The error message in such cases now indicates that the retry process
is being aborted preemptively due to pending sleep time.
For example:
Retry policy for operation 'myMethod' would exceed timeout (5 ms) due
to pending sleep time (10 ms); preemptively aborting execution
See gh-35963
Specifically, this commit introduces:
- timeout and timeoutString attributes in @Retryable
- a default getTimeout() method in RetryPolicy
- a timeout() method in RetryPolicy.Builder
- an onRetryPolicyTimeout() callback in RetryListener
- support for checking exceeded timeouts in RetryTemplate (also used
for imperative method invocations with @Retryable)
- support for checking exceeded timeouts in reactive pipelines with
@Retryable
Closes gh-35963
This commit revises the type-level nullability declaration in
ConvertingComparator in order to adapt to recent nullability changes in
Converter.
This commit also revises the workaround in commit 53d9ba879d.
See gh-35947
Add warnings to the class-level Javadoc for MergedAnnotations,
AnnotatedTypeMetadata, AnnotationMetadata, and MethodMetadata to point
out that annotations may be ignored if their attributes reference types
that are not present in the classpath.
Closes gh-35959
Allow defining converters that return non-null values by
leveraging flexible generic type level nullability in
org.springframework.core.convert.converter.Converter.
Closes gh-35947
In contrast to the previous commit, a warning similar to the following
is now logged in such cases.
WARN o.s.c.a.MergedAnnotation -
Failed to introspect meta-annotation @MyAnnotation on class
example.Config: java.lang.TypeNotPresentException:
Type example.OptionalDependency not present
See gh-35927
Prior to this commit, if a meta-annotation could not be loaded because
its attributes referenced types not present in the classpath, the
meta-annotation was silently ignored.
To improve diagnostics for such use cases, this commit introduces WARN
support in IntrospectionFailureLogger and revises AttributeMethods.canLoad()
to log a warning if a meta-annotation is ignored due to an exception
thrown while attempting to load its attributes.
For example, a warning similar to the following is now logged in such
cases.
WARN o.s.c.a.MergedAnnotation -
Failed to introspect meta-annotation @example.MyAnnotation on class
example.Config: java.lang.TypeNotPresentException:
Type example.OptionalDependency not present
This commit also improves log messages in AnnotationTypeMappings.
Closes gh-35927
For defensiveness against a singletonInstance/initialized visibility mismatch, we accept the locking overhead for pre-initialized null values (where we need the initialized field) in favor of a defensive fast path for non-null values (where we only need the singletonInstance field).
Closes gh-35905
This commit refines BindingReflectionHintsRegistrar with additional
dynamic hints for application-defined types, main core Java conversion
ones being already covered by ObjectToObjectConverterRuntimeHints.
Closes gh-35847
Read the respective fields only once in the values(), entrySet(), and
keySet() methods.
Closes gh-35822
Signed-off-by: Patrick Strawderman <pstrawderman@netflix.com>
The Spliterators returned by values, entrySet, and keySet incorrectly
reported the SIZED characteristic, instead of CONCURRENT. This could
lead to bugs when the map is concurrently modified during a stream
operation.
For keySet and values, the incorrect characteristics are inherited from
AbstractMap, so to rectify that the respective methods are overridden,
and custom collections are provided that report the correct Spliterator
characteristics.
Closes gh-35817
Signed-off-by: Patrick Strawderman <pstrawderman@netflix.com>
This commit introduces a KotlinDetector#hasSerializableAnnotation
utility method designed to detect types annotated with
`@Serializable` at type or generics level.
See gh-35761
Prior to this commit, the maximum number of retry attempts was
configured via @Retryable(maxAttempts = ...),
RetryPolicy.withMaxAttempts(), and RetryPolicy.Builder.maxAttempts().
However, this led to confusion for developers who were unsure if
"max attempts" referred to the "total attempts" (i.e., initial attempt
plus retry attempts) or only the "retry attempts".
To improve the programming model, this commit renames maxAttempts to
maxRetries in @Retryable and RetryPolicy.Builder and renames
RetryPolicy.withMaxAttempts() to RetryPolicy.withMaxRetries(). In
addition, this commit updates the documentation to consistently point
out that total attempts = 1 initial attempt + maxRetries attempts.
Closes gh-35772
This commit ensures that both `VirtualThreadDelegate` implementations
expose the same public API. If not, JAR verification fails with the
following message:
```
jar --validate --file spring-core-6.2.13-SNAPSHOT.jar
entry: META-INF/versions/21/org/springframework/core/task/VirtualThreadDelegate.class, contains a class with different api from earlier version
```
Fixes gh-35773
When JAR manifest Class-Path entries contain absolute paths (as Gradle
creates on Windows for long classpaths), PathMatchingResourcePatternResolver
incorrectly rejected them.
Fixes#35730
Signed-off-by: Artur Signell <artur@vaadin.com>
When concurrency limiting is enabled via setConcurrencyLimit() and
thread creation fails in doExecute() (e.g., OutOfMemoryError from
Thread.start()), the concurrency permit acquired by beforeAccess()
is never released because TaskTrackingRunnable.run() never executes.
This causes the concurrency count to permanently remain at the limit,
causing all subsequent task submissions to block forever in
ConcurrencyThrottleSupport.onLimitReached().
Root cause:
- beforeAccess() increments concurrencyCount
- doExecute() throws Error before thread starts
- TaskTrackingRunnable.run() never executes
- afterAccess() in finally block never called
- Concurrency permit permanently leaked
Solution:
Wrap doExecute() in try-catch block in the concurrency throttle path
and call afterAccess() in catch block to ensure permit is always
released, even when thread creation fails.
The fix only applies to the concurrency throttle path. The
activeThreads-only path does not need fixing because it never calls
beforeAccess(), so there is no permit to leak.
Test approach:
The test simulates thread creation failure and verifies that a
subsequent execution does not deadlock. The first execution should
fail with some exception (type doesn't matter), and the second
execution should complete within timeout if the permit was properly
released.
Signed-off-by: Park Juhyeong <wngud5957@naver.com>