Commit Graph
2001 Commits
Author SHA1 Message Date
Sam Brannen 9289f71ad7 Merge branch '7.0.x' 2026-09-30 17:14:52 +02:00
Sam Brannen 3a600481d2 Polish code base
- Remove redundant super() calls from constructors
- Add missing @⁠Override annotations
- Use switch rules in JdkClientHttpRequest and RfcUriParser
- Use instanceof pattern matching
- Use method references instead of trivial lambda expressions
- Use lambda expressions instead of anonymous inner classes
- Remove unused code and redundant semicolons
- Use braces with if-blocks
2026-09-30 17:08:47 +02:00
Sam Brannen 804e491eda Merge branch '7.0.x' 2026-09-21 17:25:43 +02:00
Sam Brannen 26de340102 Stop truncating Flux results to first element with @⁠CacheEvict
Prior to this commit, ReactiveCachingHandler.processCacheEvicts()
adapted every reactive return value via Mono.from(), which subscribes
for only the first element and cancels the upstream Publisher. For a
@⁠CacheEvict method that returns a Flux, this silently truncated the
returned sequence to its first element. In addition, the `#result`
variable in `condition` SpEL expressions was bound to only that first
emitted element.

To address that, this commit mirrors the existing multi-value handling
in processPutRequest(). When the adapter reports isMultiValue(), a side
Subscriber is subscribed via publish().refCount(2) that exhausts the
Flux and collects its values into a List for eviction, while the
original, unmodified Flux is returned to the caller. Consequently, the
`#result` variable in `condition` SpEL expressions for a Flux-returning
@⁠CacheEvict method is now the full List of emitted elements rather
than just the first element, making it consistent with @⁠Cacheable and
@⁠CachePut.

This commit also improves spr14235AdaptsToReactorFlux() in
CacheReproTests. Previously it exercised @⁠CacheEvict only with a
single-element Flux and never asserted on the returned sequence. Now it
uses a multi-element Flux and verifies that all elements are both
returned to the caller and visible to the `condition` expression.

Last but not least, this commit documents the aforementioned
`#result`/Flux semantics in @⁠CacheEvict's Javadoc and in the reference
manual, since both were previously invalid or incomplete for this
scenario.

Closes gh-37309
2026-09-21 17:16:34 +02:00
Sam Brannen 8a742e4b48 Merge branch '7.0.x' 2026-09-20 16:34:37 +02:00
이태경 9637d12785 Fix target-class counter assertions in AOP tests
Both target-class tests asserted the target-interface counter,
leaving the intended pointcut unchecked. Assert the target-class
counter in both the XML and @⁠AspectJ variants.

Closes gh-37310

Signed-off-by: itaekyung <taeyun1411@gmail.com>
2026-09-20 16:34:09 +02:00
Brian Clozel b6d7f1d586 Avoid duplicate date-related converters registration
Prior to this commit, `DefaultFormattingConversionService` would
register converters with both `DateTimeFormatterRegistrar` and
`DateFormatterRegistrar`, the former also registering the legace date
converters that the latter contributes.

While we cannot change the behavior for `DateTimeFormatterRegistrar` or
`DateFormatterRegistrar` because of their public contract, we can update
the `DefaultFormattingConversionService` to not use
`DateFormatterRegistrar` and register manually the annotation support
that it contributes.

Closes gh-36951
2026-09-19 12:12:10 +02:00
Sam Brannen 6f4021ad87 Merge branch '7.0.x' 2026-09-18 16:37:49 +02:00
flinter fc10d200bf Document combining @⁠Retryable with proxy-based features
Add a "Combining @⁠Retryable with Other Proxy-Based Features" section
to the resilience reference documentation, covering interaction with
@⁠Transactional, @⁠Cacheable, and @⁠Async, as well as advice order
customization between @⁠Retryable and @⁠Async via
@⁠EnableResilientMethods(order) and @⁠EnableAsync(order).

Also document the advice chain semantics in @⁠Retryable Javadoc, add
cross-reference TIP blocks in the @⁠Async, @⁠Cacheable, and
@⁠Transactional reference sections, add a @⁠Cacheable combination test
to RetryInterceptorTests, and add RetryableTransactionTests in
spring-tx for the @⁠Transactional combination.

See gh-35584
Closes gh-37005

