While assessing #35195, I noticed the following issues with our
Checkstyle configuration regarding nullability annotations.
- "^(?!org\.jspecify|\.annotations).*(NonNull|Nullable)$" contains a "|".
- "^(?!org\.jspecify|\.annotations).*(NonNull|Nullable)$" matches against
NonNull but not against Nonnull, and therefore incorrectly permits
usage of javax.annotation.Nonnull.
- Some of the Checkstyle suppressions no longer apply.
This commit addresses all of the above issues and updates several tests
to use example annotations other than javax.annotation.Nonnull where
feasible.
See gh-35195
Closes gh-35205
If an application depends on automatic type conversion from
java.time.Instant to java.sql.Timestamp, the ObjectToObjectConverter
performs the conversion based on convention, by using reflection to
invoke Timestamp.from(Instant).
However, when running in a native image a user needs to explicitly
register runtime hints for that particular use of reflection.
To assist users who are running their applications in a native image,
this commit automatically registers the necessary runtime hints for
Timestamp.from(Instant) so that users do not have to.
See gh-35175
Closes gh-35156
In order to avoid unnecessary use of reflection and to simplify native
image deployments, this commit introduces explicit support for
automatic conversions from java.util.Date to java.time.Instant and vice
versa.
To achieve that, this commit introduces an InstantToDateConverter and a
DateToInstantConverter and registers them automatically in
DefaultConversionService.
See gh-35156
Closes gh-35175
This commit leverages flexible generics nullness at method and
type level when relevant in spring-jdbc.
Due to https://github.com/uber/NullAway/issues/1075, some related
`@SuppressWarnings("NullAway")` have been added.
JdbcOperations Kotlin extensions have been refined accordingly.
Closes gh-34911
In commit 97522cfa36, I implemented a
short-circuiting matching algorithm in DefaultRetryPolicy for includes
and excludes, which was later copied to MethodRetrySpec.
After we switched to using ExceptionTypeFilter, I realized that the
matching algorithm in InstanceFilter (the superclass of
ExceptionTypeFilter) does not exhibit the same short-circuiting
characteristics.
In light of that, this commit revises the matching algorithm in
InstanceFilter to mirror the original short-circuiting algorithm in
DefaultRetryPolicy.
See gh-35058
See gh-35109
See gh-35160
Closes gh-35161
Prior to this commit, ExceptionTypeFilter only supported matching
against an exception type. However, most use cases involve matching
against an exception instance. Moreover, every use case within the core
Spring Framework uses ExceptionTypeFilter to match against concrete
exception instances.
This commit therefore introduces an overloaded match(Throwable) method
in ExceptionTypeFilter in order to provide support for the most common
use cases.
See gh-35109
Closes gh-35160
Prior to this commit, the constructors for InstanceFilter and
ExceptionTypeFilter required one to supply the matchIfEmpty flag.
However, users will typically want that to be true. Moreover, we always
supply true for the matchIfEmpty flag within the Spring Framework.
This commit therefore makes the matchIfEmpty flag optional by
introducing overloaded constructors for InstanceFilter and
ExceptionTypeFilter that only accept the includes and excludes
collections.
In addition, this commit overhauls the Javadoc for InstanceFilter and
ExceptionTypeFilter, fixing several issues in the documentation.
Furthermore, this commit applies consistent @Nullable declarations
in ExceptionTypeFilter.
Closes gh-35158
Prior to this commit, the value attribute in @Contract was declared as
follows.
String value() default "";
That allowed empty declarations such as @Contract or @Contract();
however, a contract is not useful without declared constraints.
To address that, this commit removes the `default ""` declaration in
order to force users to provide explicit constraints.
Although one could technically still declare the annotation without
constraints via @Contract(""), it's unlikely that anyone would
intentionally do that.
Closes gh-35157
This commit reduces code duplication by reusing the logic already
available in ExceptionTypeFilter.
Closes gh-35109
Signed-off-by: Mengqi Xu <2663479778@qq.com>
When the core retry functionality was introduced, it had a built-in
MaxRetryDurationPolicy. In #35058, that was migrated to a
withMaxDuration() factory method, and in #35110 that was renamed to
withMaxElapsedTime() (with a corresponding maxElapsedTime() method on
the builder) in order to align with the maxElapsedTime feature of
ExponentialBackOff. The latter also changed the semantics of the
feature in the context of the RetryPolicy.
However, @Retryable does not provide maxElapsedTime support.
In addition, the maxElapsedTime feature is a bit misleading, since it
does not actually track CPU time or wall-clock time but rather only the
sum of individual, accumulated back-off intervals/delays, which is
likely not very useful. Furthermore, the maxElapsedTime will never
apply to a zero-valued delay/interval.
In light of the above, this commit removes the maxElapsedTime support
from the built-in RetryPolicy.
Users can still implement a custom BackOff strategy if they find they
need some form of "max elapsed time" or "max duration".
See gh-34716
See gh-35058
See gh-34529
See gh-35110
Closes gh-35144
Update `SpringFactoriesLoader` so that the cache stores only the
factories and not the complete loader.
Prior to this commit, if a cache entry was added with the thread
context classloader, the loader instance would be added and the
classloader stored. If the thread context classloader subsequently
changes, and a call is made to `forDefaultResourceLocation` with
`null` for the classloader, the cached entry would be used which
contains the older classloader.
Closes gh-34732
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to runDetails
Build and Deploy Snapshot / Verify (push) Blocked by required conditionsDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:ubuntu-latest name:Linux]) (push) Waiting to runDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:21], map[id:ubuntu-latest name:Linux]) (push) Waiting to runDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:23], map[id:ubuntu-latest name:Linux]) (push) Waiting to runDetails
Deploy Docs / Dispatch docs deployment (push) Waiting to runDetails
This commit simplifies our dependency management for JUnit artifacts by
making use of the junit-jupiter and junit-platform-suite aggregator
artifacts.
Closes gh-35127
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to runDetails
Build and Deploy Snapshot / Verify (push) Blocked by required conditionsDetails
Deploy Docs / Dispatch docs deployment (push) Waiting to runDetails
After experimenting with our newly introduced core retry support
(RetryPolicy, RetryTemplate, etc.) and @Retryable support, it
became apparent that there are overlapping concerns between the current
RetryPolicy and BackOff contracts.
- RetryPolicy and BackOff both have stateful executions: RetryExecution
and BackOffExecution. However, only one stateful execution is
necessary.
- FixedBackOff and ExponentialBackOff already incorporate "retry" logic
in terms of max attempts, max elapsed time, etc. Thus, there is no
need to duplicate such behavior in a RetryPolicy and its
RetryExecution.
- RetryTemplate currently accepts both a RetryPolicy and a BackOff in
order to instrument the retry algorithm. However, users would
probably rather focus on configuring all "retry" logic via a single
mechanism.
In light of the above, this commit directly incorporates BackOff
in RetryPolicy as follows.
- Remove the RetryExecution interface and move its shouldRetry() method
to RetryPolicy, replacing the current RetryExecution start() method.
- Introduce a default getBackOff() method in the RetryPolicy interface.
- Introduce RetryPolicy.withDefaults() factory method.
- Completely overhaul the RetryPolicy.Builder to provide support for
configuring a BackOff strategy.
- Remove BackOff configuration from RetryTemplate.
- Revise the method signatures of callbacks in RetryListener.
The collective result of these changes can be witnessed in the
reworked implementation of AbstractRetryInterceptor.
RetryPolicy retryPolicy = RetryPolicy.builder()
.includes(spec.includes())
.excludes(spec.excludes())
.predicate(spec.predicate().forMethod(method))
.maxAttempts(spec.maxAttempts())
.delay(Duration.ofMillis(spec.delay()))
.maxDelay(Duration.ofMillis(spec.maxDelay()))
.jitter(Duration.ofMillis(spec.jitter()))
.multiplier(spec.multiplier())
.build();
RetryTemplate retryTemplate = new RetryTemplate(retryPolicy);
See gh-34716
See gh-34529
See gh-35058
Closes gh-35110
gh-33616 refactored `CachingMetadataReaderFactory` and broke the
behavior as it bypassed the cache for `getMetadataReader(String
className)` operations.
This commit restores the original behavior.
Fixes gh-35112