Commit Graph
35125 Commits
Author SHA1 Message Date
Tran Ngoc Nhan eb9928f993 Fix Kotlin example in Spring MVC test docs
This commit updates spring-mvc-test-client.adoc to use valid Kotlin
syntax for a constructor.

Closes gh-37388

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>
2026-10-04 12:48:25 +02:00
머랭 5e45b9be1b Fix connection leak in MySQLMaxValueIncrementer
Move connection cleanup into a finally block so the connection
is closed even if commit or auto-commit restoration fails.

Closes gh-37321

Signed-off-by: cookie-meringue <daehyeon3351@gmail.com>
2026-10-03 18:36:50 +02:00
Hyunwoo Jung f03b76a53d Copy cookies in RenderingResponse.from()
Prior to this commit, RenderingResponse.from() did not copy the
cookies of the given response, unlike ServerResponse.from().

See gh-22481
Closes gh-37378

Signed-off-by: Hyunwoo Jung <hyunwoojung@kakao.com>
2026-10-03 14:14:09 +02:00
Sam Brannen d5a7fc9a9c Update exception message in HttpMessageNotReadableException
See gh-33809
2026-10-03 13:59:21 +02:00
Sébastien Deleuze c377da58d9 Make CONTRIBUTING.md self-contained and add AGENTS.md
Prior to this commit, CONTRIBUTING.md delegated build instructions
and code style to wiki pages, which are planned for removal.

This commit inlines the build, code style and testing guidelines
into CONTRIBUTING.md, aligns them with the current build and
Checkstyle rules, and documents the commit message conventions, the
security policy and the policy on AI-assisted contributions. It also
adds a concise AGENTS.md extract for coding agents, and updates the
README to link to the Build from Source section.

Closes gh-37372

Signed-off-by: Sébastien Deleuze <sdeleuze@users.noreply.github.com>
2026-10-02 16:48:13 +02:00
Rene Schakmann 23cdf8465c Clarify ConcurrentReferenceHashMap reference semantics
Prior to this commit, the Javadoc for ConcurrentReferenceHashMap
stated that soft or weak references are used for both keys and values.

However, the references are applied to the internal map entries, each
of which holds strong references to its key and value. Consequently,
an entry may be discarded even if its key and value are still strongly
reachable from elsewhere, which differs from the semantics of
WeakHashMap.

This commit revises the class-level Javadoc as well as the Javadoc for
the ReferenceType constants to document this behavior.

See gh-24253
Closes gh-37357

Signed-off-by: rene.schakmann <rene.schakmann@reetgroup.com>
2026-10-02 15:13:24 +02:00
Sam Brannen 105c39bab7 Document type support in JSP <form:input> and point to <form:password>
Prior to this commit, the reference manual mentioned that the JSP
<form:input> tag supports HTML5-specific types, but the Javadoc and
spring-form.tld did not document the `type` attribute at all, and none
of the documentation explained which types are supported or that
<form:password> must be used for password fields.

This commit updates the documentation as follows.

- Document in InputTag, spring-form.tld, and the reference manual that
  a `type` can be supplied as a dynamic attribute, that `checkbox` and
  `radio` are not supported, and that the bound value is rendered as-is.
- Add notes to InputTag, the reference manual, and spring-form.tld
  stating that <form:input type="password"> must not be used and that
  <form:password> should be used instead.
- Document in PasswordInputTag, spring-form.tld, and the reference
  manual that <form:password> does not render the bound value by default.

Closes gh-37376
2026-10-02 13:41:27 +02:00
Sam Brannen 846521d8c5 Work around Eclipse compiler type inference errors
Eclipse fails to infer the generic types in XmlEventDecoder and
DefaultWebClient, even though javac and IntelliJ IDEA compile the code
without issues.

This commit introduces explicit type arguments for the calls to
flatMapIterable() and exceptionWrappingFunction() to work around those
bugs.
2026-10-01 12:09:57 +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 043442a2a1 Test single-value to primitive array adaptation via @⁠AliasFor
This commit adds a test to MergedAnnotationsTests that verifies a
single primitive attribute in a composed annotation can be aliased via
@⁠AliasFor to a primitive array attribute in a meta-annotation.

See gh-37349
2026-09-30 13:42:35 +02:00
Chengang Guan 6afb65b225 Fix single-value adaptation for primitive array types in TypeMappedAnnotation
Prior to this commit, `adaptForAttribute(Method, Object)` created
the wrapping array from `value.getClass()` when a single non-array
value was provided for an array attribute. This worked for object
array types but failed for primitive array types: wrapping a boxed
value produced a boxed array, which then failed the compatibility
check and threw an `IllegalStateException`.

This commit derives the component type from the declared attribute
type when it is assignable from the value type, falling back to
`value.getClass()` otherwise. The existing adaptation path for
object array types is therefore preserved, and all primitive array
types now accept a single value.