Signed-off-by: jhan0121 <jhan0121@gmail.com>
2026-09-18 16:37:25 +02:00
Brian Clozel cd110ad14e Use PropertyPath instead of utility methods
Prior to this commit, `DataBinder` and the property accessor
hierarchy relied on `PropertyAccessorUtils` and several
independent scanners for property paths.
This commit migrates all of them to `PropertyPath`, so
there is exactly one parser deciding what a well-formed property
path is, used identically for policy checks and for actual
navigation.

This removes long standing protected methods like
A`getPropertyAccessorForPropertyPathi` and `getFinalPath` from
`bstractNestablePropertyAccessor`. The path is now parsed exactly
once per public entry point, via the new `resolvePropertyPath`, which
returns a `ResolvedProperty`. Then, property navigation walks
the parsed segment list rather than re-scanning partial strings.
Any subclass overriding the removed method will need to adapt.

This removal initially conflicted with gh-37252 (maxNestedPathDepth
support). The public configuration remains but the actual behavior
changed; it is replaced with `PropertyPath.Options` which enforces
limit right after parsing, before property navigation begins.
The exception thrown changes from `InvalidPropertyException` to
`InvalidPropertyPathException`.

This commmit also reverts the `map[']` / `map["]` quoting behavior
from gh-36765 as it is incompatible with the new grammar.

See gh-37275
2026-09-17 15:37:40 +02:00
Sam Brannen 8ab525f6f0 Add a configurable limit for maximum nested property path depth
AbstractNestablePropertyAccessor resolves a nested property path
recursively, one recursive call per path segment, and there was
previously no limit on the nesting depth. Consequently, a sufficiently
deeply nested property path -- for example, against a self-referential
type -- could exhaust the current thread's call stack, resulting in a
StackOverflowError which lacks useful diagnostics for developers
attempting to assess what went wrong.

Note that the existing autoGrowCollectionLimit bounds array and
collection growth, not path depth.

The same is true for constructor binding via DataBinder.construct(),
which constructs a nested constructor argument recursively through a
nested property path. Path segments are constrained to declared
constructor parameters there, but a self-referential type nonetheless
permits an arbitrarily deep path.

With this commit, each property accessor tracks the number of nested
properties traversed to reach the object that it wraps, and an
InvalidPropertyException is thrown once the configured (or default)
maxNestedPathDepth limit is exceeded, with a message that reports the
configured limit. The limit applies regardless of autoGrowNestedPaths,
since resolving an existing deep object graph recurses in the same
manner as auto-growing one. Tracking the depth per property accessor
rather than threading it through the recursion allows the recursion to
dispatch through the protected
getPropertyAccessorForPropertyPath(String) method, which subclasses may
override, and avoids deriving the depth from the nested path, which
would require rescanning an ever longer path prefix at each level.

Constructor binding likewise tracks the nesting depth while
constructing nested objects as well as indexed and mapped elements, and
throws the same InvalidPropertyException once the limit is exceeded.

The maxNestedPathDepth (which defaults to 100) can be configured on a
per-use-case basis via ConfigurablePropertyAccessor or DataBinder,
which applies it to constructor binding directly and supplies it to the
property accessor via its binding result. In contrast to the auto-grow
collection limit, which is unlimited on a plain accessor, the nesting
depth is bounded by default even for programmatic property access,
since a large array or collection can be perfectly legitimate whereas a
deeply nested property path effectively never is.

Specifying zero for the maxNestedPathDepth disables support for nested
property paths altogether while continuing to allow simple, indexed,
and mapped property access, which is a reasonable way to constrain data
binding for a target object that is not intended to be traversed (such
as a flat DTO). However, negative values for maxNestedPathDepth are
always rejected.

Closes gh-37252
2026-09-16 17:52:04 +02:00
Yanming Zhou 74a6c1c328 Fix BeanFactory.getBean(String, ParameterizedTypeReference) to respect AOP proxy
Before this commit, the implementation uses `ResolvableType::isInstance` which doesn't take JDK proxy into account, it fails if `proxyTargetClass = false`:

```
Bean named 'userDao' is expected to be of type 'org.springframework.cache.config.ExpressionCachingIntegrationTests$BaseDao<org.springframework.cache.config.ExpressionCachingIntegrationTests$User>' but was actually of type 'org.springframework.cache.config.$Proxy53'
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'userDao' is expected to be of type 'org.springframework.cache.config.ExpressionCachingIntegrationTests$BaseDao<org.springframework.cache.config.ExpressionCachingIntegrationTests$User>' but was actually of type 'org.springframework.cache.config.$Proxy53'
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:212)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1312)
	at org.springframework.cache.config.ExpressionCachingIntegrationTests.expressionIsCacheBasedOnActualMethod(ExpressionCachingIntegrationTests.java:42)
```

See gh-34687
Closes gh-37047

Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
2026-09-14 15:57:07 +02:00
Juergen Hoeller 354ade9f40 Merge branch '7.0.x' 2026-08-29 20:02:43 +02:00
Juergen Hoeller 3656241ff1 Use singleton target as cache key for destruction purposes
Closes gh-37207
2026-08-29 20:01:40 +02:00
Sam Brannen a00fb1b5ae Avoid redundant object construction in DataBinder.createMap()
Previously, createMap() invoked createIndexedValue() – and therefore
createObject() for non-simple value types – once per matching parameter
name rather than once per distinct map key, causing redundant nested
object construction for map entries whose value type has multiple
constructor parameters.

To address that, this commit aligns createMap() with createList() and
createArray() by skipping construction for keys that have already been
resolved.

Closes gh-37019
2026-08-26 13:34:57 +02:00
Sam Brannen daa8c10031 Polish contribution
See gh-36556
2026-08-18 18:17:57 +02:00
Vedran Pavic 7da47f8c47 Simplify programmatic scheduling of cron tasks with time zone
This commit adds an overloaded `addCronTask()` method to `ScheduledTaskRegistrar`
that allows simpler scheduling of cron tasks with non-default time zones.

Closes gh-36556

Signed-off-by: Vedran Pavic <vedran@vedranpavic.com>
2026-08-18 18:14:01 +02:00
jhan0121 4bcae5305d Deprecate setDisallowedFields in DataBinder
Closes gh-36816
Signed-off-by: Juhwan Lee <jhan0121@gmail.com>
2026-07-29 16:17:09 +03:00
Juergen Hoeller 40f7d56ed4 Register original bean name as alias if not taken already
Closes gh-37038
2026-07-16 10:45:16 +02:00
Juergen Hoeller c4c0a84f83 Merge branch '7.0.x' 2026-07-16 10:20:53 +02:00
Juergen Hoeller 56d706d591 Skip concurrency limit tests when common pool parallelism is too low 2026-07-16 10:17:29 +02:00
Sam Brannen bb34bf6dc6 Merge branch '7.0.x' 2026-06-27 18:09:31 +02:00
Sam Brannen 78f05d8f8e Address deprecation warnings
This commit addresses warnings across the code base related to:

- internal and public deprecations in Spring Framework
- deprecated Locale constructors
- deprecated URL constructors
- deprecated Thread#getId method
2026-06-27 18:08:53 +02:00
Sam Brannen 94db4f7f7a Merge branch '7.0.x' 2026-06-17 11:56:51 +02:00
Yanming Zhou 0fc724b348 Make inner classes in tests static where feasible
Closes gh-36939

Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
2026-06-17 11:49:12 +02:00
Sam Brannen e23971efb9 Merge branch '7.0.x' 2026-06-05 15:15:19 +02:00
Sam Brannen 6ca66afc7b Polish contribution
See gh-36871
2026-06-05 15:13:25 +02:00
zhaomeng 1b32d8d41d Include zone ID in CronTrigger's equals() and hashCode() implementations
CronTrigger carries an optional ZoneId since 5.3 that affects
nextExecution; however, prior to this commit, equals() and hashCode()
only considered the cron expression.

This commit ensures that CronTrigger instances with the same cron
expression but different time zones are no longer considered equal.

Closes gh-36871

Signed-off-by: zhaomeng <zhaomeng1.vendor@sensetime.com>
2026-06-05 15:09:14 +02:00
Brian Clozel 9b8a851969 Merge branch '7.0.x' 2026-06-04 10:49:36 +02:00
Brian Clozel 6467fca05b Polishing contribution
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
2026-06-04 10:22:23 +02:00
arnoandCursor cddc671a8c Fix CronExpression day skip on midnight DST gap
After rollForward, BitsCronField always searched for the next
matching bit from zero. When daylight saving creates a gap at
the start of a period (e.g. Africa/Cairo), the temporal lands on
a non-zero field value and matching from zero could advance an
entire period too far, skipping the calendar day.