The accompanying test covers single-value wrapping for every array
type declared by ArrayTypes.

Closes gh-37349

Signed-off-by: Chengang Guan <guanchengang@qq.com>
2026-09-30 13:37:25 +02:00
Sam Brannen 4d3beb5c3b Stop using Tomcat's deprecated addServletMappingDecoded() method
(cherry picked from commit 4f51801320)
2026-09-30 12:50:37 +02:00
김준형 1b4955e49f Avoid phantom keys in LinkedCaseInsensitiveMap.computeIfAbsent
computeIfAbsent registered the case-insensitive key before invoking the
mapping function. If the function returned null or threw an exception,
no mapping was recorded in the target map, but the key registration was
left behind. The map then reported containsKey(key) as true while size()
was 0, keySet() was empty, and get(key) returned null. A later insertion
with a different casing also reused the stale casing of the failed call,
since the existing-key branch resolved to the registered key.

The case-insensitive key is now only looked up up front. For a new key,
it is registered from within the mapping function once a non-null value
has been computed, which is still before the entry is inserted. A null
result or an exception therefore leaves both maps untouched, while a
removeEldestEntry override that evicts the new entry right away still
removes the registration, as it does for put. The existing-key path
keeps computing under the stored casing.

Closes gh-37351

Signed-off-by: junhyeong9812 <pickjog@gmail.com>
2026-09-30 12:47:30 +02:00
Sébastien Deleuze 06c597ed6f Use equality check for value class KClass comparison
KClass instances representing the same class are not guaranteed to be
identical, so the overridden function return type check introduced in
c39edeff15 could wrongly skip unboxing, for example when a class
implements an interface declaring the same suspending function.

See gh-37191
2026-09-30 10:23:53 +02:00
Sébastien Deleuze c39edeff15 Refine Kotlin value class contribution
Only unbox value class results when the caller expects their unboxed
representation (non-primitive underlying type, non-nullable underlying
type for nullable return types, and no overridden function with a
different return type), and add related tests.

Cache the unbox method resolution per method and make it accessible
to support non-public value classes.

Closes gh-37191
2026-09-29 16:49:17 +02:00
Dmitry Sulman c08fd24de3 Fix value class return handling for suspending AOP methods
Unbox Kotlin value class results returned from proxied suspending
methods before returning them to the caller.

Spring AOP interceptor chains expose return values as Object, which
causes Kotlin value class results to be boxed. For suspending functions,
the direct return path expects the unboxed value class representation.

Update both CglibAopProxy and JdkDynamicAopProxy to detect value class
return types and unbox boxed results after coroutine adaptation.

Add tests for suspending methods returning value classes.

See gh-37191
See gh-37155

Signed-off-by: Dmitry Sulman <dmitry.sulman@gmail.com>
2026-09-29 15:01:39 +02:00
Sam Brannen c70c434486 Recognize relocated Mockito MockAccess interface
Since Mockito 5.16.1, MockAccess moved from
org.mockito.internal.creation.bytebuddy.MockAccess to
org.mockito.internal.creation.bytebuddy.access.MockAccess.

Consequently, ProxyProcessorSupport.isInternalLanguageInterface() no
longer recognized it, causing an auto-proxied mock created with the
subclass mock maker and proxyTargetClass=false to receive a JDK proxy
that only implements MockAccess instead of a CGLIB proxy of its own
class.

This commit adds a check for the new package name alongside the
existing one, since older Mockito versions may still be on the
classpath.

Closes gh-37342
2026-09-28 18:38:07 +02:00
Tran Ngoc Nhan e19e17eca5 Add missing enclosing single quotes in Javadoc
Closes gh-37338

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>
2026-09-28 10:43:38 +02:00
Hyunwoo Jung fd23ae2393 Fix MockMvc async requests example in documentation
See gh-24103
Closes gh-37318

Signed-off-by: Hyunwoo Jung <hyunwoojung@kakao.com>
2026-09-25 17:39:02 +02:00
Brian Clozel a2e3c0d81d Skip invalid links in CssLinkResourceTransformer
Prior to this commit, both `CssLinkResourceTransformer` implementations
could fail at runtime in case of invalid CSS links (for example, with
out of bounds exceptions).

This commit skips invalid links and writes them out to the resulting CSS
without any transformation.

Fixes gh-37336
2026-09-25 17:06:28 +02:00
Sam Brannen 24645069f9 Upgrade to Gradle 9.8
Closes gh-37160
2026-09-25 16:14:12 +02:00
Brian Clozel 1cfc7f8ebc Do not perform expansion on license file 2026-09-22 22:17:57 +02:00
Brian Clozel 7be3a61a14 ResponseStatusException should not override custom reason
Prior to this commit, `ResponseStatusException` would resolve the
"detail" part of a problem detail response from message codes only
(default or custom ones). If the `reason` given as an argument to the
exception was a custom message, it would be overwritten in the process.

This commit ensures that we use custom reason messages when they don't
resolve as message codes.

Fixes gh-36984
2026-09-22 16:56:40 +02:00
Sam Brannen edd497c20f Polish Javadoc and reference documentation for caching annotations
This commit documents the semantics for the `#result` SpEL expression
variable for a method that returns a Flux for @⁠Cacheable and
@⁠CachePut, both of which have always collected such a Flux's values
into a List. For such a method, `#result` refers to that List rather
than the Flux itself.

This commit addresses a number of unrelated inconsistencies in the
documentation as well.

See gh-37309
2026-09-21 17:16: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
이태경 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
Tran Ngoc Nhan a8608e681b Remove redundant whitespace in exception messages
Closes gh-37277

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>
2026-09-20 14:58:09 +02:00
Sam Brannen 48b59dfaec Polish contribution
See gh-37305
2026-09-19 19:39:48 +02:00
Tran Ngoc Nhan b5454b1a69 Add closing braces to examples
Closes gh-37305

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>
2026-09-19 19:36:24 +02:00
Juergen Hoeller 83ecf67455 Match manifest-specified jar names with pre-encoded escape sequence
Closes gh-37280
2026-09-18 20:58:46 +02:00
Juergen Hoeller 2a15cd498a Invert findColumn fallback to try common underscore naming first
Closes gh-37297
2026-09-18 20:58:37 +02:00
Sagar Chanchal cb9ce4d9e2 Fix out-of-bounds read for truncated percent-escape in opaque host
The opaque-host percent-escape validation guard reads
input.codePointAt(i + 2) after only checking 'input.length() - i < 2',
so an input such as 'foo://%4' throws StringIndexOutOfBoundsException
instead of reporting a validation error.

Fix the bounds guard to require two code points after '%' and check
ASCII hex digits rather than ASCII digits, matching the URL spec, where
invalid percent-escapes in opaque hosts are validation errors, not
failures.

Signed-off-by: Sagar Chanchal <Sagarr2112@gmail.com>
2026-09-18 17:26:03 +02:00
Sam Brannen 2aa36fea64 Polish contribution
See gh-37005
2026-09-18 16:48:27 +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
guanchengang b49252ed66 Avoid useless queue ops in ConcurrentLruCache.clear()
ConcurrentLruCache.clear() previously drained write operations before
cleaning up the cache. This could re-enqueue nodes that clear() was
about to remove, causing useless evictionQueue operations. Now clear()
iterates the cache values directly, removes and marks nodes as removed
first, and drains write operations afterward. Since AddTask fails
silently after a node is marked removed, this avoids the no-op work
and improves performance.

See gh-37287

Closes gh-37292

Signed-off-by: Chengang Guan <guanchengang@qq.com>
2026-09-18 15:53:18 +02:00
Brian Clozel 5d32f6719a Fix flaky test in RetryTemplateTests
`RetryTemplateTests` can, under load, break the build because of a flaky
test: "retryableWithTimeoutExceededAfterSecondRetry".
This usually happens when many cores are busy and the timeout check
runs before each retry attempt.
This commit extends the timeout to avoid such cases and failures.
2026-09-18 14:05:38 +02:00
Brian Clozel 8107a2b561 Polishing contribution
See gh-37285
2026-09-17 16:48:59 +02:00
seonghun lee 94afeedad6 Enforce disk usage limit when spilling part to disk
Previously, PartGenerator only enforced maxDiskUsagePerPart for body
buffers that arrived after a part had switched to file storage. The
content accumulated in memory that triggered the switch was written
to disk without any check against maxDiskUsagePerPart. As a result,
a part whose last body buffer caused the in-memory overflow was
accepted in full, even when its total size exceeded the configured
disk usage limit.

This commit checks the accumulated byte count against
maxDiskUsagePerPart before switching to file storage, and emits a
DataBufferLimitException, consistent with the existing check for
subsequent buffers.

Closes gh-35099

Signed-off-by: seonghun lee <harrisleesh@gmail.com>
2026-09-17 16:48:59 +02:00
Sam Brannen bb7ea37f1b Drain pending writes before evicting in ConcurrentLruCache.clear()
Prior to this commit, clear() polled the eviction queue to remove
entries and only afterward drained the pending write operations queue.

Consequently, a put() whose AddTask had not yet been linked into the
eviction queue -- for example, because it lost the race to self-drain
while clear() held the eviction lock -- would only be applied by that
trailing drain, linking the entry into the eviction queue right after
clear() had already finished removing everything it could see.

The practical effect was that an entry already fully added to the cache
could still be present immediately after clear() returned, with no
further concurrent activity required at that point.