Search from the actual field value in the new period instead,
falling back to zero only when no bit matches in that period.

See gh-36865

Signed-off-by: arno <me@zmovo.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 10:22:17 +02:00
Matthias Kurz 481a5743b3 Apply auto-grow limit to direct field binding
DataBinder applies its auto-grow collection limit to bean
property access, but direct field access left DirectFieldAccessor
at its default limit.

Pass DataBinder's configured limit into DirectFieldBindingResult
and apply it to the DirectFieldAccessor.

Closes gh-36861

Signed-off-by: Matthias Kurz <m.kurz@irregular.at>
2026-06-02 16:58:47 +02:00
Juergen Hoeller 00ca23859e Merge branch '7.0.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
2026-05-27 16:35:51 +02:00
Juergen Hoeller af2b96192d Force initialization of configuration class in mainline thread
Closes gh-36844
2026-05-27 16:32:37 +02:00
Juergen Hoeller 121c0ac285 Remove scanned class only when conflicting with imported class
Closes gh-36835
2026-05-27 16:31:13 +02:00
Juergen Hoeller 1b26f5d1e6 Adapt bean overriding test for deferred BeanRegistrar processing in 7.1
See gh-36648
See gh-21497
2026-04-30 14:33:55 +02:00
Juergen Hoeller 6ff2d187cf Merge branch '7.0.x'
# Conflicts:
#	spring-context/src/test/java/org/springframework/context/support/GenericApplicationContextTests.java
2026-04-30 14:21:49 +02:00
Juergen Hoeller 08c5280843 Consistent wrapping of BeanCreationExceptions from instance suppliers
Includes tests for circular references and bean definition overrides.

Closes gh-36725
See gh-36648
2026-04-30 14:19:25 +02:00
Sam Brannen 0e1a2b4f87 Merge branch '7.0.x' 2026-04-27 14:01:51 +03:00
Yanming Zhou bfb88cfc1c Remove unnecessary invocations of toString()
Closes gh-36709

Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
2026-04-27 11:27:29 +03:00
Juergen Hoeller 623bdfb677 Merge branch '7.0.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
2026-04-08 13:43:25 +02:00
Juergen Hoeller 0150c4ba06 Avoid MessageFormat rendering for exception messages in binding errors
Closes gh-36609
2026-04-08 13:39:10 +02:00
Sébastien Deleuze 2ee4c3a363 Provide bean conditional registration capabilities in BeanRegistrarDsl
Closes gh-36601
2026-04-05 18:49:07 +02:00
Sam Brannen 4709f68446 Merge branch '7.0.x' 2026-04-02 18:40:08 +02:00
Sam Brannen 1ead8bf1ab Polishing 2026-04-02 18:39:37 +02:00
Sam Brannen fd50c0841c Merge branch '7.0.x' 2026-04-02 16:55:02 +02:00
Sam Brannen 00fbd91cca Skip annotations that cannot be processed in AnnotationBeanNameGenerator
Prior to this commit, AnnotationBeanNameGenerator failed when searching
for a convention-based bean name, if an annotation referenced a
non-existent class.

To address that, this commit introduces a try-catch block around each
invocation of MergedAnnotation.asAnnotationAttributes() and skips
processing of the current MergedAnnotation if an exception occurs,
which is likely due to a type referenced from an annotation attribute
not being present in the classpath.

See gh-31203
Closes gh-36524
2026-04-02 16:51:17 +02:00
Sam Brannen 596c0df826 Merge branch '7.0.x' 2026-04-02 12:45:50 +02:00
Sam Brannen b6fc3a1b6f Enforce use of AssertJ assumptions via Checkstyle
Closes gh-36582
2026-04-02 12:43:12 +02:00
Stéphane Nicoll d5b6f4a7ee Polish BeanRegistrar Javadoc and add tests for non-invocation semantics
Revise the BeanRegistrar Javadoc to document the two distinct usage
modes: @Configuration/@Import and programmatic GenericApplicationContext
setup.

Clarify that implementations are not Spring components (requiring a
no-arg constructor and no dependency injection), and detail the ordering
guarantees for each mode.

Add missing tests

Signed-off-by: Stéphane Nicoll <stephane.nicoll@broadcom.com>
2026-04-02 11:18:58 +02:00