To address that, this commit revises clear() so that it drains the
pending write operations queue before polling the eviction queue, so
any write that was already queued gets cleaned up along with everything
else. However, a put() that is genuinely concurrent with an in-progress
clear() call can still survive, which is consistent with the cache's
weak-consistency design.

Thanks to @guanchengang for raising gh-37286, which prompted this fix.

Closes gh-37287
2026-09-17 12:45:42 +02:00
Brian Clozel 9e0d1c734e Upgrade to artifactory-deploy-action 0.0.5 2026-09-15 10:06:11 +02:00
Sam Brannen 3178df92bd Consistently use while (true) instead of for (;;) across the codebase 2026-09-14 18:15:02 +02:00
김준형 c1aa1b7405 Prevent double size decrement in ConcurrentLruCache
markAsRemoved() transitions a node to the removed state and decrements
the current size, but it did not check whether the node had already
been removed. The eviction path and an explicit removal can process
the same node in sequence: when a write drain runs a queued AddTask
whose eviction polls a node that a concurrent remove(K) has already
taken out of the cache, the eviction decrements the size, and the
queued RemovalTask for the same node decrements it again. The sibling
transition markForRemoval() guards against invalid transitions; this one
did not.

Each extra decrement makes currentSize permanently smaller than the
number of cached entries, so eviction stops triggering and the cache
exceeds its capacity for good, silently. A bounded two-thread stress
run accumulates the drift reliably: before the change the cache
stabilized far above its capacity in 20 out of 20 runs.

markAsRemoved() now returns without decrementing when the entry is
already in the removed state, mirroring the guard in markForRemoval().
The removed state is terminal, so each node is counted down exactly
once. The new test races explicit removals against eviction and then
verifies that the cache converges back to its capacity; it also
asserts that the racing thread ran and terminated cleanly.

Closes gh-37268

Signed-off-by: junhyeong9812 <pickjog@gmail.com>
2026-09-14 18:06:47 +02:00
Sam Brannen 8c1b366bda Polish contribution
See gh-37261
2026-09-14 17:38:39 +02:00
guanchengang d571c4097d Lazily handle setClientInfo/setNetworkTimeout in LazyConnectionDataSourceProxy
This commit extends LazyConnectionInvocationHandler to cache early
calls to:

- setClientInfo(String, String)
- setNetworkTimeout(Executor, int)

These methods now defer physical connection acquisition until Statement
creation, consistent with existing lazy behavior for autoCommit,
readOnly, transactionIsolation, catalog, and schema.

We also accept and lazily cache calls to setNetworkTimeout() even when
the provided Executor is null. Since some JDBC driver implementations
completely ignore the Executor parameter (or fall back to a default
executor), we cannot meaningfully validate or handle a null Executor
before the physical connection is obtained.

getClientInfo() and getClientInfo(String) remain non-lazy (triggering
immediate connection fetch), because they are read operations whose
values cannot be reliably cached due to driver defaults, pooled
connection remnants, or external session modifications.

setClientInfo(Properties) also remains non-lazy. The reason is that JDBC
driver implementations are inconsistent. Some treat it as overwrite,
others as append/merge. To guarantee behavior identical to non-lazy
execution across all drivers, we choose not to cache or replay it,
avoiding any risk of semantic mismatch.

See gh-37258
Closes gh-37261

Signed-off-by: Chengang Guan <guanchengang@qq.com>
2026-09-14 17:31:37 +02:00
Juergen Hoeller 803517c0cb Upgrade to Tomcat 11.0.25, Jetty 12.1.13, Netty 4.2.18, Protobuf 4.36.1 2026-09-14 15:55:16 +02:00
Juergen Hoeller 8a511726cd Consistent JPA/Hibernate transaction interoperability
Closes gh-37273
2026-09-14 15:54:43 +02:00
Hyunwoo Jung 4898ed3ad8 Fix message supplier coverage in AssertTests
Closes gh-37255

Signed-off-by: Hyunwoo Jung <hyunwoojung@kakao.com>
2026-09-14 15:01:52 +02:00
Sam Brannen f768641c08 Polish contribution
See gh-37254
2026-09-14 14:50:45 +02:00
Hyunwoo Jung 01a23e32b5 Fix CollectionToCollectionConverterTests
Closes gh-37254

Signed-off-by: Hyunwoo Jung <hyunwoojung@kakao.com>
2026-09-14 14:41:06 +02:00
Hyunwoo Jung 9d1156f1fd Avoid redundant filtering in FilteredMap.size()
Since keySet() already applies the filter, size() evaluated the
predicate twice for every accepted key.

This commit uses delegate.keySet() instead, avoiding the second
evaluation as well as a FilteredSet and FilteredIterator allocation.

Closes gh-37256

Signed-off-by: Hyunwoo Jung <hyunwoojung@kakao.com>
2026-09-14 14:31:42 +02:00