Compare commits

..

694 Commits

Author SHA1 Message Date
Spring Builds 8c85c3166c Release v5.3.31 2023-11-16 08:00:15 +00:00
Juergen Hoeller b28a5f858c Upgrade to Reactor 2020.0.38 and Netty 4.1.101
Includes RxJava 3.1.8, SmallRye Mutiny 1.9.0, BlockHound 1.0.8, OpenPDF 1.3.33, Checkstyle 10.12.5

Closes gh-31584
2023-11-15 14:25:03 +01:00
Juergen Hoeller e660859ec3 Consistent ordering of overloaded operations
(cherry picked from commit c373f496f3)
2023-11-15 14:15:47 +01:00
Stéphane Nicoll a6ab308cf4 Fix wrong nullability requirement
Closes gh-31611
2023-11-15 12:08:19 +01:00
Sam Brannen c489234cc2 Polish contribution
See gh-31598
See gh-31603

(cherry picked from commit e71117dcdf)
2023-11-14 15:31:32 +01:00
Jason af593588d3 Avoid duplicate resources in PathMatchingResourcePatternResolver on Windows
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.

See gh-31598
Closes gh-31603

(cherry picked from commit d5874ab99e)
2023-11-14 15:31:11 +01:00
Juergen Hoeller 75193b2e84 Upgrade to Log4J 2.21.1, Tomcat 9.0.82, Jetty 9.4.53, Undertow 2.2.28, Netty 4.1.100, Reactor 2020.0.37 2023-11-09 12:32:42 +01:00
Juergen Hoeller f97e819c9e Log4jLog re-resolves ExtendedLogger on deserialization
This is necessary for compatibility with Log4J 2.21, analogous to the existing re-resolution in Spring's SLF4J adapter.

Closes gh-31582

(cherry picked from commit 1e78cc35e5)
2023-11-09 12:12:55 +01:00
Juergen Hoeller f8e1ce3074 Check for procedure vs function constants in CallMetaDataContext
Closes gh-31550

(cherry picked from commit 9957bb6918)
2023-11-09 12:06:59 +01:00
Arjen Poutsma d3ec9395e1 Guard for empty FileItems in CommonsFileUploadSupport
This commit ensures that a FileItem is not empty before its value is
read.

Closes gh-31564
2023-11-08 15:35:17 +01:00
Juergen Hoeller de0cb53394 Polishing
(cherry picked from commit 925fa0272b)
2023-10-24 23:32:17 +02:00
Juergen Hoeller 1bf5d8b9e5 Avoid ResolvableType for simple assignability check in copyProperties
Closes gh-27246

(cherry picked from commit 09aa59f9e7)
2023-10-24 23:22:31 +02:00
Stéphane Nicoll 15a306d8dd Resolve to empty MultiValueMap when no matrix variables are provided
Closes gh-31484
2023-10-24 11:02:45 +02:00
Juergen Hoeller 680939557c Test for @Resource @Lazy fallback type match
See gh-31447
2023-10-23 17:49:04 +02:00
Juergen Hoeller 84f3ce1f91 Test for getObjectType on uninitialized ProxyFactoryBean
See gh-31473
2023-10-23 17:48:56 +02:00
Juergen Hoeller 2dc4fe0857 BeanCopier sets name prefix for public classes as well
Includes consistent formatting of Spring-patched files.

Closes gh-28699

(cherry picked from commit 7a60e2024b)
2023-10-15 16:25:40 +02:00
Juergen Hoeller cb28e2a701 Polishing 2023-10-11 16:01:12 +02:00
Juergen Hoeller 0370aa6007 Do not close transactional Connection in doReleaseConnection
Closes gh-28133
2023-10-11 15:51:58 +02:00
Juergen Hoeller 704650de6d Properly return SQLExceptionTranslator-provided exception
Closes gh-31409
2023-10-11 13:20:13 +02:00
Arjen Poutsma 8538a73f20 Updated Java 8 version in sdkmanrc 2023-10-11 10:38:59 +02:00
Juergen Hoeller c615a6667d Revise javadoc for LifecycleProcessor bean etc 2023-10-10 23:28:57 +02:00
Juergen Hoeller 45cfe70d30 Revise transaction annotation recommendations
Closes gh-23538
2023-10-10 23:11:59 +02:00
Juergen Hoeller 288e255ce9 Throw IllegalArgumentException for null SQL String
Closes gh-31391

(cherry picked from commit 8b5d993e61)
2023-10-10 23:07:46 +02:00
Stéphane Nicoll 12159b98a2 Provide best-effort toString for Lazy resolved message
Previously, MessagingMessageListenerAdapter or any adapter relying on
the default MessagingMessageConverter would log an incoming message
with a toString of the Message that does not provide any extra
information. This is due to the default implementation providing a
lazy resolution message that only attempts to extract the payload
when necessary.

This commit implements a toString method that uses the raw JMS message
if the payload is not available. If it is, the payload is used instead.

Closes gh-21265

(cherry picked from commit a37abd5e54)
2023-10-10 23:07:40 +02:00
Sam Brannen 7a8ec2a761 Polish BeanPropertyRowMapper Javadoc 2023-10-02 17:28:15 +02:00
Stéphane Nicoll ca4674df42 Fix description of default behavior in BeanPropertyRowMapper
Closes gh-31349
2023-10-02 15:08:47 +02:00
Juergen Hoeller 2ec32a4e2f Polishing 2023-09-29 15:39:11 +02:00
Juergen Hoeller 3849ed3a0c Explicit note on local bean access within @PostConstruct method
Closes gh-27876
2023-09-29 15:38:55 +02:00
Sam Brannen d62f17864c Test status quo for zero capacity behavior in ConcurrentLruCache
See gh-31317
2023-09-27 12:57:08 +02:00
Stéphane Nicoll 3c59c2a275 Fix note on CGLIB supported method visibility
CGLIB do support package-private and protected methods now so the
note in the reference doc should be changed accordingly.

Closes gh-31311
2023-09-25 15:26:42 +02:00
Juergen Hoeller 2b4c1e265c Reset findLoadedClassMethod in case of makeAccessible failing
Closes gh-31232
2023-09-14 16:46:17 +02:00
Spring Builds cc0cbc15aa Next development version (v5.3.31-SNAPSHOT) 2023-09-14 07:54:54 +00:00
Juergen Hoeller f7bf2431fb Clarify IN clause resolution with List/Iterable parameter
Closes gh-31228
2023-09-14 09:28:54 +02:00
Sébastien Deleuze 40678bb981 Refine CORS documentation for wildcard processing
This commit adds a reference documentation section dedicated
to CORS credentialed requests and related wildcard processing.

Closes gh-31168
2023-09-11 18:22:03 +02:00
Sébastien Deleuze 75faf698af Refine CORS documentation for wildcard processing
This commit refines CORS wildcard processing Javadoc to
provides more details on how wildcards are handled for
Access-Control-Allow-Methods, Access-Control-Allow-Headers
and Access-Control-Expose-Headers CORS headers.

For Access-Control-Expose-Headers, it is not possible to copy
the response headers which are not available at the point
when the CorsProcessor is invoked. Since all the major browsers
seem to support wildcard including on requests with credentials,
and since this is ultimately the user-agent responsibility to
check on client-side what is authorized or not, Spring Framework
continues to support this use case.

See gh-31168
2023-09-11 18:15:07 +02:00
Juergen Hoeller 39c225c813 AnnotationUtils.clearCache() includes all annotation caches
Closes gh-31170

(cherry picked from commit 78fce80c43)
2023-09-11 17:49:56 +02:00
Juergen Hoeller 0c3d8d7a44 Align abstract method signatures with original Commons Logging API
Closes gh-31166

(cherry picked from commit 268043e9c9)
2023-09-11 17:49:35 +02:00
Sam Brannen ddcae04ad5 Do not invoke [Map|Collection].isEmpty() in nullSafeConciseToString()
gh-30811 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-31156
2023-09-08 16:21:39 +02:00
Juergen Hoeller 994bbec0c3 Polishing 2023-08-23 18:57:17 +02:00
Juergen Hoeller afb378a59f Consistently throw ParseException instead of IllegalStateException
Closes gh-31097
2023-08-23 18:57:12 +02:00
Sébastien Deleuze a4fc7d3c11 Optimize ClassUtils#getMostSpecificMethod
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-31100
2023-08-23 18:16:49 +02:00
Sam Brannen 88c3a788f3 Update copyright headers 2023-08-21 15:12:54 +02:00
Sam Brannen d7ac89ecc9 Revise contribution
Beginning with Java 16, inner classes may contain static members. We
therefore need to search for @DynamicPropertySource methods in the
current class after searching enclosing classes so that a local
@DynamicPropertySource method can override properties registered in an
enclosing class.

However, since Spring Framework 5.3.x is built using Java 8, this
commit removes DynamicPropertySourceOverridesEnclosingClassTests since
it declares a static method in a @Nested (inner) test class, which
results in a compiler error on Java 8.

See https://bugs.openjdk.org/browse/JDK-8254321
See gh-31085
2023-08-21 15:06:00 +02:00
Yanming Zhou 9894174960 Allow overriding dynamic property from enclosing class in nested test class
Prior to this commit, a dynamic property registered via a
@DynamicPropertySource method in a @Nested test class was not able to
override a property registered via a @DynamicPropertySource method in
the enclosing class.

See gh-26091
Closes gh-31083
2023-08-21 14:52:58 +02:00
Juergen Hoeller 493f75e892 Optimize whitespace checks in StringUtils (as far as possible on JDK 8)
Closes gh-31067
2023-08-18 11:40:19 +02:00
Juergen Hoeller df066d8190 Fix accidental javadoc references to jakarta packages 2023-08-16 13:03:23 +02:00
Juergen Hoeller 5f7a6a0f38 Align validation metadata handling in PayloadMethodArgumentResolver
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

(cherry picked from commit c7269feeaa)
2023-08-16 13:02:31 +02:00
Juergen Hoeller 4326c53222 Polishing
(cherry picked from commit 2ce75dc415)
2023-08-14 20:02:50 +02:00
Juergen Hoeller 3da7a35a91 Test factory-bean/method placeholders as well
See gh-20189

(cherry picked from commit 8b3ddeed05)
2023-08-14 19:41:48 +02:00
Juergen Hoeller b9be40ccd2 Add registerReactiveTypeOverride method to ReactiveAdapterRegistry
Closes gh-31047

(cherry picked from commit 389238f622)
2023-08-14 15:18:56 +02:00
Juergen Hoeller f7d4bd176e Explicit note on connection pool deadlock with REQUIRES_NEW
Closes gh-26250
2023-08-12 14:59:32 +02:00
Juergen Hoeller 2b48254268 Use extracted attributes instead of annotation access
See gh-31034

(cherry picked from commit d781f299c0)
2023-08-12 11:38:50 +02:00
Juergen Hoeller bb46b31925 Find TransactionalEventListener annotation on target method
Closes gh-31034

(cherry picked from commit 6fc4898a1b)
2023-08-12 11:38:41 +02:00
Juergen Hoeller 0c275107ea Cancel without interruption of currently running tasks
Leave potential interruption up to scheduler shutdown.

Closes gh-31019

(cherry picked from commit 6fc5a78252)
2023-08-10 00:08:39 +02:00
Juergen Hoeller 9931f442e4 Polishing
(cherry picked from commit 2aae0a4e0c)
2023-08-07 15:14:06 +02:00
Juergen Hoeller fc085e8663 Reinstate Introspector.flushFromCaches() call for JDK ClassInfo cache
Closes gh-27781
2023-08-07 15:07:33 +02:00
Juergen Hoeller 9d7154901f Polishing
(cherry picked from commit 6e5af9dccb)
2023-08-06 14:50:24 +02:00
Juergen Hoeller 24893d038f Polishing 2023-08-04 10:35:51 +02:00
Juergen Hoeller b9482375b7 Sort multiple @Autowired methods on same bean class via ASM
Closes gh-30359

(cherry picked from commit 7e6612a920)
2023-08-04 01:31:49 +02:00
Juergen Hoeller ad61fb75da Polishing 2023-08-02 01:24:11 +02:00
Juergen Hoeller c5aa7830bc Polishing
(cherry picked from commit abbea39855)
2023-07-27 21:58:22 +02:00
Juergen Hoeller 14c8c9168c Polishing 2023-07-26 14:02:05 +02:00
Juergen Hoeller 23eb0e3128 Polishing
(cherry picked from commit bbde68c49e)
2023-07-25 19:58:12 +02:00
Juergen Hoeller 840bd574db Polishing
(cherry picked from commit fdf1418dfb)
2023-07-24 11:40:59 +02:00
Juergen Hoeller 6dea580145 Clarify DataAccessException/ScriptException declarations for R2DBC
Closes gh-30932

(cherry picked from commit 5bcf5c6f7c)
2023-07-24 11:35:23 +02:00
Juergen Hoeller d1efc891db Upgrade to Netty 4.1.95 2023-07-22 00:43:26 +02:00
Juergen Hoeller c9849d6972 Polishing
(cherry picked from commit 3a9e0ea8a7)
2023-07-22 00:43:09 +02:00
Juergen Hoeller 790abeda1c Polishing 2023-07-21 20:40:06 +02:00
Juergen Hoeller 340b32a3cb Polishing 2023-07-19 23:31:38 +02:00
Juergen Hoeller a7b7466274 Polishing 2023-07-19 01:17:25 +02:00
Juergen Hoeller 3a8c0dbd8a Decouple exception messages for sync=true from @Cacheable
(cherry picked from commit bbcc788f60)
2023-07-18 22:12:58 +02:00
Juergen Hoeller b387d9bf10 MethodIntrospector handles overriding bridge method correctly
Closes gh-30906

(cherry picked from commit 616f728afa)
2023-07-18 13:27:15 +02:00
Juergen Hoeller 0f33f79c05 Avoid synchronization for shortcut re-resolution
See gh-30883

(cherry picked from commit 161a717639)
2023-07-16 16:26:37 +02:00
Juergen Hoeller ef65429823 Polishing
(cherry picked from commit 3a278cc66d)
2023-07-15 14:38:30 +02:00
Juergen Hoeller 0b4b313bae Cache DependencyDescriptor per autowired constructor argument
Aligned with shortcut handling in AutowiredAnnotationBeanPostProcessor.
Includes minor MethodInvoker optimization for pre-resolved targetClass.

Closes gh-30883

(cherry picked from commit 6183f06846)
2023-07-15 14:38:24 +02:00
Juergen Hoeller 6879be7508 Explicit hints for @PostConstruct methods (preventing deadlocks)
Closes gh-25074
2023-07-14 16:33:22 +02:00
Juergen Hoeller 355fa258bd Polishing 2023-07-14 14:52:15 +02:00
Spring Builds 60337738d8 Next development version (v5.3.30-SNAPSHOT) 2023-07-13 07:54:12 +00:00
Juergen Hoeller 53319381d0 Polishing
(cherry picked from commit c873a597c7)
2023-07-12 19:25:26 +02:00
Juergen Hoeller e1e7fa489b Upgrade to Reactor 2020.0.34 (and Tomcat 9.0.78)
Closes gh-30873
2023-07-12 09:41:42 +02:00
Brian Clozel e1351a5cb5 Update OS version in CI image 2023-07-12 08:28:18 +02:00
Juergen Hoeller ac94d2bd54 Polishing
(cherry picked from commit f19433f2d8)
2023-07-11 18:40:40 +02:00
Juergen Hoeller 16fd70ae35 Avoid illegal reflective access in ContextOverridingClassLoader
Closes gh-22791

(cherry picked from commit 0b02a5e073)
2023-07-11 18:36:19 +02:00
Juergen Hoeller c1bf09952b Improve diagnostics for LinkageError in case of ClassLoader mismatch
Closes gh-25940
2023-07-11 18:36:12 +02:00
Juergen Hoeller 9e7ee0cb8e Deprecate setAllowResultAccessAfterCompletion and document it as broken
Closes gh-26557
2023-07-11 18:36:02 +02:00
rstoyanchev 1cd994d3a8 Encapsulate full path initialization 2023-07-11 11:45:23 +01:00
Juergen Hoeller 3d28c024c5 Handle JDBC warnings in case of a statement exception as well
Closes gh-23106

(cherry picked from commit 3b899fe7e2)
2023-07-10 17:25:05 +02:00
Juergen Hoeller 3444892aea Polishing
(cherry picked from commit a17cf742b2)
2023-07-09 17:13:49 +02:00
Juergen Hoeller 14a7983eef Tolerate isCandidateClass call with null as annotation type
Closes gh-30842

(cherry picked from commit a102cd5f32)
2023-07-09 17:05:54 +02:00
Sam Brannen 0a4f290f0f Polish DefaultSingletonBeanRegistryTests 2023-07-09 16:11:45 +02:00
Sam Brannen 6ea4d3794a Further simplify DefaultSingletonBeanRegistry.isDependent()
See gh-30841
2023-07-09 16:11:41 +02:00
bnbakp0582 85eec5d344 Simplify DefaultSingletonBeanRegistry.isDependent()
Move `alreadySeen` handling out of for-loop.

Closes gh-30841
2023-07-09 16:11:32 +02:00
Juergen Hoeller 0961bc546a Polishing
(cherry picked from commit 0b7a24fc14)
2023-07-08 01:10:31 +02:00
Juergen Hoeller f2df10c7fe Polishing 2023-07-07 13:26:06 +02:00
Sam Brannen 03f1fabbdb Improve assertions in DefaultConversionServiceTests
Specifically, we now check the actual type of a converted collection in
various assertions to ensure that converters adhere to their contracts.
2023-07-06 13:11:35 +02:00
Sam Brannen 2ada2b77f6 Update Javadoc for ObjectUtils.nullSafeConciseToString()
See gh-30811
2023-07-06 12:29:46 +02:00
Juergen Hoeller d5380b3070 Expand tests for array to Collection/Set/List interface
See gh-28048
2023-07-05 21:12:36 +02:00
Sam Brannen a3907a64e5 Support arrays, collections, & maps in ObjectUtils.nullSafeConciseToString()
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-30811
2023-07-05 17:15:15 +02:00
Juergen Hoeller dd16e012ba Clarify ReactiveTransactionManager exception declarations
Avoid misleading "throws TransactionException" declarations but preserve javadoc "@throws" notes for specific exceptions (with reactive propagation semantics).

Closes gh-30817
2023-07-05 12:15:05 +02:00
Juergen Hoeller d4cd358c76 Discuss JdbcTransactionManager vs DataSourceTransactionManager
Closes gh-30802
2023-07-05 12:14:48 +02:00
Juergen Hoeller da814e01c7 Polishing 2023-07-04 21:52:36 +02:00
Juergen Hoeller 5d4c2846d9 Polishing 2023-07-04 16:43:29 +02:00
Juergen Hoeller a3daee6ad8 Make File/Path tests pass on Windows
See gh-30806
2023-07-04 16:38:10 +02:00
Juergen Hoeller 5614e5bc18 Restore full representation of rejected value in FieldError.toString()
We would preferably use ObjectUtils.nullSafeConciseToString(rejectedValue) here but revert to the full nullSafeToString representation for strict backwards compatibility (programmatic toString calls as well as exception messages).

Closes gh-30799

(cherry picked from commit 1dc9dffc70)
2023-07-04 16:13:48 +02:00
Juergen Hoeller 6dde13f597 Refresh cached value after unexpected mismatch (e.g. null vs non-null)
In addition to the previously addressed removal of bean definitions, this is able to deal with prototype factory methods returning non-null after null or also null after non-null. Stale cached values are getting refreshed rather than bypassed.

Closes gh-30794

(cherry picked from commit 0226580773)
2023-07-04 16:13:44 +02:00
Sam Brannen c057da23ec Extend supported types in ObjectUtils.nullSafeConciseToString()
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-30806
2023-07-04 15:01:35 +02:00
Sam Brannen a7f07328ab Add tests for status quo in ObjectUtils.nullSafeConciseToString() 2023-07-04 14:57:57 +02:00
Sam Brannen 45f747fae1 Clean up warnings in tests 2023-07-04 14:34:32 +02:00
Vladyslav Baidak 258bd3f73c Fix typo in Javadoc for BeanDefinitionDsl.kt
Closes gh-30798
2023-07-03 15:53:09 +02:00
Juergen Hoeller 97b95d9d01 Upgrade to Tomcat 9.0.76, Netty 4.1.94, Undertow 2.2.25, Checkstyle 10.12.1 2023-06-30 13:16:57 +02:00
Juergen Hoeller 69827a2f21 Raise beforeCompletion/afterCompletion exception log level to error
Closes gh-30776

(cherry picked from commit f1567fb21a)
2023-06-30 13:16:37 +02:00
Juergen Hoeller ef699b6a9e Align ConcurrentMapCacheManager locking behavior with CaffeineCacheManager
Closes gh-30780

(cherry picked from commit 60865eae4b)
2023-06-30 10:53:21 +02:00
Juergen Hoeller e440eb8365 Consistently handle invocation exceptions in TypeProxyInvocationHandler
Closes gh-30764

(cherry picked from commit 3cb746c358)
2023-06-28 15:48:41 +02:00
Juergen Hoeller 02cbee560d Polishing
(cherry picked from commit 6526e79eea)
2023-06-26 20:06:12 +02:00
Juergen Hoeller 14da1aca2f Adapt no-arg value from interface-based InvocationHandler callback
Closes gh-30756

(cherry picked from commit b77d4d01c5)
2023-06-26 20:06:06 +02:00
Juergen Hoeller ce97342fee Consistently use mutable ArrayList for modulesToInstall vs modules
Closes gh-30751

(cherry picked from commit 062d701ae1)
2023-06-26 12:39:01 +02:00
Sam Brannen 2e51aa250e Update copyright headers 2023-06-22 14:54:43 +02:00
Juergen Hoeller ec2957afc8 Test for supportsEventType mismatch with unrelated event type
See gh-30712
2023-06-21 18:01:15 +02:00
Juergen Hoeller d3df45d8fe Avoid ResolvableType creation for interface/superclass check
See gh-30713

(cherry picked from commit 1dfe737d0e)
2023-06-21 17:46:59 +02:00
Juergen Hoeller 5375f62dc1 Cache hasUnresolvableGenerics result for repeated checks
Closes gh-30713

(cherry picked from commit 93218a06ba)
2023-06-21 13:24:42 +02:00
Juergen Hoeller c7bc40d3ba Ensure Spring LogFactory contains all public methods from Apache LogFactory
Closes gh-30668

(cherry picked from commit 20bbebb299)
2023-06-21 09:58:23 +02:00
Juergen Hoeller 1071778aa9 Fall back to type-based creation if no bean of the given name exists
Closes gh-30683

(cherry picked from commit dff7aa4d4b)
2023-06-17 11:46:48 +02:00
Juergen Hoeller 40a9ae9d14 Recognize error code 2628 as data integrity violation (MSSQL 2019)
Closes gh-30681

(cherry picked from commit c634acd9ff)
2023-06-17 11:44:11 +02:00
Sam Brannen e34a7baeb3 Remove code duplication in RootBeanDefinition 2023-06-15 16:12:31 +02:00
Brian Clozel 62eb9b391d Use Docker hub credentials for CI tasks 2023-06-15 13:20:51 +02:00
Spring Builds ea89bf2c91 Next development version (v5.3.29-SNAPSHOT) 2023-06-15 07:32:26 +00:00
Juergen Hoeller 99ae6e70bb Declare ClassLoader for DeserializingConverter constructor as nullable
Closes gh-30670

(cherry picked from commit b9221656cc)
2023-06-14 22:34:28 +02:00
Juergen Hoeller c2cc55eacc Consider UUID as simple value type with concise toString output
Closes gh-30661

(cherry picked from commit 927d27b121)
2023-06-14 10:47:54 +02:00
Juergen Hoeller 9cff2ace97 Upgrade to Reactor 2020.0.33
Closes gh-30656
2023-06-13 18:40:46 +02:00
Juergen Hoeller 3c2590d339 Document limited isolation level support for concurrent transactions
See gh-29997
2023-06-13 12:57:52 +02:00
Juergen Hoeller 4b55333b0e Document which @Scheduled attributes support SpEL expressions
Closes gh-29290

(cherry picked from commit f8c8873c99)
2023-06-12 13:08:02 +02:00
Juergen Hoeller c27acad616 Specific check for parent of MethodInvocationInfo ClassLoader
See gh-30389
2023-06-12 11:33:54 +02:00
Juergen Hoeller 70be9afdc6 Reuse method cache from original proxy factory (aligned with 6.0.x)
See gh-30616
2023-06-12 11:11:07 +02:00
Juergen Hoeller d4450a8702 Specific check for parent of spring-aop ClassLoader
Closes gh-30389

(cherry picked from commit 0a5aff1b60)
2023-06-12 11:08:37 +02:00
Juergen Hoeller 210e47d65e Polishing 2023-06-08 18:31:31 +02:00
Juergen Hoeller 06411831e8 Consistent ProxyCallbackFilter#equals/hashCode methods
Opaque check in equals instead; no consideration of optimize flag.

Closes gh-30616
2023-06-08 18:31:26 +02:00
Juergen Hoeller 8c7daa807a Polishing 2023-06-07 20:14:41 +02:00
Juergen Hoeller 46d171a8fd Restore creation of plain HashSet/HashMap for direct HashSet/HashMap type
Closes gh-30596

(cherry picked from commit cdc4497664)
2023-06-05 14:03:15 +02:00
Juergen Hoeller 259bd5250d Consistent javadoc references to JdbcTransactionManager 2023-06-05 11:12:38 +02:00
Juergen Hoeller cef046218c Upgrade to Tomcat 9.0.75, Netty 4.1.93, Undertow 2.2.24, EclipseLink 2.7.12 2023-06-04 18:13:00 +02:00
Juergen Hoeller e4bd1344e2 Set and reset shared isolation value within synchronized transaction begin
Since EclipseLink applies a custom transaction isolation value to its shared DatabasePlatform instance, we need to immediately restore the original value after the current value got picked up for JDBC Connection access inside of EclipseLink. In order to not interfere with concurrent transactions, we need to use synchronization around the transaction begin sequence in such a case.

Closes gh-29997
2023-06-04 18:12:40 +02:00
Juergen Hoeller 9decbf2158 Polishing 2023-06-03 00:01:18 +02:00
Juergen Hoeller 268b7a8931 Revise TargetSource implementations for proper nullability
Includes hashCode optimization in AbstractBeanFactoryBasedTargetSource.
Includes ThreadLocal naming fix in ThreadLocalTargetSource.

Closes gh-30576
Closes gh-30581

(cherry picked from commit c68552556f)
2023-06-02 23:48:41 +02:00
Juergen Hoeller 1240fb6b9a Consistently publish events from CompletableFuture
Closes gh-30578

(cherry picked from commit b738a20233)
2023-06-02 23:36:13 +02:00
Brian Clozel 7dae3afb4b Resolve Asciidoctor extensions from Central
This commit upgrades spring-asciidoctor-extensions-block-switch to 0.6.1
as this version is available on Maven Central.
2023-05-30 09:49:23 +02:00
Stephane Nicoll d9de36b5ee Merge branch 'gh-30555' into 5.3.x
Closes gh-30555
2023-05-30 09:18:41 +02:00
Stephane Nicoll 4e696db922 Update copyright year of changed file
See gh-30554
2023-05-30 09:18:06 +02:00
Stefano Cordio 0adad10595 Fix FileSystemUtils::deleteRecursively Javadoc
See gh-30554
2023-05-30 09:17:54 +02:00
Juergen Hoeller 540d0d9345 Avoid Autowired shortcut resolution for NullBean values
Includes getBean documentation against NullBean values.

Closes gh-30485

(cherry picked from commit 8b8d147480)
2023-05-26 11:16:09 +02:00
Brian Clozel 572bbeeba3 Use spring-doc-resources SNAPSHOT version 2023-05-25 20:04:08 +02:00
Brian Clozel 77cd44dd20 Update CI pipeline 2023-05-25 19:13:58 +02:00
rstoyanchev 65e7b4a279 Add ignore rule for cached-antora-playbook.yml
In case of checking out the 5.3.x branch after 6.0.x or main
2023-05-23 15:14:01 +01:00
Sam Brannen 7d95a24573 Make maximum SpEL expression length configurable
Closes gh-30446
2023-05-10 15:12:36 +02:00
Juergen Hoeller 1dbe0ee6db Respect TaskDecorator configuration on DefaultManagedTaskExecutor
Closes gh-30442
2023-05-08 12:18:53 +02:00
Juergen Hoeller 0211016957 Consistent support for MultiValueMap and common Map implementations
Closes gh-30440
2023-05-08 12:13:44 +02:00
Sam Brannen 08fe123930 Introduce Environment.matchesProfiles() for profile expressions
Environment.acceptsProfiles(String...) was deprecated in 5.1 in
conjunction with gh-17063 which introduced a new
acceptsProfiles(Profiles) method to replace it. The deprecated method
only supports OR semantics; whereas, the new method supports profile
expressions. Thus, the goal was to encourage people to use the more
powerful profile expressions instead of the limited OR support with
profile names.

However, there are use cases where it is difficult (if not impossible)
to provide a Profiles instance, and there are use cases where it is
simply preferable to provide profile expressions directly as strings.

To address these issues, this commit introduces a new matchesProfiles()
method in Environment that accepts a var-args list of profile
expressions.

See gh-30206
Closes gh-30226
2023-04-25 19:19:22 +02:00
Sam Brannen 219448796f Polish Environment and StandardEnvironmentTests
See gh-30206
See gh-30226
2023-04-25 19:19:03 +02:00
Sam Brannen 0956c144c9 Polish ProfilesParser internals 2023-04-25 18:56:08 +02:00
Sam Brannen 964950a8b9 Reject null and empty SpEL expressions
Prior to gh-30325, supplying a null reference for a SpEL expression was
effectively equivalent to supplying the String "null" as the
expression. Consequently, evaluation of a null reference expression
always evaluated to a null reference. However, that was accidental
rather than by design.

Due to the introduction of the checkExpressionLength(String) method in
InternalSpelExpressionParser (in conjunction with gh-30325), an attempt
to evaluate a null reference as a SpEL expression now results in a
NullPointerException.

To address both of these issues,
TemplateAwareExpressionParser.parseExpression() and
SpelExpressionParser.parseRaw() now reject null and empty SpEL
expressions.

See gh-30371
Closes gh-30373
2023-04-25 14:31:35 +02:00
Sam Brannen 5afd94f90f Polish SpelParserTests and TemplateExpressionParsingTests 2023-04-25 14:29:01 +02:00
Arjen Poutsma ec5f7644e4 Updated CI image JDK 2023-04-24 13:00:06 +02:00
Arjen Poutsma 0c8ef4c671 Updated sdkmanrc 2023-04-24 12:37:15 +02:00
Spring Builds a851b7309a Next development version (v5.3.28-SNAPSHOT) 2023-04-13 08:57:10 +00:00
Sam Brannen 6bfb94a563 Disable variable assignment in SimpleEvaluationContext
This commit introduces infrastructure to differentiate between
programmatic setting of a variable in an EvaluationContext versus the
assignment of a variable within a SpEL expression using the assignment
operator (=). In addition, this commit disables variable assignment
within expressions when using the SimpleEvaluationContext.

Closes gh-30327
2023-04-13 10:20:06 +02:00
Sam Brannen ebc8265428 Limit SpEL expression length
This commit enforces a limit of the maximum size of a single SpEL
expression.

Closes gh-30329
2023-04-13 10:15:02 +02:00
Sam Brannen 86457464d7 Limit string concatenation in SpEL expressions
This commit introduces support for limiting the maximum length of a
string resulting from the concatenation operator (+) in SpEL
expressions.

Closes gh-30331
2023-04-13 10:14:18 +02:00
Sam Brannen be129dc171 Change max regex length in SpEL expressions to 1000
This commit changes the max regex length in SpEL expressions from 1024
to 1000 in order to consistently use "round" numbers for recently
introduced limits.

See gh-30265
2023-04-13 10:14:15 +02:00
Juergen Hoeller 8bb1b3eb44 Upgrade to Netty 4.1.91 and Checkstyle 10.9.3 2023-04-12 13:53:17 +02:00
Stephane Nicoll 6abd822e77 Upgrade to Reactor 2020.0.31
Closes gh-30315
2023-04-11 17:35:25 +02:00
rstoyanchev 1c43a4c7ab Fix regression in ReactorServerHttpRequest
Instead of a backport for cef916, this change simply undoes the
optimization that led to the regression.

Closes gh-30314
2023-04-11 15:12:54 +01:00
Sam Brannen 423f2215c2 Remove flaky assertion to fix build on JDK 17
Sometime between JDK 8 and JDK 17, the behavior for List::toArray()
changed. Specifically, the type returned for List<String> changed from
String[] to Object[].

This commit therefore removes an assertion against this particular
JDK-specific behavior. The affected test method retains additional
assertions along the same lines but which are not flaky.
2023-04-10 17:34:04 +02:00
Sébastien Deleuze 0bad69d5fb Fix SSE with indenting serializer in WebMvc.fn
This commit ensures that HTTP headers like "text/event-stream"
are correctly forwarded to the converter used in
SseServerResponse for proper pretty print handling.

Close gh-30302
2023-04-07 11:56:47 +02:00
Sam Brannen 6b19642256 Increase max regex length in SpEL expressions
This commit increases the max regex length in SpEL expressions from 256
to 1024 in order to support use cases where a regex may be rather long
without necessarily increasing the complexity of the regex.

Closes gh-30298
2023-04-06 18:02:36 +02:00
Sam Brannen 19bb4e96f2 Improve Javadoc for ObjectUtils.nullSafeConciseToString() 2023-04-06 17:36:32 +02:00
Sam Brannen 7a2594acda Add tests for corner cases
See gh-30290
See gh-30286
2023-04-05 15:28:45 +02:00
Sam Brannen 91c58af7af Introduce ObjectUtils.nullSafeConciseToString()
ObjectUtils.nullSafeToString(Object) exists for generating a string
representation of various objects in a "null-safe" manner, including
support for object graphs, collections, etc.

However, there are times when we would like to generate a "concise",
null-safe string representation that does not include an entire object
graph (or potentially a collection of object graphs).

This commit introduces ObjectUtils.nullSafeConciseToString(Object) to
address this need and makes use of the new feature in FieldError and
ConversionFailedException.

Closes gh-30286
2023-04-05 15:25:59 +02:00
Sam Brannen 0a1aeafe08 Introduce StringUtils.truncate()
StringUtils.truncate() serves as central, consistent way for truncating
strings used in log messages and exception failure messages, for
immediate use in LogFormatUtils and ObjectUtils.

See gh-30286
Closes gh-30290
2023-04-05 15:15:53 +02:00
Simon Baslé 0e69bac7b0 Polish 0cfbf60: fix a test for Java 8 compatibility 2023-04-04 15:25:27 +02:00
Simon Baslé 0cfbf6036c Rename MockMVC matcher methods to prevent regression in user tests
This commit changes the name of two recently introduced methods in the
`MockRestRequestMatchers` class for header and queryParam. These have
been found to cause false negatives in user tests, due to the new
overload taking precedence in some cases.

Namely, using a `Matcher` factory method which can apply to both `List`
and `String` will cause the compiler to select the newest list overload,
by instantiating a `Matcher<Object>`.

This can cause false negatives in user tests, failing tests that used
to pass because the Matcher previously applied to the first String in
the header or queryParam value list. For instance, `equalsTo("a")`.

The new overloads are recent enough and this has enough potential to
cause an arbitrary number of user tests to fail that we break the API
to eliminate the ambiguity, by renaming the methods with a `*List`
suffix.

See gh-30220
See gh-30238
Closes gh-30235
2023-04-04 15:07:41 +02:00
Sébastien Deleuze e931fdc5c2 Make HttpComponentsHeadersAdapter#getFirst nullable
Backport of gh-30267

Closes gh-30269
2023-04-03 09:06:32 +02:00
Sébastien Deleuze 3a1681357c Fix PathVariable reference documentation code snippets
Closes gh-30258
2023-03-31 15:51:45 +02:00
Juergen Hoeller a93382dbbf Propagate HttpStreamResetException itself if cause is null
Closes gh-30245

(cherry picked from commit 8fca258207)
2023-03-30 19:32:29 +02:00
Sébastien Deleuze 79c5ef88f5 Refine generic type management in AbstractMessageWriterResultHandler
This commit updates AbstractMessageWriterResultHandler#writeBody in
order to use the declared bodyParameter instead of
ResolvableType.forInstance(body) when the former has unresolvable
generics.

Closes gh-30215
2023-03-30 18:26:15 +02:00
Juergen Hoeller 0c80e5f9e6 Use JdkDynamicAopProxy class loader instead of JDK bootstrap/platform loader
Closes gh-30115

(cherry picked from commit 7e905e3e00)
2023-03-29 14:07:50 +02:00
Juergen Hoeller 7ad01a94d6 Use MethodInvocationInfo class loader in case of JDK platform loader as well
Closes gh-30210

(cherry picked from commit 491ae1e3be)
2023-03-29 13:56:23 +02:00
Juergen Hoeller 5d6d653cbd Use MethodInvocationInfo class loader in case of core JDK interface type
Closes gh-30210

(cherry picked from commit ce2689eead)
2023-03-28 13:56:02 +02:00
Johnny Lim 9868e888a5 Update versions in Javadoc
Closes gh-30191
2023-03-25 17:17:28 +01:00
ghostg00 6f6eb3d996 Fix example in Javadoc for @EnableWebSocket
The `echoWebSocketHandler()` method is not defined in the
`WebSocketConfigurer` interface and should therefore be annotated with
`@Bean` instead of `@Override`.

Closes gh-30187
2023-03-24 17:55:24 +01:00
Giuseppe a94c50e294 Handle all exceptions for stored proc out param retrieval in SharedEntityManagerCreator
Prior to this commit, the EntityManager was not closed in
SharedEntityManagerCreator.DeferredQueryInvocationHandler's
invoke(Object, Method, Object[]) method if an invocation of
getOutputParameterValue(*) threw an exception other than
IllegalArgumentException, which could lead to a connection leak.

This commit addresses this by catching RuntimeException instead of
IllegalArgumentException.

Closes gh-30164
2023-03-22 15:44:06 +01:00
Kukri b8c1255ee0 Fix anchor in link to "Web on Reactive Stack" chapter
Closes gh-30163
2023-03-22 11:35:12 +01:00
Spring Builds 129062034b Next development version (v5.3.27-SNAPSHOT) 2023-03-20 10:05:15 +00:00
rstoyanchev eafe3afe11 Polishing and minor refactoring in HandlerMappingIntrospector
Closes gh-30128
2023-03-20 08:38:11 +00:00
Sam Brannen 26e0343c16 Improve diagnostics in SpEL for matches operator
Supplying a large regular expression to the `matches` operator in a
SpEL expression can result in errors that are not very helpful to the
user.

This commit improves the diagnostics in SpEL for the `matches` operator
by throwing a SpelEvaluationException with a meaningful error message
to better assist the user.

Closes gh-30145
2023-03-20 00:07:01 +01:00
Sam Brannen 4d5e7207f2 Improve diagnostics in SpEL for repeated text
Attempting to create repeated text in a SpEL expression using the
repeat operator can result in errors that are not very helpful to the
user.

This commit improves the diagnostics in SpEL for the repeat operator by
throwing a SpelEvaluationException with a meaningful error message in
order to better assist the user.

Closes gh-30143
2023-03-20 00:06:54 +01:00
Sam Brannen 430fc25aca Increase scope of regex pattern cache for the SpEL matches operator
Prior to this commit, the pattern cache for the SpEL `matches` operator
only applied to expressions such as the following where the same
`matches` operator is invoked multiple times with different input:

  "map.keySet().?[#this matches '.+xyz']"

The pattern cache did not apply to expressions such as the following
where the same pattern ('.+xyz') is used in multiple `matches`
operations:

  "foo matches '.+xyz' AND bar matches '.+xyz'"

This commit addresses this by moving the instance of the pattern cache
map from OperatorMatches to InternalSpelExpressionParser so that the
cache can be reused for all `matches` operations for the given parser.

Closes gh-30141
2023-03-20 00:06:46 +01:00
Sam Brannen 0882ca57d4 Polishing 2023-03-20 00:06:32 +01:00
Sam Brannen 94bbf85c0e Stop printing to System.out in SpEL tests 2023-03-20 00:06:24 +01:00
Juergen Hoeller 2c2ef12f68 Upgrade to Netty 4.1.90 and Checkstyle 10.9.1 2023-03-17 18:10:02 +01:00
Juergen Hoeller 120d512ff6 Polishing (backported from main) 2023-03-17 18:09:46 +01:00
Sam Brannen 3ddf183922 Update copyright headers 2023-03-17 14:51:13 +01:00
rstoyanchev 4c69bfd32f Upgrade to Reactor 2020.0.30
Closes gh-30116
2023-03-16 08:30:16 +00:00
Sam Brannen 41d71e9a7f Revise contribution
See gh-25316
2023-03-15 14:30:53 +01:00
mrcoffee77 36682b7ad2 Ensure methods declared in Object can be invoked on a JDK proxy in SpEL
This commit ensures that methods declared in java.lang.Object (such as
toString() can be invoked on a JDK proxy instance in a SpEL expression.

Closes gh-25316
2023-03-15 14:30:53 +01:00
Sam Brannen 30601a5014 Polishing 2023-03-15 14:30:53 +01:00
Brian Clozel f2371f5e7d Ignore quality factor when filtering out "*/*"
Prior to this commit, the `RequestedContentTypeResolverBuilder` would
create a `RequestedContentTypeResolver` that internally delegates to a
list of resolvers. Each resolver would either return the list of
requested media types, or a singleton list with the "*/*" media type; in
this case this signals that the resolver cannot find a specific media
type requested and that we should continue with the next resolver in the
list.

Media Types returned by resolvers can contain parameters, such as the
quality factor. If the HTTP client requests "*/*;q=0.8", the
`HeaderContentTypeResolver` will return this as a singleton list. While
this has been resolved from the request, such a media type should not be
selected over other media types that could be returned by other
resolvers.

This commit changes the `RequestedContentTypeResolverBuilder` so that it
does not select "*/*;q=0.8" as the requested media type, but instead
continues delegating to other resolvers in the list. This means we need
to remove the quality factor before comparing it to the "*/*" for
equality check.

Fixes gh-30121
2023-03-15 10:45:31 +01:00
rstoyanchev f0da099b12 Prefer request hostName and hostPort in ReactorServerHttpRequest
Backport of 682a4d53 and 9624ea39

Closes gh-29974
2023-03-14 07:02:21 +00:00
Brian Clozel d00fd4c502 Allow runtime compatibility with SnakeYaml 2.0
This commit ensures that SnakeYaml 2.0 is compatible at runtime with
Spring Framework 5.3.x with the `YamlProcessor` support.
The baseline version for SnakeYaml remains the same.

Closes gh-30097
2023-03-10 12:41:03 +01:00
Sébastien Deleuze 44a6d13cc0 Fix minor spacings in webflux docs
Closes gh-30095
2023-03-09 11:56:55 +01:00
Juergen Hoeller 284657355a Upgrade to Log4J 2.20, Tomcat 9.0.73, Jetty 9.4.51, Undertow 2.2.23 2023-03-08 17:44:10 +01:00
Juergen Hoeller 6a81ed3a50 Polishing 2023-03-08 17:43:35 +01:00
Brian Clozel 0a053cfccb Avoid lock contention in CaffeineCacheManager
Prior to this commit, using a dynamic `CaffeineCacheManager` would rely
on `ConcurrentHashMap#computeIfAbsent` for retrieving and creating cache
instances as needed. It turns out that using this method concurrently
can cause lock contention even when all known cache instances are
instantiated.

This commit avoids using this method if the cache instance already
exists and avoid storing `null` entries in the map. This change reduces
lock contention and the overall HashMap size in the non-dynamic case.

See gh-30066
Fixes gh-30085
2023-03-08 16:27:50 +01:00
Sam Brannen 22bb76d326 Revise documentation for @AspectJ argument name resolution algorithm
Closes gh-30057
2023-03-02 17:22:17 +01:00
Sam Brannen 4dc45d551c Update documentation for @AspectJ argument name resolution algorithm
Closes gh-30057
2023-03-01 17:29:50 +01:00
Sam Brannen e5d05ddfc3 Remove obsolete MetadataAwareAspectInstanceFactory Javadoc
We no longer have any JDK 5 related limitations imposed on us as was
the case when MetadataAwareAspectInstanceFactory was introduced; however,
MetadataAwareAspectInstanceFactory will remain as a specialized
sub-interface of AspectInstanceFactory.
2023-03-01 17:13:55 +01:00
Sam Brannen 44a5f8ec06 Add missing package-info.java file for autoproxy.target package 2023-03-01 17:13:45 +01:00
Sam Brannen 0a8bda40f4 Fix .gitignore pattern for Maven "target" folders
Rationale: changes in org.springframework.aop.framework.autoproxy.target
were previously ignored since the "target" package was ignored by the
previous "eager" pattern for "target" folders.
2023-03-01 17:13:32 +01:00
Radek Kraus 8a879c6fed Protect JMS connection creation against prepareConnection errors
This commit uses a local variable for the creation of a new JMS
Connection so that a rare failure in prepareConnection(...) does not
leave the connection field in a partially initialized state.

If such a JMSException occurs, the intermediary connection is closed.
This commit further defends against close() failures at that point,
by logging the close exception at DEBUG level. As a result, the original
JMSException is always re-thrown.

See gh-29116
Closes gh-30051
2023-02-28 16:35:36 +01:00
Sam Brannen 28d11aaf64 Polish contribution
See gh-30036
2023-02-27 16:47:09 +01:00
1993heqiang 02941127e1 Fix "Configuring a Global Date and Time Format" example
Closes gh-30036
2023-02-27 16:47:03 +01:00
Sam Brannen b1b24458c9 Polishing 2023-02-27 16:46:16 +01:00
Sébastien Deleuze 854b625be2 Add missing @Nullable annotations to LogMessage methods
Closes gh-30009
2023-02-24 17:51:52 +01:00
rstoyanchev a2b7a907ec Prefer local hostAddress in ReactorServerHttpRequest
Closes gh-28601
2023-02-23 16:40:38 +00:00
Brian Clozel 4f0a8911ca Fix CI image resource in pipeline
This commit fixes the CI image resource configuration so that it can be
checked autmatically by the pipeline.
This also updates various resources.
2023-02-23 09:44:09 +01:00
Sam Brannen 40fef7b232 Fix Javadoc for MockRestRequestMatchers 2023-02-22 11:09:03 +01:00
Sam Brannen 423134f64c Revise queryParam() and header() support in MockRestRequestMatchers
See gh-29953
See gh-29964
2023-02-22 11:08:05 +01:00
Sam Brannen 574c10d219 Polishing 2023-02-22 11:08:05 +01:00
Johnny Lim 2b4b947050 Fix Javadoc since for MockRestRequestMatchers queryParam() and header() (#29986)
See gh-29953
See gh-29964
2023-02-22 11:08:05 +01:00
Juergen Hoeller 4993b1090a Polishing 2023-02-22 11:08:05 +01:00
Juergen Hoeller 3adabf391f Consistent ordering of Resource methods (backported from main) 2023-02-15 12:35:41 +01:00
Juergen Hoeller 0026338c00 Consistent @Bean method return type for equivalence with XML example
Closes gh-29970
2023-02-14 16:57:35 +01:00
Juergen Hoeller cdea667e58 Test for request attribute visibility in FreeMarker (backported from main)
See gh-29787
2023-02-14 16:57:22 +01:00
Juergen Hoeller 66b1c0b4b0 Upgrade to Netty 4.1.89 2023-02-14 11:38:32 +01:00
Juergen Hoeller 6e42d36614 ASM upgrade for JDK 20/21 support (backported from main)
Closes gh-29966
2023-02-14 11:38:12 +01:00
Simon Baslé 7f2c93fa1f Allow MockRest to match header/queryParam value list with one Matcher
This commit adds a `header` variant and a `queryParam` variant to the
`MockRestRequestMatchers` API which take a single `Matcher` over the
list of values.

Contrary to the vararg variants, the whole list is evaluated and the
caller can choose the desired semantics using readily-available iterable
matchers like `everyItem`, `hasItems`, `hasSize`, `contains` or
`containsInAnyOrder`...

The fact that the previous variants don't strictly check the size of the
actual list == the number of provided matchers or expected values is
now documented in their respective javadocs.

See gh-29953
Closes gh-29964
2023-02-13 17:53:48 +01:00
Johnny Lim 4c351e811a Polish
See gh-29928
2023-02-09 09:55:19 +01:00
rstoyanchev 5b67dea506 Unwrap session before selecting stats counter
See gh-29375
2023-02-08 18:10:11 +00:00
Sam Brannen b9fe095f60 Clearly document that DataClassRowMapper supports Java records
Closes gh-29814
2023-02-07 19:09:47 +01:00
Sam Brannen 6b17014b5a Polish RowMapper tests 2023-02-07 19:09:32 +01:00
Sam Brannen 878246b09b Avoid confusing terminology in BeanPropertyRowMapper
Prior to this commit, the term "field" was sometimes used to refer to a
database column and sometimes used to refer to a bean property, which
lead to confusion in the Javadoc as well as within the code.

This commit addresses this by avoiding use of the term "field".
2023-02-07 19:07:40 +01:00
Sam Brannen 9067ccab2d Update copyright headers 2023-02-07 16:35:52 +01:00
Manthan Bhatt 4e00aece7a Restrict forwards in MockMvcWebConnection to 100
This change restricts the maximum number of forwards in MockMvcWebConnection to 100,
in case a forward is configured in a way that causes a loop. This is necessary in HtmlUnit
backed tests, unlike in classic MockMvc tests in which the forwards are not actually resolved.

See gh-29557
Closes gh-29866

Co-authored-by: Simon Baslé <sbasle@vmware.com>
2023-02-07 16:24:57 +01:00
Sam Brannen c9841f37b6 Revise Testcontainers examples based on feedback
Closes gh-29940
2023-02-07 15:57:23 +01:00
Johnny Lim 92d513e9fb Add MockMvc.multipart() Kotlin extensions with HttpMethod
See gh-28545
See gh-28631
Closes gh-29941
2023-02-07 15:12:27 +01:00
Sam Brannen 782ee34cb7 Update @DynamicPropertySource examples regarding changes in Testcontainers
Closes gh-29939
2023-02-07 13:38:50 +01:00
Sam Brannen 80c10fad92 Polish RowMapper tests 2023-02-03 18:06:10 +01:00
Sam Brannen 498a0d286f Clarify semantics of primitivesDefaultedForNullValue in BeanPropertyRowMapper
Closes gh-29923
2023-02-03 18:06:10 +01:00
Sam Brannen e9d45d1b49 Polish Javadoc for RowMappers 2023-02-03 18:01:07 +01:00
danu 0851b0f72d Release R2DBC connection when cleanup fails in transaction
When using R2dbcTransactionManager, connection will not be released if
it encounters error while doing `afterCleanup` steps. As `afterCleanup`
can use a database connection when doing `setAutoCommit(true)`, it can
fail under some conditions where the connection is not reliable.

This leads to the Connection not being released.

This commit ensures that inner steps of the `doCleanupAfterCompletion`
are protected against errors, logging the errors and continuing the
cleanup until the last step, which releases the connection.

Backport of commit e050c37
See gh-29703
Closes gh-29925

Co-authored-by: Simon Baslé <sbasle@vmware.com>
2023-02-03 17:43:22 +01:00
Brian Clozel 91d991e86c Rely only on Docker Hub for fetching OCI images 2023-02-02 21:47:19 +01:00
Juergen Hoeller 960f6fb936 Add missing warn level check (backported from main) 2023-02-01 18:28:20 +01:00
Juergen Hoeller 4d3d34528e Upgrade to Tomcat 9.0.71, Netty 4.1.87, AssertJ 3.24.2, HtmlUnit 2.70, Checkstyle 10.7 2023-02-01 18:26:00 +01:00
Juergen Hoeller 78ba946266 Clarify postProcessBeanFactory lifecycle state
Closes gh-29064

(cherry picked from commit b8827d8e11)
2023-02-01 18:21:16 +01:00
Juergen Hoeller 42e7318cbb Polishing 2023-01-31 16:48:36 +01:00
Juergen Hoeller 000383fbff Explicit target ClassLoader for interface-based infrastructure proxies
Includes direct JDK Proxy usage instead of ProxyFactory where possible.

Closes gh-29913

(cherry picked from commit 4d6249811e)
2023-01-31 16:48:27 +01:00
Juergen Hoeller 37cbdc2cf4 Lazily load ContextLoader.properties (and lazily fail if not present)
Closes gh-29905

(cherry picked from commit a74b86e812)
2023-01-31 16:21:45 +01:00
Juergen Hoeller 6d95e7f9d9 Declare no-op close() method in order to avoid container-triggered shutdown call
Closes gh-29892

(cherry picked from commit 7c9dca3d2e)
2023-01-31 16:21:39 +01:00
rstoyanchev 45a7917a36 Backport of cf9fc69d6b
Closes gh-29911
2023-01-31 11:55:32 +00:00
rstoyanchev 25b95b8b98 Avoid ClassLoader issue in Jetty10 WebSocket upgrade
Closes gh-29256
2023-01-31 11:50:22 +00:00
Sam Brannen 6bd7a7321e Revise generated default name for @JmsListener subscription
The previous commit changed the generated default name for a JMS
subscription to <FQCN>#<method name> -- for example:

- org.example.MyListener#myListenerMethod

However, the JMS spec does not guarantee that '#' is a supported
character. This commit therefore changes '#' to '.' as the separator
between the class name and method name -- for example:

- org.example.MyListener.myListenerMethod

This commit also introduces tests and documentation for these changes.

See gh-29902
2023-01-30 19:57:28 +01:00
Sam Brannen 11aaba9877 Polishing 2023-01-30 19:52:24 +01:00
fml2 07fd7606e7 Improve generated default name for a @JmsListener subscription
Prior to this commit, when using durable subscribers with @JmsListener
methods that do not specify a custom subscription name the generated
default subscription name was always
org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.
Consequently, multiple such @JmsListener methods were assigned the
same subscription name which violates the uniqueness requirement.

To address this, MessagingMessageListenerAdapter now implements
SubscriptionNameProvider and generates the subscription name based on
the following rules.

- if the InvocableHandlerMethod is present, the subscription name will
  take the form of handlerMethod.getBeanType().getName() + "#" +
  handlerMethod.getMethod().getName().
- otherwise, getClass().getName() is used, which is analogous to the
  previous behavior.

Closes gh-29902
2023-01-30 19:52:15 +01:00
Sam Brannen 40d2466334 Fix build due to Jackson Javadoc publication changes
The Jackson project no longer publishes Javadoc at
https://fasterxml.github.io which breaks the `javadoc` and `api` build
tasks due to their dependency on that web site for external Javadoc links.

As a workaround, we now reference Jackson's Javadoc via
https://www.javadoc.io.

See https://github.com/FasterXML/jackson-databind/issues/3440
Closes gh-29895
2023-01-29 12:43:11 +01:00
Sam Brannen 3d6d853bbc Include all Hibernate methods in SharedEntityManagerCreator's queryTerminatingMethods
Prior to this commit, we included Hibernate's Query.list() method in
SharedEntityManagerCreator's queryTerminatingMethods set but did not
include all of Hibernate's query-terminating methods.

To address this, this commit additionally includes the stream(),
uniqueResult(), and uniqueResultOptional() methods from Hibernate's
Query API in SharedEntityManagerCreator's query-terminating methods set.

Closes gh-29888
2023-01-28 20:59:46 +01:00
Sam Brannen 90ea39cc6b Update copyright headers 2023-01-28 20:49:13 +01:00
Arjen Poutsma 21c3d4f4a9 Support Jetty 10 in JettyClientHttpRequest
Though Jetty 10 was previously supported in the JettyClientHttpResponse,
this commit ensures support in the JettyClientHttpRequest.

Closes gh-29867
See gh-26123
2023-01-26 17:27:57 +01:00
Simon Baslé de53d77344 DatabaseClient uses SQL Supplier more lazily
This commit modifies the `DefaultDatabaseClient` implementation in order
to ensure lazier usage of the `Supplier<String>` passed to the sql
method (`DatabaseClient#sql(Supplier)`).

Since technically `DatabaseClient` is an interface that could have 3rd
party implementations, the lazyness expectation is only hinted at in the
`DatabaseClient#sql` javadoc.

Possible caveat: some log statements attempt to reflect the now lazily
resolved SQL string. Similarly, some exceptions can capture the SQL that
caused the issue if known. We expect that these always occur after the
execution of the statement has been attempted (see `ResultFunction`).
At this point the SQL string will be accessible and logs and exceptions
should reflect it as before. Keep an eye out for such strings turning
into `null` after this change, which would indicate the opposite.

Backport of d72df5ace4
See gh-29367
Closes gh-29887
2023-01-26 15:20:38 +01:00
Sébastien Deleuze e4e90bbec0 Polish RouterFunctionDsl KDoc 2023-01-23 13:27:34 +01:00
Sébastien Deleuze d0828be0cd Remove WebClientIntegrationTests#exchangeWithRelativeUrl outdated test
This test can fail when a web server runs on port 80 and
is not relevant anymore due to the removal of related feature
via 6e936a4081.

Closes gh-29863
2023-01-20 12:24:41 +01:00
Sébastien Deleuze 4a4b332709 Refine Jackson2ObjectMapperBuilder#configureFeature exception handling
This commit changes the FatalBeanException previously thrown for
an IllegalArgumentException which seems more suitable for that
use case.

Closes gh-29860
2023-01-20 10:15:49 +01:00
Brian Clozel 33f1c9b614 Upgrade Gradle Enterprise & Conventions plugins
This is required to adapt to the repo.spring.io permission changes.
2023-01-19 11:34:05 +01:00
Arjen Poutsma 53ac812fb0 Updated sdkmanrc 2023-01-19 10:05:36 +01:00
Arjen Poutsma 60c89dd2df Fix IllegalStateException in empty ProducesRequestCondition
When comparing empty ProducesRequestCondition, compareTo would throw an
IllegalStateException if the Accept header was invalid. This commit
fixes that behavior.

See gh-29794
Closes gh-29836
2023-01-18 10:45:12 +01:00
Minsoo Cheong(Merlin) 4bd2531774 Fix R2dbcTransactionManager debug log: don't log a Mono (#29800)
When logging the current connection inside R2dbcTransactionManager
doBegin, the mono object was logged instead of the connection lambda
parameter.

Other similar debug-level logs do use the actual Connection object,
so this commit does the same.

Backport of gh-29800
Closes gh-29824
2023-01-16 11:30:35 +01:00
Spring Builds 4fd5630700 Next development version (v5.3.26-SNAPSHOT) 2023-01-11 11:19:35 +00:00
Juergen Hoeller 26cd33cb2b Upgrade to Reactor 2020.0.27
Includes HtmlUnit 2.69, AssertJ 3.24.1, Checkstyle 10.6

Closes gh-29798
2023-01-11 00:23:38 +01:00
Juergen Hoeller 2ee393ae71 Upgrade to Tomcat 9.0.70, Jetty 9.4.50, Netty 4.1.86, Undertow 2.2.22, HtmlUnit 2.67, Mockito 4.9, AssertJ 3.23.1, Checkstyle 10.5 2022-12-23 15:52:09 +01:00
Juergen Hoeller 0815d29e45 Defensive check for null returned from createConnection()
Closes gh-29706
2022-12-23 15:51:37 +01:00
Brian Clozel 777f01d786 Fix path within mapping when pattern contains ".*"
Prior to this commit, extracting the path within handler mapping would
result in "" if the matching path element would be a Regex and contain
".*". This could cause issues with resource handling if the handler
mapping pattern was similar to `"/folder/file.*.extension"`.

This commit introduces a new `isLiteral()` method in the `PathElement`
abstract class that expresses whether the path element can be compared
as a String for path matching or if it requires a more elaborate
matching process.

Using this method for extracting the path within handler mapping avoids
relying on wildcard count or other properties.

See gh-29712
Fixes gh-29716
2022-12-19 10:53:02 +01:00
Sam Brannen f8fea013fc Update Jakarta Mail info in ref docs
Closes gh-29708
2022-12-17 14:18:42 +01:00
Sam Brannen 916539178b Improve documentation for literals in SpEL expressions
Closes gh-29701
2022-12-16 14:51:48 +01:00
Sam Brannen fdf3bcc9d9 Remove obsolete AttributeMethods.hasOnlyValueAttribute() method
See gh-29685
2022-12-13 15:52:01 +01:00
Sam Brannen 5ddc984192 Support repeatable annotation containers with multiple attributes
Prior to this commit, there was a bug in the implementation of
StandardRepeatableContainers.computeRepeatedAnnotationsMethod() which
has existed since Spring Framework 5.2 (when
StandardRepeatableContainers was introduced). Specifically,
StandardRepeatableContainers ignored any repeatable container
annotation if it declared attributes other than `value()`. However,
Java permits any number of attributes in a repeatable container
annotation.

In addition, the changes made in conjunction with gh-20279 made the bug
in StandardRepeatableContainers apparent when using the
getMergedRepeatableAnnotations() or findMergedRepeatableAnnotations()
method in AnnotatedElementUtils, resulting in regressions for the
behavior of those two methods.

This commit fixes the regressions and bug by altering the logic in
StandardRepeatableContainers.computeRepeatedAnnotationsMethod() so that
it explicitly looks for the `value()` method and ignores any other
methods declared in a repeatable container annotation candidate.

See gh-29685
Closes gh-29686
2022-12-13 15:47:13 +01:00
Sam Brannen b2ce54e7f1 Revise RepeatableContainersTests 2022-12-13 15:47:13 +01:00
Juergen Hoeller 937ab5f4b2 Polishing (aligned with main) 2022-12-13 12:06:09 +01:00
Juergen Hoeller 064c618050 Drop SQLExceptionSubclassFactory and unify SQLStateSQLExceptionTranslator tests 2022-12-13 12:05:35 +01:00
Juergen Hoeller 8c80ec1138 Avoid NPE on BeanDescriptor access with SimpleBeanInfoFactory
Closes gh-29681

(cherry picked from commit d74191427e)
2022-12-13 11:43:43 +01:00
rstoyanchev 912fa7602a Improve invalid Content-Type handling in WebFlux
Closes gh-29565
2022-12-09 11:53:16 +00:00
rstoyanchev 525fc7a27e Optimize object creation PartialMatchHelper
Closes gh-29667
2022-12-09 11:27:03 +00:00
Sam Brannen 72285034ba Support arrays in AST string representations of SpEL expressions
Prior to this commit, SpEL's ConstructorReference did not provide
support for arrays when generating a string representation of the
internal AST. For example, 'new String[3]' was represented as 'new
String()' instead of 'new String[3]'.

This commit introduces support for standard array construction and array
construction with initializers in ConstructorReference's toStringAST()
implementation.

Closes gh-29666
2022-12-08 23:23:01 -05:00
Sam Brannen 933474000b Polishing 2022-12-08 18:45:02 -05:00
Sam Brannen 4e8aebcde7 Fix SpEL support for quotes within String literals
Prior to this commit, there were two bugs in the support for quotes
within String literals in SpEL expressions.

- Two double quotes ("") or two single quotes ('') were always replaced
  with one double quote or one single quote, respectively, regardless
  of which quote character was used to enclose the original String
  literal. This resulted in the loss of one of the double quotes when
  the String literal was enclosed in single quotes, and vice versa. For
  example, 'x "" y' became 'x " y'.

- A single quote which was properly escaped in a String literal
  enclosed within single quotes was not escaped in the AST string
  representation of the expression. For example, 'x '' y' became 'x ' y'.

This commit fixes both of these related issues in StringLiteral and
overhauls the structure of ParsingTests.

Closes gh-29604
Closes gh-28356
2022-12-07 16:03:49 -05:00
Sam Brannen dff5b1ff8e Polishing 2022-12-07 15:59:08 -05:00
Sam Brannen fa0a4a0a46 Improve Javadoc for SqlLobValue 2022-12-07 15:58:56 -05:00
Sam Brannen 41a6b7ec20 Update copyright headers for source code changed since August 2022
The changes in this commit were performed using the newly introduced
update_copyright_headers.sh script.
2022-12-03 17:23:21 -05:00
Sam Brannen cfaa4ba89c Apply update_copyright_headers.sh to staged files as well 2022-12-03 17:23:21 -05:00
Sam Brannen 598e9d586b Introduce update_copyright_headers.sh shell script
In order to automate maintenance of copyright headers in our source
code (especially when merging PRs from external contributors), this
commit introduces an update_copyright_headers.sh script (tested on
mac OS) that will update the copyright headers of all Java, Kotlin,
and Groovy source files that have been added or modified this year
(or at least as far back as the git log history supports it).

For example, running this script currently outputs the following.

Updating copyright headers in Java, Kotlin, and Groovy source code for year 2022
warning: log for 'main' only goes back to Tue, 16 Aug 2022 16:24:55 +0200
2022-12-03 17:23:21 -05:00
Sam Brannen 750a8b359f Stop using Mockito to spy() on JDK I/O streams
When running on JDK 16+, we are not able to spy() on JDK types. To
address this, this commit stops using Mockito to spy on JDK I/O streams
(such as ByteArrayInputStream and ByteArrayOutputStream).
2022-12-03 17:23:21 -05:00
Sam Brannen c838bcff3a Fix/Disable JMX & JNDI tests on JDK 16+ 2022-12-03 17:23:21 -05:00
Sam Brannen 109b00d24d Avoid use of deprecated Character/Double constructors in tests 2022-12-03 17:23:21 -05:00
Sam Brannen b6abf45a56 Introduce @Suite classes for individual modules 2022-12-03 16:32:27 -05:00
Juergen Hoeller 2d94b43faa Polishing 2022-12-02 11:15:03 +01:00
Sam Brannen f7f73439ab Modify MBeanTestUtils to work on JDK 17+ 2022-11-30 14:55:15 +01:00
Sam Brannen 5e55558a93 Fix SockJsServiceTests
See gh-29594
2022-11-28 17:12:08 +01:00
Sam Brannen eee50d3b8a Polishing 2022-11-28 17:06:22 +01:00
Sam Brannen 92af390ed2 Polish contribution
See gh-29594
2022-11-28 17:02:53 +01:00
Aashay Chapatwala 332d2a36bb Add title to SockJS iFrames for accessibility compliance
Closes gh-29594
2022-11-28 17:02:01 +01:00
Brian Clozel 92b2b828f5 Fix Java 17 test CI and remove Java 11 variant
This commit fixes configuration and runtime issues with the Java 17 test
CI variant and removes the Java 11 one, now that Spring Framework 5.3.x
is in maintenance mode.
2022-11-28 10:17:56 +01:00
Juergen Hoeller a11222f681 Polishing 2022-11-25 17:58:59 +01:00
Juergen Hoeller 7de8d81932 Explicit documentation notes on standard Java reflection
See gh-29531
2022-11-24 14:25:43 +01:00
Juergen Hoeller 0e33537d9d Consistent use of DefaultParameterNameResolver in tests 2022-11-23 11:17:58 +01:00
Sébastien Deleuze 00da70e26b Fix some typos in Kotlin WebClient example code
Closes gh-29542
2022-11-22 08:35:50 +01:00
Sam Brannen 72b44cebea Catch Error for SourceHttpMessageConverter in WebMvcConfigurationSupport
Prior to this commit, the addDefaultHttpMessageConverters() method in
WebMvcConfigurationSupport caught Throwable for SourceHttpMessageConverter
instantiation; whereas, the rest of the code base correctly catches Error
for SourceHttpMessageConverter instantiation (to handle errors such as
NoClassDefFoundError).

Throwable should not be caught since it can mask other categories of
failures (such as configuration errors).

This commit therefore switches to catching Error for SourceHttpMessageConverter
instantiation in WebMvcConfigurationSupport.

Closes gh-29537
2022-11-21 17:37:22 +01:00
Marten Deinum 1ee3777ac7 Fix link to Bean Utils Light Library in BeanUtils Javadoc
The URL for the BULL library has changed (not sure when, probably way back).

This updates it to the correct location.

Closes gh-29534, gh-29536
2022-11-21 17:25:50 +01:00
divcon cad6e8756d Fix link to WebFlux section in reference manual
Closes gh-29526
2022-11-19 14:51:03 +01:00
Sam Brannen c7bd685c54 Polishing 2022-11-19 14:49:26 +01:00
Sam Brannen 4f472d2ac4 Remove TODOs in WebFlux ref docs 2022-11-19 14:49:07 +01:00
Stephane Nicoll a18842b72b Fix link to WebFlux section
Closes gh-29517
2022-11-18 10:48:05 +01:00
Spring Builds a41f97bc2b Next development version (v5.3.25-SNAPSHOT) 2022-11-16 08:07:01 +00:00
Sam Brannen 8e64701cb7 Fix Javadoc formatting issue in TestSocketUtils 2022-11-15 14:47:00 +01:00
Sam Brannen ae9a9e3c06 Document TestSocketUtils in the testing chapter 2022-11-15 14:43:56 +01:00
Juergen Hoeller c94025699f Upgrade to Reactor 2020.0.25
See gh-29464
2022-11-15 13:11:32 +01:00
Juergen Hoeller ec3f59e6fe Allow AutoCloseable dereferences on original AutoCloseable beans
Closes gh-29480
2022-11-14 23:37:05 +01:00
Juergen Hoeller 49ee4a4fdf Deprecated unused findAutowireCandidates template method (removed in 6.0)
See gh-29487
2022-11-14 23:35:47 +01:00
Sam Brannen 698f8995f7 Revise TestSocketUtils and tests
Closes gh-29132
2022-11-14 20:26:58 +01:00
Chris Bono ee51dab1f3 Introduce TestSocketUtils as a replacement for SocketUtils
SocketUtils was officially deprecated in 5.3.16 (gh-28052) and removed
in 6.0 M3 (gh-28054); however, there is still need for a subset of this
functionality in integration tests for testing scenarios in which it is
not possible for the system under test to select its own random port
(or rely on the operating system to provide an ephemeral port).

This commit therefore introduces a scaled down version in the
spring-test module called TestSocketUtils which supports retrieval of a
single TCP port.

See gh-29132
2022-11-14 20:26:58 +01:00
Sam Brannen 743a96b75e Polish SocketUtilsTests 2022-11-14 20:26:58 +01:00
Sébastien Deleuze b766a49a4d Support suspending functions returning Unit in WebFlux
Closes gh-27629
2022-11-13 19:05:29 +01:00
67 3ff308403a Fix two typos in integration.adoc and webflux.adoc
- Change "you ca" to "you can" in webflux.adoc

- English names can be used in "month" field instead of "day-of-month"
  field in cron expressions in integration.adoc

Closes gh-29469
2022-11-11 17:11:16 +01:00
Sam Brannen 27f3feea1a Ensure SpEL ternary and Elvis expressions are enclosed in parentheses in toStringAST()
Prior to this commit, ternary and Elvis expressions enclosed in
parentheses (to account for operator precedence) were properly parsed
and evaluated; however, the corresponding toStringAST() implementations
did not enclose the results in parentheses. Consequently, the string
representation of the ASTs did not reflect the original semantics of
such expressions.

For example, given "(4 % 2 == 0 ? 1 : 0) * 10" as the expression to
parse and evaluate, the result of toStringAST() was previously
"(((4 % 2) == 0) ? 1 : 0 * 10)" instead of
"((((4 % 2) == 0) ? 1 : 0) * 10)", implying that 0 should be multiplied
by 10 instead of multiplying the result of the ternary expression by 10.

This commit addresses this by ensuring that SpEL ternary and Elvis
expressions are enclosed in parentheses in toStringAST().

Closes gh-29463
2022-11-11 17:11:07 +01:00
Sam Brannen b42b785cd1 Polish ParsingTests 2022-11-11 17:10:57 +01:00
rstoyanchev f9d8367379 Exclude URL query from checkpoint in DefaultWebClient
Closes gh-29148
2022-11-11 13:29:36 +00:00
rstoyanchev 09b19d7aa6 Update RestTemplate Javadoc
Closes gh-29311
2022-11-11 12:16:02 +00:00
rstoyanchev 8ade083a05 Filter out null WebSocketSession attributes
Closes gh-29315
2022-11-11 11:20:18 +00:00
rstoyanchev db9e89fba9 Update docs on web controller method return values
Closes gh-29349
2022-11-11 11:03:24 +00:00
Juergen Hoeller d7d44c6c51 Polishing 2022-11-10 18:26:49 +01:00
Juergen Hoeller 330d2a5982 Upgrade to Reactor 2020.0.24
Includes Netty 4.1.85, Tomcat 9.0.68, Jetty 9.4.49, Jetty Reactive HttpClient 1.1.13, Undertow 2.2.21, SmallRye Mutiny 1.8, Log4J 2.19, OpenPDF 1.3.30, Mockito 4.8.1, HtmlUnit 2.66, Checkstyle 10.4

Closes gh-29464
2022-11-10 18:25:55 +01:00
Juergen Hoeller 86fbb8678a Use unquoted value in assertion message in MediaType.checkParameters()
Closes gh-29461
2022-11-10 18:24:57 +01:00
Christoph Dreis 55b258f2de Avoid unnecessary allocations in StompDecoder#unescape
Closes gh-29443
2022-11-08 18:10:54 +01:00
Sam Brannen f4b3333fa8 Avoid reflection for annotation attribute method invocations
As a follow up to 332b25b680, this commit consistently avoids the use of
reflection for annotation attribute method invocations.

See gh-29301
Closes gh-29448
2022-11-08 16:23:33 +01:00
Sam Brannen e5878ab15b Fix precondition assertions 2022-11-08 12:08:08 +01:00
Sam Brannen dedbbf0a79 Avoid warnings in tests 2022-11-08 12:04:56 +01:00
Sam Brannen 5f02323b9c Avoid String allocations with Assert.isTrue() 2022-11-05 14:40:45 +01:00
Sam Brannen 902cdd1a2f Ignore spring-core-test from main branch in nohttp checks 2022-11-05 14:39:50 +01:00
Sam Brannen deabd66939 Avoid String allocations with Assert.state() 2022-11-04 16:24:59 +01:00
Christoph Dreis 2a853aea67 Avoid String allocations in MediaType.checkParameters
Closes gh-29428
2022-11-04 16:24:59 +01:00
Sam Brannen a281d8c3fd Polishing 2022-11-04 16:24:59 +01:00
Sam Brannen 638d91f5f4 Ignore framework-docs from main branch in nohttp check 2022-11-04 16:22:01 +01:00
Sam Brannen 6abfe041b1 Ignore /framework-docs/build folder from main branch 2022-11-02 15:32:16 +01:00
Roy Lee 462d33e68d Fix typo in WebSocket reference doc regarding subscription header
Closes gh-29228
2022-11-02 15:28:43 +01:00
Steve Gerhardt fded79d807 Make SimpleMailMessage setters parameters nullable
Closes gh-29139
2022-11-02 12:18:03 +01:00
Sébastien Deleuze c14cbd07f4 Use non-null DateFormat for CustomDateEditor in tests
Closes gh-29419
2022-11-02 12:01:49 +01:00
Christoph Dreis 58bb6e7181 Reduce allocations caused by producible media types
Closes gh-29412
2022-11-02 11:15:26 +01:00
David Costanzo e1df056059 Fix typo: "as describe in" -> "as described in" 2022-10-31 09:07:39 +01:00
Arjen Poutsma 46329851c1 Ensure state of PartGenerator accepts buffers
This commit makes sure that the current state of the PartGenerator
is able to handle an incoming buffer, possibly requested because of
a request coming from the subscription. All states accept new buffers
except the WritingFileState.

Closes gh-29227
2022-10-27 12:12:57 +02:00
Arjen Poutsma 51d109de30 Updated sdkmanrc 2022-10-27 12:03:34 +02:00
rstoyanchev 3d89acf9ea Adjust checkForLeaks timeout settings
LeakAwareDataBufferFactory#checkForLeaks automatically waits up to 5
sec for buffers to be released, which could be used as a way of
awaiting on some async logic to complete, and as long as buffers are
released, it shouldn't be long. However, the leak test in
LeakAwareDataBufferFactoryTests actually expects to find a leak, and
always ends up waiting the full 5 seconds.

This change, makes the wait configurable, with the no-arg method
using 0 (no waiting). AbstractLeakCheckingTests uses 1 second by
default since ResourceRegionEncoderTests did fail locally. If more
tests need this, we can adjust the settings.
2022-10-24 10:55:39 +01:00
Brian Clozel 9410998897 Add caching headers to If-Unmodified-Since responses
Conditional requests using "If-Unmodified-Since" headers are generally
used as precondition checks for state-changing methods (POST, PUT,
DELETE). See https://datatracker.ietf.org/doc/html/rfc7232#section-3.4
The spec also allows for idempotent methods like GET and HEAD.

Prior to this commit, the "If-Unmodified-Since" processing done in
`checkNotModified` (see `ServletWebRequest` and
`DefaultServerWebExchange`) would only focus on the state changing
methods and not take into account the safe methods. For those cases, the
"ETag" and "Last-Modified" would be missing from the response.

This commit ensures that such headers are added as expected in these
cases.

Fixes gh-29362
2022-10-21 15:11:08 +02:00
Mikk Raudvere 12cc8a9f07 Fix typos
Closes gh-29364
2022-10-21 09:35:38 +02:00
Juergen Hoeller 4c38777064 Explain logger name semantics (see AbstractTraceInterceptor.setLoggerName)
See gh-28678
2022-10-19 14:49:27 +02:00
Vedran Pavic fb291379e4 Avoid use of Commons Logging in LoggingCacheErrorHandler public API
At present, creating LoggingCacheErrorHandler with custom logger requires use of Commons Logging API, as the appropriate constructor expects org.apache.commons.logging.Log instance. As Commons Logging is rarely the logging framework of choice in applications these days, interaction with its API might not be desirable.

This commit adds LoggingCacheErrorHandler constructor that accepts logger name and thus avoids leaking out any details about the underlying logging framework.
2022-10-19 13:48:59 +02:00
Juergen Hoeller 182ba4ac29 Upgrade to Checkstyle 10.3.4 2022-10-18 23:05:10 +02:00
Juergen Hoeller dbcfeb8f4f Aligned with PathMatchingResourcePatternResolverTests on main
See gh-29333
2022-10-18 23:04:44 +02:00
Juergen Hoeller 6f64cfd1e5 Test square brackets with index/key expressions
See gh-27925
2022-10-18 23:04:23 +02:00
Sam Brannen 652781c4a1 Test status quo in 5.3.x for PathMatchingResourcePatternResolver
See gh-29333
2022-10-18 17:51:29 +02:00
Juergen Hoeller 8e25e32eb8 Polishing 2022-10-18 16:17:30 +02:00
Juergen Hoeller 4b0bf16389 Select ambiguous write method based on read method (matching its return type)
Also avoids unnecessary checks in name-based PropertyDescriptor constructor.

See gh-29320
2022-10-18 16:17:03 +02:00
Juergen Hoeller 33023b240f Provide optional SimpleBeanInfoFactory for better introspection performance
Closes gh-29330
2022-10-17 12:25:53 +02:00
Juergen Hoeller c407dc3df8 Reset/rebuild BeanPostProcessorCache within full synchronization
Closes gh-29299
2022-10-17 12:25:35 +02:00
Sébastien Deleuze 1439c5bb8f Document how to use WebJars without webjars-locator-core dependency
Closes gh-29322
2022-10-16 20:28:57 +02:00
Stephane Nicoll 3f42d4de43 Upgrade Ubuntu version in CI image 2022-10-13 11:29:31 +02:00
Sam Brannen 5ac687f4aa Add warning to AnnotatedElementUtils.getMergedRepeatableAnnotations()
See gh-20279
2022-10-11 20:49:19 +02:00
Sam Brannen 332b25b680 Support searches for non-public repeatable annotations
Prior to this commit, searches for non-public repeatable annotations
failed with error messages similar to the following, since the
repeatable annotation's container's `value()` method could not be
invoked via reflection.

JDK 8:

java.lang.IllegalAccessError: tried to access class
org.springframework.core.annotation.NestedRepeatableAnnotationsTests$A
from class com.sun.proxy.$Proxy12

JDK 17:

java.lang.IllegalAccessError: failed to access class
org.springframework.core.annotation.NestedRepeatableAnnotationsTests$A
from class jdk.proxy2.$Proxy12
(org.springframework.core.annotation.NestedRepeatableAnnotationsTests$A
is in unnamed module of loader 'app'; jdk.proxy2.$Proxy12 is in module
jdk.proxy2 of loader 'app')

This commit makes it possible to search for non-public repeatable
annotations by first attempting to invoke the repeatable annotation's
container's `value()` method via the container's InvocationHandler (if
the container is a JDK dynamic proxy) and then falling back to
reflection for the method invocation if an error occurs (such as a
SecurityException).

Closes gh-29301
2022-10-11 19:27:40 +02:00
Sam Brannen 9876701493 Support nesting in AnnotatedElementUtils.getMergedRepeatableAnnotations()
This commit is a follow up to 828f74f71a
and applies to same fix for getMergedRepeatableAnnotations().

See the previous commit for details.

Closes gh-20279
2022-10-11 18:06:00 +02:00
Sam Brannen 828f74f71a Support nesting in AnnotatedElementUtils.findMergedRepeatableAnnotations()
Prior to this commit, the findMergedRepeatableAnnotations() methods in
AnnotatedElementUtils failed to find repeatable annotations declared
on other repeatable annotations (i.e., when one repeatable annotation
type was used as a meta-annotation on a different repeatable annotation
type).

The reason is that
findMergedRepeatableAnnotations(element, annotationType, containerType)
always used RepeatableContainers.of(annotationType, containerType) to
create a RepeatableContainers instance, even if the supplied
containerType was null. Doing so restricts the search to supporting
only repeatable annotations whose container is the supplied
containerType and prevents the search from finding repeatable
annotations declared as meta-annotations on other types of repeatable
annotations.

Note, however, that direct use of the MergedAnnotations API already
supported finding nested repeatable annotations when using
RepeatableContainers.standardRepeatables() or
RepeatableContainers.of(...).and(...).and(...). The latter composes
support for multiple repeatable annotation types and their containers.

This commit addresses the issue for findMergedRepeatableAnnotations()
when the containerType is null or not provided.

However, findMergedRepeatableAnnotations(element, annotationType, containerType)
still suffers from the aforementioned limitation, and the Javadoc has
been updated to make that clear.

Closes gh-20279
2022-10-11 17:21:28 +02:00
Sam Brannen 965dd66f8c Improve Javadoc for RepeatableContainers 2022-10-11 16:41:19 +02:00
Sam Brannen b71d95df71 Document how to switch to the default set of TestExecutionListeners
Closes gh-29281
2022-10-08 16:20:55 +02:00
Sam Brannen b20de758b2 Support custom status code in ExchangeResult for WebTestClient
Prior to this commit, ExchangeResult.assertWithDiagnostics() threw an
IllegalArgumentException for a custom HTTP status code since toString()
invoked getStatus() without a try-catch block.

This commit addresses this issue by introducing a formatStatus() method
that defensively formats the response status, initially trying to
format the HttpStatus and falling back to formatting the raw integer
status code.

Closes gh-29283
2022-10-08 15:45:24 +02:00
Johnny Lim 1c1a0afbed Use AssertJ static imports consistently in 5.3.x
Closes gh-29282
2022-10-08 13:57:21 +02:00
Sam Brannen a599601dd9 Document how to switch to the default set of TestExecutionListeners
Closes gh-29281
2022-10-07 17:58:22 +02:00
Sam Brannen 5eee4673c1 Document limitation of AopTestUtils.getUltimateTargetObject() regarding non-static TargetSource
Closes gh-29276
2022-10-07 16:09:39 +02:00
Sam Brannen 8caed88c14 Test status quo for URI/URL for scanned filesystem resources
See gh-29275
2022-10-07 12:17:27 +02:00
Sam Brannen 3dc60f1627 Backport changes to PathMatchingResourcePatternResolverTests 2022-10-07 11:01:02 +02:00
Sam Brannen fee38175b3 Revert "Test encoding and Unicode normalization for scanned resources"
This reverts commit eb2c1cbcd4.
2022-10-04 14:29:22 +02:00
Sam Brannen eb2c1cbcd4 Test encoding and Unicode normalization for scanned resources
This commit introduces tests which serve as "regression tests" for the
behavior of PathMatchingResourcePatternResolver in Spring Framework
5.3.x with regard to URL-encoding and Unicode normalization of resource
paths.

Specifically, the new tests demonstrate that resource paths do NOT need
to be decoded or normalized in 5.3.x.

See gh-29243
2022-10-04 13:19:59 +02:00
Brian Clozel 8d0ac214f3 Configure more memory for checkstyleNohttp
See https://docs.gradle.org/7.5/release-notes.html#checkstyle-tasks-use-toolchains-and-execute-in-parallel-by-default
2022-10-04 13:08:08 +02:00
Sam Brannen 7241c30141 Backport changes to PathMatchingResourcePatternResolverTests 2022-10-04 11:48:29 +02:00
Brian Clozel 777caef4f7 Upgrade to Gradle 7.5.1 2022-09-30 14:35:31 +02:00
Brian Clozel 9465110917 Polish
See gh-26707
2022-09-26 22:25:44 +02:00
chenrl b71e686cbd Fix ServletContextResource isFile check
Prior to this commit, `ServletContextResource` could rely on
`ServletContext#getRealPath` to check whether a resource exists.
This behavior is not enforced on some Servlet containers, as this method
is only meant to translate virtual paths to real paths, but not
necessarily check for the existence of the file.

See https://bz.apache.org/bugzilla/show_bug.cgi?id=55837#c3 for a
rationale of this behavior in Tomcat.

This commit enforces an additional check, resolving the path as a `File`
and checking that is exists and is a file.

Closes gh-26707
2022-09-26 22:20:15 +02:00
Stephane Nicoll 433a23a0bd Merge pull request #29190 from dreis2211
* pr/29190:
  Polish "Avoid resizing of Maps created by CollectionUtils"
  Avoid resizing of Maps created by CollectionUtils

Closes gh-29190
2022-09-26 09:06:52 +02:00
Stephane Nicoll 7309fe9f2e Polish "Avoid resizing of Maps created by CollectionUtils"
See gh-29190
2022-09-26 09:00:45 +02:00
Christoph Dreis 874a296a76 Avoid resizing of Maps created by CollectionUtils
See gh-29190
2022-09-26 08:54:52 +02:00
Stephane Nicoll d872e7c326 Merge pull request #29198 from izeye
* pr/29198:
  Use actions/checkout@v3 for Gradle Wrapper Validation Action

Closes gh-29198
2022-09-26 08:52:30 +02:00
Johnny Lim 4ca574cde1 Use actions/checkout@v3 for Gradle Wrapper Validation Action
See gh-29198
2022-09-26 08:52:21 +02:00
Stephane Nicoll 98ecf0a412 Merge pull request #29201 from inabajunmr
* pr/29201:
  Fix MockMvc sample setup

Closes gh-29201
2022-09-26 08:50:49 +02:00
inaba jun ddef70935a Fix MockMvc sample setup
See gh-29201
2022-09-26 08:50:01 +02:00
Johnny Lim 1d0dc43e5f Upgrade to Gradle Enterprise Conventions Plugin 0.0.11
Closes gh-29165
2022-09-18 14:50:03 +02:00
Jerome Prinet d8e4dc967f Update Gradle Enterprise plugin to 3.11.1
Closes gh-29164
2022-09-16 17:56:23 +02:00
Sam Brannen f0f633d187 Limit exclude to core Spring Framework committers 2022-09-15 17:15:50 +02:00
Sam Brannen 4b7aa6bb39 Exclude core committers from generated changelog 2022-09-15 16:25:57 +02:00
Spring Builds 13933ee2c6 Next development version (v5.3.24-SNAPSHOT) 2022-09-15 07:59:36 +00:00
rstoyanchev ae8b7973b4 Improve Javadoc on RequestEntity#getUrl
Closes gh-28930
2022-09-14 19:25:55 +01:00
Juergen Hoeller a7f430bda8 Upgrade to Checkstyle 10.3.3, RxJava 3.1.5, SmallRye Mutiny 1.7, HtmlUnit 2.64, JsonPath 2.7 2022-09-14 19:28:27 +02:00
Juergen Hoeller 5a781eeb54 Upgrade to RSocket 1.1.3, Netty 4.1.82, Tomcat 9.0.65, Undertow 2.2.19, Hibernate Validator 6.2.5 2022-09-14 18:42:04 +02:00
Sam Brannen a879d18c9c Reintroduce Caucho exclusion for 5.3.x
See gh-28876
2022-09-14 17:10:17 +02:00
Marc Wrobel ce49068ff9 Fix links in Javadoc and reference docs
- Fix broken links (by using a new URL, an alternative URL, or a
  Wayback Machine link)

- Use HTTPS where possible

- Remove https://issuetracker.springsource.com/browse/EBR-349: this
  link is dead and is also mentioned in
  https://jira.spring.io/browse/SPR-8093

- Clean up nohttp allowlist.lines

Closes gh-28876
2022-09-14 17:00:11 +02:00
Sam Brannen 62a0ab3667 Polish contribution 2022-09-14 16:50:32 +02:00
Marc Wrobel 92a231cf91 Fix typos in Javadoc, reference docs, and code
Closes gh-28822
2022-09-14 16:45:34 +02:00
Sam Brannen 50dff77d01 Polish contribution 2022-09-14 16:08:01 +02:00
Marc Wrobel 0f479293b1 Replace use of the <tt> HTML tag in Javadoc
The <tt> HTML tag was used in HTML 4 to define teletype text. It is not
supported in HTML5, and its use is discouraged.

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tt

Closes gh-28819
2022-09-14 15:56:16 +02:00
Johnny Lim 5f5d383eeb Fix Javadoc since tag for AbstractGenericWebContextLoader.createContext()
See gh-28983
Closes gh-29154
2022-09-14 15:53:18 +02:00
Sam Brannen 529481c44c Polish contribution
See gh-29150
2022-09-14 14:35:43 +02:00
Jens Dietrich 35d379f9d3 Add missing @Nullable in SettableListenableFuture
Closes gh-29150
2022-09-14 14:32:37 +02:00
Brian Clozel c871758a51 Upgrade to Reactor 2020.0.23
Closes gh-29129
2022-09-13 21:35:11 +02:00
Stephane Nicoll 0d2bfc926f Apply consistent ordering in hierarchical contexts
Previously, if `@Order` is specified on a `@Bean` method, and the
candidate bean is defined in a parent context, its order wasn't taken
into account when retrieving the bean from a child context.

This commit makes sure the metadata of a bean is taken into
consideration in all cases.

Closes gh-29105
2022-09-13 07:23:22 +02:00
rstoyanchev 4e97776969 Polishing contribution
Closes gh-28715
2022-09-12 11:47:55 +01:00
Napster d42f950a36 Pass headers to STOMP receipt callbacks
See gh-28715
2022-09-12 10:55:12 +01:00
rstoyanchev 4eabe29b9a Polishing contribution
Closes gh-28785
2022-09-12 10:52:53 +01:00
npriebe cd10171f98 Make WebSocketConnectionManager#isConnected public
See gh-28785
2022-09-12 09:54:57 +01:00
jbotuck 597c687da8 Fix indentation in ref docs for RestTemplate
Closes gh-29014
2022-09-12 09:51:33 +01:00
Stephane Nicoll 081d70123e Start building against Reactor 2020.0.23 snapshots
See gh-29129
2022-09-10 09:44:11 +02:00
Stephane Nicoll d9c2ccb4b3 Upgrade Ubuntu version in CI image
Closes gh-29106
2022-09-08 10:57:36 +02:00
Stephane Nicoll c503f356c7 Merge pull request #29104 from boahc077
* pr/29104:
  Restrict permissions for GitHub action

Closes gh-29104
2022-09-08 09:04:15 +02:00
Ashish Kurmi 7f9933fdb7 Restrict permissions for GitHub action
See gh-29104
2022-09-08 09:03:47 +02:00
Brian Clozel a425512025 Polish
See gh-29050
2022-09-07 15:02:10 +02:00
Kevin Yue 298c9a6f1b Redirect response wrapper should commit response
This commit ensures that when using `sendRedirect`, the response wrapper
behaves correctly with regards to the Servlet specification:

1. reset the response buffer to clear any partially written response
2. set the expected response HTTP headers
3. flush the buffer to commit the response

Closes gh-29050
2022-09-07 14:59:15 +02:00
Stephane Nicoll 8dcb2a75fa Merge pull request #29048 from 1993heqiang
* pr/29048:
  Fix typo in data-access section

Closes gh-29048
2022-09-05 07:23:56 +02:00
heqiang 111a9902ac Fix typo in data-access section
See gh-29048
2022-09-05 07:21:31 +02:00
Sam Brannen 0389fcca7e Fix sporadically failing SpEL test 2022-09-02 16:41:44 +02:00
junsu bb3ada4a67 Fix Kotlin Serialization converter registration logic
This commit fixes Kotlin Serialization converter
registration logic in RestTemplate,
AbstractMessageBrokerConfiguration and
AllEncompassingFormHttpMessageConverter classes
to be similar to the one in
WebMvcConfigurationSupport.

Closes gh-29008
2022-09-02 11:17:51 +02:00
Sam Brannen 6a68bd58f9 Introduce AnnotationUtils.isSynthesizedAnnotation(Annotation)
Since SynthesizedAnnotation will be deprecated (and potentially
completely removed) in Spring Framework 6.0, this commit introduces
AnnotationUtils.isSynthesizedAnnotation(Annotation) in 5.3.x to allow
people to migrate away from relying on SynthesizedAnnotation.

Closes gh-29054
2022-09-01 17:35:22 +02:00
Sam Brannen b1414bf15b Polishing 2022-09-01 17:23:04 +02:00
Arjen Poutsma f91943977c RenderingResponse must set status code on RedirectView
This commit makes sure that WebFlux's RenderingResponse sets the HTTP
status code when rendering a RedirectView.

Closes: gh-28839
2022-08-30 15:14:03 +02:00
Arjen Poutsma 4c0ece944a Fix race condition in PartGenerator
This commit fixes a race condition in PartGenerator, used by
DefaultPartHttpMessageReader. The condition can occur when a
completion signal comes in, and the state is changed to IdleFileState
at the same time.

Closes gh-28963
2022-08-30 12:11:22 +02:00
Sam Brannen 2c75eb8745 Support @Nested tests in MockServerContainerContextCustomizerFactory
Prior to this commit, MockServerContainerContextCustomizerFactory did
not find @WebAppConfiguration on an enclosing class and therefore
failed to create a MockServerContainerContextCustomizer for a @Nested
test class.

This commit addresses this by using TestContextAnnotationUtils to
determine if the test class is "annotated" with @WebAppConfiguration.

Closes gh-29037
2022-08-28 18:41:27 +02:00
Sam Brannen 711820ec70 Introduce createContext() factory method in AbstractWebGenericContextLoader
Prior to this commit it was possible to configure the
DefaultListableBeanFactory used by the GenericWebApplicationContext
created by AbstractWebGenericContextLoader, but it was not possible to
completely replace the bean factory.

This commit introduces a new createContext() factory method in
AbstractWebGenericContextLoader which indirectly allows subclasses to
supply a custom DefaultListableBeanFactory implementation to the
GenericWebApplicationContext.

See gh-25600
Closes gh-28983
2022-08-21 15:05:23 +02:00
Sam Brannen 69d87f16ee Reorganize internals of DefaultCacheAwareContextLoaderDelegate 2022-08-21 15:02:28 +02:00
Sam Brannen 38f94799f4 Use andExpectAll() in example in MockMvc Javadoc 2022-08-19 16:05:31 +02:00
Sam Brannen 4264d0becd Fix example in MockMvc Javadoc 2022-08-19 16:02:10 +02:00
Arjen Poutsma 7e7d6b9c3a Propagate Context in DataBufferUtils::write(Path)
This commit makes sure that the Reactor context is propagated in
DataBufferUtils::write(Path).

Closes gh-28933
See gh-27517
2022-08-16 11:21:12 +02:00
Stephane Nicoll dfc06eda7a Upgrade Java 8 version in CI image and .sdkmanrc 2022-08-11 13:31:36 +02:00
Stephane Nicoll f0aa6ebed6 Merge pull request #28949 from izeye
* pr/28949:
  Polish "Add missing TreeSet to CollectionFactory.createCollection()"
  Add missing TreeSet to CollectionFactory.createCollection()

Closes gh-28949
2022-08-11 10:43:56 +02:00
Stephane Nicoll 6806aaf162 Polish "Add missing TreeSet to CollectionFactory.createCollection()"
See gh-28949
2022-08-11 08:28:43 +02:00
Johnny Lim ccec75c98d Add missing TreeSet to CollectionFactory.createCollection()
See gh-28949
2022-08-11 08:22:11 +02:00
Stephane Nicoll 22029b4487 Merge pull request #28944 from wilkinsona
* pr/28944:
  Correct description of @RequestParam with WebFlux

Closes gh-28944
2022-08-09 15:32:17 +02:00
Andy Wilkinson d6b60046ce Correct description of @RequestParam with WebFlux
See gh-28944
2022-08-09 15:30:08 +02:00
Stephane Nicoll 6685e78c36 Deprecate NestedIOException
NestedIOException has been removed in Spring Framework 6 and this commit
marks it as deprecated in 5.x. Users that were relying on this exception
should use IOException directly.

Closes gh-28929
2022-08-05 10:04:47 +02:00
Chanhyeong Cho 8685b2f5bf Fix broken kdoc-api links in kotlin.adoc
Fixes gh-28908
2022-08-04 11:02:02 +02:00
Stephane Nicoll 4af225405c Upgrade Java 18 version in CI image 2022-08-04 10:02:49 +02:00
Stephane Nicoll 51e594ae81 Upgrade Java 17 version in CI image 2022-08-04 10:02:15 +02:00
Stephane Nicoll c2554b2b27 Upgrade Java 11 version in CI image 2022-08-04 10:01:49 +02:00
Stephane Nicoll 86a762b5ee Upgrade Java 8 version in CI image 2022-08-04 10:01:23 +02:00
Stephane Nicoll 211241befe Upgrade Ubuntu version in CI image 2022-08-04 10:00:30 +02:00
Brian Clozel 0caa2ac696 Customize connection in UrlResource getInputStream
Prior to this commit, the `AbstractFileResolvingResource` would
provide a default implementation for `customizeConnection` which only
sets the HTTP request method as "HEAD".
While this is consistent with its usage within that class (in
`exists()`, `contentLength()` or `lastModified()`), this is not opened
for general usage by sub-classes.

`UrlResource` is an example of that, where its `getInputStream()` method
does not call this customization method.

This not only prevents implementations from calling
`customizeConnection` in various cases, but it also misleads developers
as they might think that customizations will be applied automatically.

This commit ensures that `customizeConnection` is called in all relevant
places and that the configuration of the HTTP method is instead done in
each method as it is use case specific.

Fixes gh-28909
2022-08-03 23:13:52 +02:00
Stephane Nicoll 4eb8a5c082 Merge pull request #28914 from izeye
* pr/28914:
  Fix Javadoc since for new modules() and modulesToInstall()

Closes gh-28914
2022-08-02 16:11:04 +02:00
Johnny Lim d080b64907 Fix Javadoc since for new modules() and modulesToInstall()
See gh-28914
2022-08-02 16:10:47 +02:00
Stephane Nicoll 5ab55dfb64 Merge pull request #28183 from luvarqpp
* pr/28183:
  Polish "Improve documentation of Cacheable"
  Improve documentation of Cacheable

Closes gh-28183
2022-07-29 18:06:57 +02:00
Stephane Nicoll 04209def46 Polish "Improve documentation of Cacheable"
Apply the same improvements to CacheEvict and CachePut.

See gh-28183
2022-07-29 18:04:23 +02:00
luvarqpp 3a61930bd0 Improve documentation of Cacheable
See gh-28183
2022-07-29 17:57:15 +02:00
Stephane Nicoll 456c7889a3 Merge pull request #28488 from arend-von-reinersdorff
* pr/28488:
  Polish "Clarify docs on JNDI properties in Servlet environment"
  Clarify docs on JNDI properties in Servlet environment

Closes gh-28488
2022-07-29 17:13:42 +02:00
Stephane Nicoll 982d8ea84a Polish "Clarify docs on JNDI properties in Servlet environment"
See gh-28488
2022-07-29 17:09:55 +02:00
Arend v. Reinersdorff 67eb2bbf19 Clarify docs on JNDI properties in Servlet environment
See gh-28488
2022-07-29 17:05:58 +02:00
Stephane Nicoll a6596e2446 Merge pull request #28780 from vpavic
* pr/28780:
  Add missing nullability annotations to ResponseCookie

Closes gh-28780
2022-07-29 17:01:19 +02:00
Vedran Pavic 812b089f1d Add missing nullability annotations to ResponseCookie
See gh-28780
2022-07-29 16:54:37 +02:00
Rossen Stoyanchev 2172b99fee Polishing contribution
Closes gh-28836
2022-07-29 15:24:17 +03:00
floriankirmaier b6144e5682 Improve setting of WebSocket error status
See gh-28836
2022-07-29 15:07:15 +03:00
Rossen Stoyanchev 6e6f8637d1 Polishing contribution
Closes gh-28771
2022-07-29 14:45:42 +03:00
Johnny Lim 00f7f5ff0a Use MediaType.APPLICATION_FORM_URLENCODED_VALUE
See gh-28771
2022-07-29 14:40:45 +03:00
Arjen Poutsma 3d4a778b73 Fix KDoc API link 2022-07-29 11:08:57 +02:00
Stephane Nicoll 446c1add4f Merge pull request #28885 from edfeff
* pr/28885:
  Upgrade copyright year of changed file
  Fix typo in Javadoc of AbstractEncoder

Closes gh-28885
2022-07-29 09:31:42 +02:00
Stephane Nicoll aef4b0ec5a Upgrade copyright year of changed file
See gh-28885
2022-07-29 09:29:58 +02:00
wpp 675e0b94c1 Fix typo in Javadoc of AbstractEncoder
See gh-28885
2022-07-29 09:29:35 +02:00
Arjen Poutsma b8b54ee524 Ensure WebClient exceptions are serializable
Not all HttpHeaders implementations are serializable. This commit
ensures that WebClientRequestException and WebClientResponseException
are serializable, by copying any non-serializable HttpHeaders into a
new, serializable, instance.

Closes gh-28321
2022-07-28 14:09:11 +02:00
Arjen Poutsma 97ea8a6789 Copy HttpHeaders to ensure serializability
Not all HttpHeaders implementations are serializable. This commit
ensures that WebClientRequestException and WebClientResponseException
are serializable, by copying any non-serializable HttpHeaders into a
new, serializable, instance.

Closes gh-28321
2022-07-28 13:55:43 +02:00
Stephane Nicoll 95a400abfb Merge pull request #28867 from arvyy
* pr/28867:
  Add missing closing parenthesis

Closes gh-28867
2022-07-25 13:32:13 +02:00
arvyy 4383a673bb Add missing closing parenthesis
See gh-28867
2022-07-25 13:30:45 +02:00
Arjen Poutsma f7b94fc3e8 Updated sdkmanrc 2022-07-25 12:21:58 +02:00
Stephane Nicoll 93760d1211 Merge pull request #28853 from marcwrobel
* pr/28853:
  Polish "Deprecate SockJsServiceRegistration#setSupressCors"
  Deprecate SockJsServiceRegistration#setSupressCors

Closes gh-28853
2022-07-22 16:15:05 +02:00
Stephane Nicoll 421b5cb311 Polish "Deprecate SockJsServiceRegistration#setSupressCors"
See gh-28853
2022-07-22 16:07:47 +02:00
Marc Wrobel 1cc36e5be9 Deprecate SockJsServiceRegistration#setSupressCors
SockJsServiceRegistration#setSupressCors name contains a typo. It is
now deprecated in favor of a correctly spelled method, setSuppressCors.

See gh-28853
2022-07-22 16:06:54 +02:00
Stephane Nicoll f7c32d3a0b Merge pull request #28842 from adrianbob
* pr/28842:
  Reintroduce Javadoc links to Apache HttpClient 5.1 APIs

Closes gh-28842
2022-07-19 15:39:36 +02:00
Adrian Bob 9c0a2eeeb2 Reintroduce Javadoc links to Apache HttpClient 5.1 APIs
See gh-28842
2022-07-19 15:39:18 +02:00
Jupiter 7fa9f1c9cf Fix broken link to rsocket protocol page
Closes gh-28817
2022-07-19 10:14:46 +02:00
Arjen Poutsma 1e03b30d33 Use existing context path in DefaultServerRequestBuilder
Closes gh-28820
2022-07-14 15:10:31 +02:00
Spring Builds 7df149c8b8 Next development version (v5.3.23-SNAPSHOT) 2022-07-14 08:50:40 +00:00
rstoyanchev e50131d454 Add Consumer methods to configure Jackson modules
Closes gh-28633
2022-07-13 19:10:51 +01:00
rstoyanchev cdd4e8cd7f Improve regex support for URL path matching
Closes gh-28815
2022-07-13 18:43:51 +01:00
Juergen Hoeller 02b7ddbc70 Upgrade to Log4J 2.18, H2 2.1.214, OpenPDF 1.3.29, XStream 1.4.19, HtmlUnit 2.63, Jetty Reactive HttpClient 1.1.12 2022-07-13 16:48:02 +02:00
Juergen Hoeller 8e5c4903d4 Avoid synchronization in AbstractAspectJAdvice#calculateArgumentBindings
Aligned with the early calculateArgumentBindings call in ReflectiveAspectJAdvisorFactory.

Closes gh-26377
2022-07-13 16:47:35 +02:00
Marc Wrobel bd3499671c Fix typos in test code
This commit fixes typos in test class names, test method names, and
test variable names.

Closes gh-28807
2022-07-13 16:24:11 +02:00
Sam Brannen 2e4d7e4ef9 Polishing 2022-07-13 16:13:09 +02:00
Marc Wrobel c6be3b33c9 Fix and improve Javadoc in spring-aop
Closes gh-28803
2022-07-13 16:13:02 +02:00
Marc Wrobel c112bb0ae1 Fix and improve Javadoc in spring-beans
See gh-28803
2022-07-13 16:12:51 +02:00
Marc Wrobel 165fba868c Fix typos in reference docs
Closes gh-28805
2022-07-13 15:12:31 +02:00
Marc Wrobel 2ca64ad88a Fix minor typos in project README
See gh-28805
2022-07-13 15:12:21 +02:00
Sam Brannen ea27206a32 Polishing 2022-07-13 14:45:31 +02:00
Marc Wrobel c48c5e7691 Fix and improve Javadoc in spring-context
Closes gh-28802
2022-07-13 14:45:23 +02:00
Marc Wrobel bc15f839cd Fix and improve Javadoc in spring-core
See gh-28802
2022-07-13 14:45:13 +02:00
Sam Brannen 46db372951 Polishing 2022-07-13 14:01:47 +02:00
Marc Wrobel 91258271e4 Fix and improve Javadoc in spring-expression
Closes gh-28800
2022-07-13 14:01:41 +02:00
Marc Wrobel e76fbcb290 Fix and improve Javadoc in spring-jms
See gh-28800
2022-07-13 14:01:37 +02:00
Marc Wrobel 82ca27e46f Fix and improve Javadoc in spring-messaging
See gh-28800
2022-07-13 14:01:29 +02:00
Marc Wrobel bca104798b Fix and improve Javadoc in spring-jdbc
Closes gh-28796
2022-07-13 13:42:48 +02:00
Marc Wrobel b30eb6837c Fix and improve Javadoc in spring-oxm
See gh-28796
2022-07-13 13:42:42 +02:00
Marc Wrobel ac06d1dfa9 Fix and improve Javadoc in spring-orm
See gh-28796
2022-07-13 13:42:33 +02:00
Marc Wrobel cfb39acc97 Fix and improve Javadoc in spring-r2dbc
See gh-28796
2022-07-13 13:42:16 +02:00
Sam Brannen 222dbf8377 Update copyright date 2022-07-13 13:22:40 +02:00
kacperkrzyzak 10838a636f Correctly identify MaxUploadSizeExceededException in StandardMultipartHttpServletRequest
This commit correctly identifies MaxUploadSizeExceededException in
StandardMultipartHttpServletRequest by converting keywords in the
exception message to lowercase before checking for their presence, for
compatibility with Jetty 9.4.x.

Closes gh-28759
2022-07-13 13:17:53 +02:00
Juergen Hoeller 3c3ae32f07 Upgrade to Netty 4.1.79, Jetty 9.4.48, Undertow 2.2.18, Checkstyle 10.3.1 2022-07-13 11:11:17 +02:00
Juergen Hoeller a3e46a2db7 ResolvableType.forInstance returns NONE for null instance
Closes gh-28776
2022-07-13 11:10:35 +02:00
Juergen Hoeller de1b938e2e Improve diagnostics for CGLIB ClassLoader mismatch with --add-opens hint
Closes gh-28747
2022-07-13 11:10:00 +02:00
Juergen Hoeller d72aeac319 Create well-known non-interface types without using reflection
Closes gh-28718
2022-07-13 11:09:43 +02:00
Juergen Hoeller 5247eeba84 Support LocalDate/Time for SQL type mappings
Closes gh-28778
2022-07-13 11:09:30 +02:00
Juergen Hoeller ae70e3c81c Apply read-only enforcement after R2DBC transaction begin
Includes prepareTransactionalConnection variant aligned with JDBC DataSourceTransactionManager.

Closes gh-28610
2022-07-13 11:09:17 +02:00
Sébastien Deleuze c942c8d2cf Fix expectations in MockMvc Kotlin documentation
Closes gh-28301
2022-07-13 10:06:41 +02:00
Sébastien Deleuze 1201af20e4 Improve consistency of Kotlin injection code samples
Closes gh-28596
2022-07-13 09:42:47 +02:00
Sébastien Deleuze d1df4d3739 Fix Kotlin code snippets language
Closes gh-28810
2022-07-13 09:21:02 +02:00
Sébastien Deleuze 1ef8800c6c Fix Kotlin example for custom @Production
Closes gh-28680
2022-07-13 09:13:47 +02:00
Sébastien Deleuze 4d7e4e0c58 Fix a typo
See gh-28630
2022-07-12 18:54:01 +02:00
Stephane Nicoll c7067269b3 Upgrade to Reactor 2020.0.21
Closes gh-28765
2022-07-12 14:31:43 +02:00
Sam Brannen 3af6a22b9f Temporarily disable Javadoc links to Apache HttpClient 5.1 APIs 2022-07-12 13:26:07 +02:00
Sam Brannen 31a9694fc8 Improve Javadoc for ContextCache#clearStatistics()
See gh-28795
2022-07-12 13:04:34 +02:00
Marc Wrobel 92b8e99cbc Fix and improve Javadoc in spring-test
Closes gh-28795
2022-07-12 12:55:59 +02:00
Marc Wrobel 3b68e97710 Fix and improve Javadoc in spring-tx
Closes gh-28794
2022-07-12 12:36:49 +02:00
Marc Wrobel 6f494ef438 Fix and improve Javadoc in spring-web
Closes gh-28791
2022-07-12 12:08:12 +02:00
Sam Brannen 19704805fd Polish contribution
See gh-28790
2022-07-12 11:56:01 +02:00
Marc Wrobel 31c6965c7f Fix and improve Javadoc in spring-webflux
Closes gh-28790
2022-07-12 11:48:58 +02:00
Sam Brannen 5b1a84e395 Polish contribution
See gh-28789
2022-07-12 10:39:11 +02:00
Marc Wrobel 6985fa8057 Fix and improve Javadoc in spring-webmvc
Closes gh-28789
2022-07-12 10:39:03 +02:00
Marc Wrobel 03f0c57704 Fix and improve Javadoc in spring-websocket
Closes gh-28788
2022-07-11 21:30:32 +02:00
Sam Brannen d274e893a6 Remove superfluous static declaration for enum, annotation, & interface 2022-07-09 16:16:13 +02:00
Arjen Poutsma aa8b06b622 Delete file on multipart cancel
This commit makes sure that the temporary file used for multipart
storage is deleted when the source stream is malformed or cancelled.

Closes gh-28740
2022-07-08 16:36:01 +02:00
Sam Brannen 323dbb912e Move convention-based attribute override tests to @Nested class 2022-07-06 13:19:41 +02:00
rstoyanchev 63d7e81a48 Switch to Reactor 2020-0.21 snapshots
See gh-28765
2022-07-06 11:30:44 +01:00
Sam Brannen 07960d4918 Polishing 2022-07-06 11:44:15 +02:00
Sam Brannen 07cfcbc3a9 Move convention-based attribute override tests to @Nested class 2022-07-06 11:42:39 +02:00
Sam Brannen 2af27d899f Trim string input in Converters where whitespace is irrelevant
Closes gh-28756
2022-07-05 13:53:00 +02:00
Sam Brannen 0621a8eff1 Fix concurrency issues in FreeMarkerMacroTests
Prior to this commit, tests in these two classes intermittently failed
with errors similar to the following, due to concurrent modification
of shared files.

expected:
  "<input type="text" id="name" name="name" value="Darren"     >"
 but was:
  "<input type="text" id="name" name="name" value="Darren"     >

  "hidden"/>"

This commit fixes this by creating a new temporary folder for each test
method invocation.
2022-07-05 13:17:50 +02:00
Sam Brannen 7ac646bc96 Upgrade to TestNG Engine 1.0.4 2022-07-05 12:43:05 +02:00
Sam Brannen 2c3243c93c Trim string input in PropertyEditors where whitespace is irrelevant
Closes gh-28755
2022-07-04 19:24:58 +02:00
Sam Brannen 2bf5f7a6b3 Introduce lenient parsing in DataSize regarding whitespace
Prior to this commit, a DataSize input string could not be parsed if it
contained any whitespace.

With this commit, a DataSize input string can contain leading, trailing,
or 'in between' whitespace. For example, the following will be parsed
to the same DataSize value.

- "1024B"
- "1024 B"
- " 1024B "
- " 1024 B "

Closes gh-28643
2022-07-04 19:24:58 +02:00
Sam Brannen bf39492c34 Introduce StringUtils.trimAllWhitespace(CharSequence)
Closes gh-28757
2022-07-04 19:24:45 +02:00
rstoyanchev 007bdede46 Add missing check to avoid re-initialization
Noticed during review of #28736 that a check protecting against
re-initialization was accidentally removed in commit
3d6e38bb43.
2022-07-04 16:17:57 +01:00
rstoyanchev 22cc6c5918 Polishing contribution
Closes gh-28736
2022-07-04 16:12:57 +01:00
CodeInDreams 461ba53b39 Qualify channelExecutor and taskScheduler in WebSocket config
See gh-28736
2022-07-04 15:51:40 +01:00
Sam Brannen d1d6eb095e Fix GenericApplicationContextTests on Microsoft Windows (round 2)
The previous change to the tests resulted in a failure on Windows when
using the DefaultResourceLoader by expecting an exception when no
exception is thrown.

This commit narrows the scope of the if-clause to expect an exception
only when using the FileSystemResourceLoader on Windows.

See gh-28703, gh-28746
2022-07-03 17:59:37 +02:00
Sam Brannen f732fab820 Delete unused imports and dead code in CGLIB fork 2022-07-03 17:30:30 +02:00
Sam Brannen fda3f8201a Switch warning level for forbidden reference to INFO in Eclipse IDE 2022-07-03 17:23:55 +02:00
Sam Brannen e608b36713 Improve GenericApplicationContextTests.getResource*() tests
This commit updates the tests so that they test something meaningful on
MS Windows as well as on Linux/Mac.

See gh-28703, gh-28746
2022-07-03 14:36:41 +02:00
jason 59180e76a7 Fix GenericApplicationContextTests on Microsoft Windows
The tests introduced in commit 9868c28c73 pass on Mac OS and Linux but
fail on Microsoft Windows.

This commit updates the tests so that they pass on MS Windows as well.

See gh-28703
Closes gh-28746
2022-07-03 14:35:07 +02:00
Sam Brannen c5987d7c37 Fix typo in test 2022-07-02 17:09:07 +02:00
Sam Brannen 5650e20edd Polishing 2022-07-01 10:42:23 +02:00
Johnny Lim 2885177f5b Add @since tag for new CannotGetJdbcConnectionException constructor
See gh-28669
Closes gh-28738
2022-07-01 10:39:35 +02:00
rstoyanchev 058ce36402 Improve ExtendedWebExchangeDataBinder implementation
Close gh-28646
2022-07-01 03:23:32 +01:00
Vikey Chen 2afe560e41 Replace forEach with putAll
See gh-28646
2022-07-01 03:01:12 +01:00
rstoyanchev b95362a3fd Avoid request params access for form data in logRequest
Close gh-28587
2022-07-01 02:55:16 +01:00
Sam Brannen 9ea45697ac Support cookie comments in MockHttpServletResponse and MockCookie
Prior to this commit, if a cookie was added to MockHttpServletResponse,
the comment attribute was not included in the generated Set-Cookie
header. In addition, MockCookie.parse(String) did not support the
Comment attribute.

This commit addresses both of these issues.

Closes gh-28730
2022-06-30 16:51:43 +02:00
Johnny Lim fe2b8580a0 Upgrade to Gradle Enterprise Conventions 0.0.10 2022-06-30 14:59:55 +02:00
Sam Brannen 622fc3edf7 Fix merged annotation attributes regression
Commit d6768ccc18 introduced a regression in the support for merging
annotation attributes in a multi-level annotation hierarchy.

This commit addresses that issue by ensuring that a merged annotation
is once again synthesized if a meta-annotation in the annotation
hierarchy declares attributes that override attributes in the target
annotation.

Closes gh-28716
2022-06-28 14:22:53 +02:00
Sam Brannen 9868c28c73 Honor ProtocolResolvers in GenericApplicationContext
When the ProtocolResolver SPI was introduced in Spring Framework 4.3,
support for protocol resolvers was added in DefaultResourceLoader's
getResource() implementation; however, GenericApplicationContext's
overridden getResource() implementation was not updated accordingly.

Prior to this commit, if a GenericApplicationContext was configured
with a custom ResourceLoader, registered protocol resolvers were
ignored.

This commit ensures that protocol resolvers are honored in
GenericApplicationContext even if a custom ResourceLoader is used.

Closes gh-28703
2022-06-27 18:00:29 +02:00
Sam Brannen a970516080 Polish GenericApplicationContextTests 2022-06-27 17:05:02 +02:00
Sam Brannen 0c9def89de Ignore build artifacts from the main branch for nohttp 2022-06-27 15:05:05 +02:00
Sam Brannen 8892a05868 Ignore /spring-core/graalvm/build artifacts from the main branch
This commit eases switching between the `main` and `5.3.x` branches.
2022-06-27 14:43:06 +02:00
Sam Brannen d6768ccc18 Ensure meta-annotations are not unnecessarily synthesized
Prior to this commit, meta-annotations were unnecessarily synthesized
when attempting to synthesize a MergedAnnotation retrieved via the
MergedAnnotations.from(AnnotatedElement, ...).get(<annotationType>) API.

This is a regression in our merged annotation support that was
introduced when the MergedAnnotations API replaced our previous support.

This commit fixes this by revising the logic in TypeMappedAnnotation's
createSynthesizedAnnotation() method so that a meta-annotation is
returned unmodified if it is not synthesizable.

This commit also updates BootstrapUtilsTests, since @BootstrapWith
should never have been synthesized, and Class#getCanonicalName() is
only used in the toString() implementation of an annotation synthesized
by Spring or normal annotations on Java 19+ (see
https://bugs.openjdk.org/browse/JDK-8281462).

Closes gh-28704
2022-06-25 20:02:04 +02:00
Sam Brannen faf20b7a5a Polish MergedAnnotations Javadoc and internals 2022-06-25 19:50:03 +02:00
Sam Brannen 661996471e Polishing 2022-06-25 19:24:51 +02:00
Stephane Nicoll 5639ff0939 Merge pull request #28669 from kevin0x90
* pr/28669:
  Polish "Fix DataSourceUtils inconsistent exception handling"
  Fix DataSourceUtils inconsistent exception handling

Closes gh-28669
2022-06-23 09:04:40 +02:00
Stephane Nicoll e98b602d4f Polish "Fix DataSourceUtils inconsistent exception handling"
See gh-28669
2022-06-23 09:01:39 +02:00
Kevin Schönfeld edfe5d2f18 Fix DataSourceUtils inconsistent exception handling
Align IllegalStateException with SQLException handling and propagate
the original exception.

See gh-28669

Co-authored-by: Christoph Mies <chr.mi@web.de>
2022-06-23 09:01:39 +02:00
Sam Brannen 26df4580b3 Revise internals of LoggingCacheErrorHandler
Since LoggingCacheErrorHandler was only recently introduced in 5.3.16,
we have decided to completely revise its internals (protected API) in
5.3.x while retaining the current public API.

Specifically, this commit:

- introduces protected getLogger() and isLogStackTraces() methods to
  improve extensibility

- revises logCacheError() to accept a Supplier<String> for lazy
  resolution of error messages

Closes gh-28672
See gh-28670, gh-28648
2022-06-21 16:13:55 +02:00
Vedran Pavic 57208bf47a Simplify LoggingCacheErrorHandlerTests
See gh-28648
2022-06-21 14:40:09 +02:00
Sam Brannen 8b34558284 Polish LoggingCacheErrorHandler 2022-06-21 14:07:39 +02:00
Vedran Pavic dbe8f200a9 Simplify creation of LoggingCacheErrorHandler with logged stacktrace
At present, creating a LoggingCacheErrorHandler that logs stack traces
also requires supplying the logger to be used. This might be
inconvenient for some users, as it requires usage of the Commons
Logging API.

This commit simplifies creation of such as LoggingCacheErrorHandler
instance by adding a constructor that only accepts a boolean flag
indicating whether to log stack traces.

Closes gh-28670
2022-06-21 13:50:10 +02:00
Sam Brannen ea4d9a20ac Upgrade to Hamcrest 2.2 2022-06-21 13:48:02 +02:00
Sam Brannen e19e9757d4 Polishing 2022-06-20 15:19:02 +02:00
Jerome Prinet 2473e956ff Update Gradle Enterprise plugin
Closes gh-28661
2022-06-20 11:40:43 +02:00
Sébastien Deleuze 854307d8d8 Document that Kotlin inline classes are not supported
Closes gh-28642
2022-06-17 12:34:58 +02:00
Sébastien Deleuze 3401359bdf Refine @Required Kotlin documentation
Refine @Required Kotlin documentation to use
annotation use site targets.

Closes gh-28630
2022-06-17 12:25:52 +02:00
Sébastien Deleuze f1c00dd8a6 Fix a typo in ResponseEntity documentation
Closes gh-28647
2022-06-17 12:15:22 +02:00
Sam Brannen bdf91ac435 Set default encoding for Eclipse projects to UTF-8
This change aligns with Java 18 support in recent versions of Eclipse.
2022-06-16 16:13:35 +02:00
Lars Grefer 181023c0c3 Update to Bouncycastle 1.71
Closes gh-28636
2022-06-16 16:03:11 +02:00
Sam Brannen fb1fa073a6 Polishing 2022-06-15 15:07:58 +02:00
Sam Brannen e9806a96dc Polish contribution and introduce test
See gh-28631
2022-06-15 15:07:58 +02:00
Johnny Lim 9b93508374 Add MockMvcRequestBuilders.multipart(HttpMethod, String, Object...)
See gh-28545
Closes gh-28631
2022-06-15 14:09:59 +02:00
Sam Brannen 8b4750e705 Fix Kotlin example for @ComponentScan basePackages attribute
Closes gh-28628
2022-06-15 11:27:39 +02:00
Spring Builds 2e033339d1 Next development version (v5.3.22-SNAPSHOT) 2022-06-15 08:17:52 +00:00
Stephane Nicoll c75da7ba10 Upgrade to Reactor 2020.0.20
Closes gh-28612
2022-06-14 19:27:03 +02:00
Sam Brannen eeac150030 Polish contribution
See gh-28616
2022-06-14 16:42:51 +02:00
Fabian Gonzalez 0ce9516aef Avoid eager instantiation of non-singleton FactoryBean in getBeanNamesForType
Closes gh-28616
2022-06-14 16:42:31 +02:00
Sam Brannen e47cc44947 Polish DefaultListableBeanFactoryTests 2022-06-14 16:38:11 +02:00
Juergen Hoeller 57db73dcb8 Upgrade to Tomcat 9.0.64, Jackson 2.12.7, Apache Johnzon 1.2.18, OpenPDF 1.3.28, H2 2.1.212, Mockito 4.6.1, HtmlUnit 2.62, Checkstyle 10.3 2022-06-14 15:10:17 +02:00
Juergen Hoeller d7be1e0dab Polishing 2022-06-14 15:09:39 +02:00
Juergen Hoeller 30c873b4b5 Move NestedServletExceptionTests to spring-web module
See gh-25162
2022-06-14 15:09:21 +02:00
Juergen Hoeller e72b0a04cd Document limitations for MessageProducer/Consumer caching with WebLogic JMS
Closes gh-28500
2022-06-14 15:09:10 +02:00
Juergen Hoeller f8b41c1ad2 Consistent support for setContextClass in CGLIB beans package
Closes gh-28530
2022-06-14 15:08:44 +02:00
rstoyanchev 8c777111fa Revise commit #52d068 with corrected test
Update test detecting RouterFunction beans in parent contexts to use
different bean names and avoid shadowing. Changed the fix accordingly
given that BeanProvider does detect beans in parent contexts.

See gh-28595
2022-06-14 10:07:56 +01:00
rstoyanchev d28d603081 Polishing
See gh-28595
2022-06-14 09:35:17 +01:00
rstoyanchev 52d0681ca1 WebMvc respects RouterFunction beans ordering
Closes gh-28595
2022-06-14 09:20:19 +01:00
Sam Brannen 97854d9fec Refactor ObjectToObjectConverter to use Executable instead of Member 2022-06-13 18:01:54 +02:00
Sam Brannen 73f3860bb7 Polish Javadoc for ObjectToObjectConverter 2022-06-13 18:01:05 +02:00
Sam Brannen 452f1b877c Consider return type of static methods in ObjectToObjectConverter
Prior to this commit, ObjectToObjectConverter considered the return
type of non-static `to[targetType.simpleName]()` methods but did not
consider the return type of static `valueOf(sourceType)`,
`of(sourceType)`, and `from(sourceType)` methods.

This led to scenarios in which `canConvert()` returned `true`, but a
subsequent `convert()` invocation resulted in a
ConverterNotFoundException, which violates the contract of the
converter.

This commit addresses this issue by taking into account the return type
of a static valueOf/of/from factory method when determining if the
ObjectToObjectConverter supports a particular conversion. Whereas the
existing check in `determineToMethod()` ensures that the method return
type is assignable to the `targetType`, the new check in
`determineFactoryMethod()` leniently ensures that the method return
type and `targetType` are "related" (i.e., reside in the same type
hierarchy).

Closes gh-28609
2022-06-13 17:20:18 +02:00
Arjen Poutsma c278d8c656 Do not ignore charset in Jaxb2XmlDecoder
This commit makes sure that the charset, if defined in the mimetype, is
used when decoding XML to JAXB2 objects.

Closes gh-28599
2022-06-13 13:47:31 +02:00
Stephane Nicoll e3b288716d Upgrade to Reactor 2020.0.20
Closes gh-28612
2022-06-13 11:39:15 +02:00
Arjen Poutsma 27738cc20f Fix code samples for nested router functions
Closes gh-28603
2022-06-10 13:36:33 +02:00
Sam Brannen babff8e635 Fix Kotlin example for dependency injection with static factory method
Closes gh-28589
2022-06-09 13:16:19 +02:00
Sam Brannen 290cc73d3d Fix Kotlin example for @Required
Since @Required can only be declared on a method, this commit moves the
@Required declaration from the field to the "set" method.

Closes gh-28590
2022-06-09 13:13:43 +02:00
Stephane Nicoll 8a30bc2993 Upgrade Java 18 version in CI image 2022-06-09 08:14:54 +02:00
Stephane Nicoll aa8be28a01 Upgrade Java 17 version in CI image 2022-06-09 08:14:30 +02:00
Stephane Nicoll f43b28e7ba Upgrade Java 11 version in CI image 2022-06-09 08:14:05 +02:00
Stephane Nicoll 1476867ee7 Upgrade Java 18 version in CI image 2022-06-09 08:13:36 +02:00
Stephane Nicoll 4d9dc61f5d Polish 2022-06-09 08:13:12 +02:00
Stephane Nicoll 7eebc48a6e Upgrade Ubuntu version in CI image 2022-06-09 08:11:36 +02:00
Sam Brannen 8478e8e70a Polish contribution
This commit:

- fixes Checkstyle violations
- improves Javadoc
- adds missing @since tags
- renames getCurrentQueueSize() to getQueueSize()
- avoids NullPointerExceptions in getQueueSize()
- introduces tests for queue size and queue capacity

Closes gh-28583
2022-06-08 16:39:10 +02:00
Rémy e386bdb82c Expose ThreadPoolTaskExecutor queue size and capacity for metrics
We use Grafana to monitor our app via Spring's JMX exporter, and we
think it could be interesting to have at least the current queue size
for this purpose since the queue size directly affects the app memory
load. Having the queue capacity seems also interesting to set up
triggers whose values are calculated based on the maximum capacity of
the queue.

This commit introduces new getCurrentQueueSize() and getQueueCapacity()
methods in ThreadPoolTaskExecutor.

See gh-28583
2022-06-08 16:39:00 +02:00
Arjen Poutsma 4912c3c455 Updated sdkmanrc 2022-06-08 12:13:21 +02:00
rstoyanchev 8fcc7ab9d1 CompositeLog respects log level changes at runtime
Closes gh-28477
2022-06-08 10:07:52 +01:00
rstoyanchev 7c47b470ff MockMvc allows HttpMethod input for multipart request
Closes gh-28545
2022-06-08 10:07:52 +01:00
Sam Brannen 479ef3f3fd Update documentation regarding nested test class support
Closes gh-28579
2022-06-08 09:52:42 +02:00
Sam Brannen be1b7da12f Add entries for "Sam Brannen" to .mailmap 2022-06-07 14:27:42 +02:00
Phillip Webb 89360b18f4 Update '.mailmap` to consistently use @vmware.com emails
(cherry picked from commit 83063a7269)
2022-06-07 14:14:10 +02:00
Stephane Nicoll 209fe5f452 Merge pull request #28572 from gorisanson
* pr/28572:
  Polish contribution
  Update reference docs to use PropertySourcesPlaceholderConfigurer

Closes gh-28572
2022-06-07 08:30:52 +02:00
Stephane Nicoll e18a118f8b Polish contribution
See gh-28572
2022-06-07 08:29:28 +02:00
Lee, Kyutae 77aac7768d Update reference docs to use PropertySourcesPlaceholderConfigurer
See gh-28572
2022-06-07 08:22:53 +02:00
Sam Brannen e2767371b5 Lazily initialize DataSize.PATTERN
To avoid unnecessary eager initialization of DataSize.PATTERN, this
commit initializes it lazily in the first invocation of DataSize.parse
by moving PATTERN to a private static nested class.

Closes gh-28560
2022-06-03 13:30:45 +02:00
Sam Brannen aab9da0366 Polish LocaleResolver support 2022-06-03 13:10:55 +02:00
Sam Brannen cda1e5507c Polishing 2022-06-01 16:28:05 +02:00
Balázs Póka 1d5ffaf30a Always construct new exception on error in DefaultWebClient
Always construct new exception on error, otherwise memory leak may
occur due to repeated use of singleton exception.

Closes gh-28550
2022-06-01 16:07:41 +02:00
Arjen Poutsma c55606ed08 Recognize Kotlin coroutines in isAsyncVoidReturnType
This commit makes sure that Kotlin coroutines are correctly identified
by InvocableHandlerMethod::isAsyncVoidReturnType.

Closes gh-26829
2022-06-01 15:13:30 +02:00
Sam Brannen aa8802a81d Avoid new AssertJ deprecations 2022-05-31 16:13:31 +02:00
Sam Brannen 1beb7068f6 Use new AssertJ exception assertions 2022-05-31 14:08:28 +02:00
Sam Brannen 9d324e59a0 Upgrade to AssertJ 3.23.0 2022-05-31 12:55:43 +02:00
Sam Brannen 8547f8601d Polish LocaleResolver tests 2022-05-31 11:55:30 +02:00
Stephane Nicoll 40cb81470b Merge pull request #28542 from eltociear
* pr/28542:
  Fix typo in webflux.adoc

Closes gh-28542
2022-05-31 10:01:30 +02:00
Ikko Ashimine 6e3b3c5419 Fix typo in webflux.adoc
See gh-28542
2022-05-31 10:01:13 +02:00
Sam Brannen a221835558 Throw IllegalStateException for invalid port in HierarchicalUriComponents
Prior to this commit, getPort() in HierarchicalUriComponents threw a
NumberFormatException for an invalid port supplied as a String, which
was inconsistent with exception handling elsewhere in the class as well
as within the same method.

This commit introduces a try-catch block in getPort() to consistently
throw IllegalStateExceptions for ports that cannot be parsed.

Closes gh-28521
2022-05-25 11:29:12 +02:00
Sam Brannen aa06a09dee Polishing 2022-05-25 11:29:12 +02:00
hsteinmueller bde0931e51 Fix Javadoc for DatabaseClient
The documentation for DatabaseClient had misplaced double quotes in the
example on how to map a select statement to a row.

Closes gh-28520
2022-05-24 17:15:44 +02:00
Sam Brannen 7b95c928d1 Fix Javadoc for ResourcePatternResolver 2022-05-23 20:32:01 +02:00
Sam Brannen 53f88d455f Fix Javadoc for AbstractFileResolvingResource.isFile(URI) 2022-05-23 20:32:01 +02:00
Sam Brannen 53a506f6bb Polishing 2022-05-23 20:22:37 +02:00
rstoyanchev f95bf96ec9 Correct path encoding/decoding in PathResourceResolver
Decoding is required for non-UrlResource when the HandlerMapping is
not expected to decode the path. Encoding is the opposite.

This commit ensures correct determination of whether the HandlerMapping
is expected to have decoded the path or not that in turn depends on
whether PathPattern or PathMatcher is in use.

Closes gh-27791
2022-05-23 11:03:42 +01:00
rstoyanchev 66a5742df3 Polishing 2022-05-23 10:07:03 +01:00
Sam Brannen 59c7bb1f86 Use Arrays.toString instead of Arrays.asList when generating Strings 2022-05-17 15:36:31 +02:00
Sam Brannen a1c3efbb5f Polish ManagedList[Tests] and ManagedSet[Tests] 2022-05-17 15:36:31 +02:00
Sam Brannen 6efe3aee34 Polishing 2022-05-16 11:20:20 +02:00
Sam Brannen f2fe7f335c Improve nullReturningBeanPostProcessor() test
See gh-28459
2022-05-14 18:30:39 +02:00
Sam Brannen 48c797e429 Fix Kotlin example for static factory method
Closes gh-28399
2022-05-11 17:33:31 +02:00
Sam Brannen be782a2197 Polish ref docs regarding the BeanFactory API
See gh-28403
2022-05-11 17:16:40 +02:00
Sam Brannen 8098e45bad Sync gradle.properties between 5.3.x and main 2022-05-11 16:30:44 +02:00
Sam Brannen 06679a5583 Fix tests in DispatcherServletTests
See gh-28424
2022-05-11 16:00:26 +02:00
Sam Brannen 745eb1a881 Polish DispatcherServletTests 2022-05-11 15:59:47 +02:00
Spring Builds 10c55ff912 Next development version (v5.3.21-SNAPSHOT) 2022-05-11 07:08:24 +00:00
Juergen Hoeller 83186b689f Refine CachedIntrospectionResults property introspection
Closes gh-28445
2022-05-11 08:32:06 +02:00
rstoyanchev dc2947c52d Ignore invalid connect frame
Closes gh-28443
2022-05-11 07:22:22 +01:00
Arjen Poutsma e4ec376075 Disabling Undertow server in CoroutinesIntegrationTests 2022-05-10 15:55:00 +02:00
Juergen Hoeller c81e11d537 Polishing 2022-05-10 13:07:00 +02:00
Juergen Hoeller de6180b093 Upgrade to Reactor 2020.0.19
Includes Netty 4.1.77 and RxJava 3.1.4.

Closes gh-28437
2022-05-10 13:05:56 +02:00
Sam Brannen 1c10cdd1e8 Update copyright dates
See gh-28433
2022-05-10 11:33:32 +02:00
evgeny.bovykin 941b92cbed Make inner classes static when feasible
A static nested class does not keep an implicit reference to its
enclosing instance.

This prevents a common cause of memory leaks and uses less memory per
instance of the class.

Closes gh-28433
2022-05-10 11:32:37 +02:00
Sam Brannen e26d8839b3 Stop referring to features as Java 6/7 features where unnecessary 2022-05-09 19:09:06 +02:00
Sam Brannen a1c7380398 Add test for value attribute in @ModelAttribute in WebFlux
This complements the previous commit which tested only the `name`
attribute.

See gh-28423
2022-05-09 15:22:22 +02:00
Sam Brannen 7dd622bdb2 Support name attribute in @ModelAttribute in WebFlux
Prior to this commit, the `name` attribute in @ModelAttribute was not
supported when using WebFlux. This is because MethodParameter was used
instead of SynthesizingMethodParameter when retrieving the
@ModelAttribute annotation. In other words, @AliasFor was not honored
because the annotation was not synthesized. Consequently, only the
`value` attribute was supported in WebFlux when specifying a custom name
via @ModelAttribute.

This commit fixes this by using SynthesizingMethodParameter to retrieve
the @ModelAttribute annotation.

Closes gh-28423
2022-05-07 17:16:26 +02:00
Sam Brannen 64c96c579d Polish contribution
See gh-28422
2022-05-07 16:18:47 +02:00
Carlos Bouzón García 39e3876301 Fix BindingResult error when ModelAttribute has custom name in WebFlux
Closes gh-28422
2022-05-07 16:18:04 +02:00
Juergen Hoeller f771603789 Polishing 2022-05-05 18:04:54 +02:00
Juergen Hoeller e441832e99 Accept WritableResource as required dependency type as well
Closes gh-15284
2022-05-05 18:04:13 +02:00
Juergen Hoeller f963fc5f98 Check that nullable annotations are from org.springframework.lang
Closes gh-28410
2022-05-05 18:02:27 +02:00
Juergen Hoeller b55eee1b0d Upgrade to ASM 9.3
Closes gh-28390
2022-05-05 18:01:53 +02:00
Juergen Hoeller 28742171fd Upgrade to Netty 4.1.76, Mockito 4.5.1, HtmlUnit 2.61 2022-05-05 18:01:31 +02:00
Lee, Kyutae 7a75b94556 Fix typo in reference docs regarding RequestMappingHandlerAdapter
Closes gh-28370
2022-05-05 16:31:40 +02:00
Sam Brannen ab71ff93bb Polish package-info for org.springframework.util
See gh-28411
2022-05-05 16:22:52 +02:00
neals cf30327740 Remove Log4J configurer from package-info.java in spring-core
Closes gh-28411
2022-05-05 16:16:49 +02:00
neals e22a038725 Remove Log4J initialization from package-info.java
Closes gh-28420
2022-05-05 16:10:59 +02:00
Brian Clozel 7aedb9ee33 Build CI image using oci-build-task resource 2022-05-03 15:50:29 +02:00
Brian Clozel 5b1719cd77 Upgrade CI to concourse-release-scripts 0.3.4 2022-05-03 15:09:23 +02:00
Brian Clozel c056b81753 Upgrade JDK and Ubuntu versions in CI image 2022-05-03 15:08:14 +02:00
Brian Clozel dbdd67ec62 Remove outdated docker-image resource from CI
The docker-image resource is now replaced by the registry-image
resource.
2022-05-03 15:05:58 +02:00
Sam Brannen 4fcfa5b991 Update and simplify ArrayConstructorTests 2022-05-03 14:27:48 +02:00
Sam Brannen ed06a6de26 Convert SimpleFormController example to @Controller in reference manual
This change is necessary since the SimpleFormController class no longer
exists.
2022-05-03 12:03:04 +02:00
Sam Brannen afa799b4f0 Suppress warning in test 2022-05-03 11:46:47 +02:00
rstoyanchev f0d149b330 Polishing contribution
Closes gh-27830
2022-04-28 11:26:50 +01:00
binchoo caaf83b8e6 Add tests for binding to a Part field
See gh-27830
2022-04-28 10:45:09 +01:00
rstoyanchev b30f4d7bb7 Exposes all root causes to ExceptionHandler methods
Closes gh-28155
2022-04-28 04:04:57 +01:00
Arjen Poutsma b6b03f38d7 Updated .sdkmanrc 2022-04-26 11:54:02 +02:00
Stephane Nicoll 46b0d7dc03 Merge pull request #28369 from izeye
* pr/28369:
  Add Javadoc since for GraphQL constants

Closes gh-28369
2022-04-24 10:05:28 +02:00
izeye fcf64798b5 Add Javadoc since for GraphQL constants
See gh-28369
2022-04-24 09:58:50 +02:00
Stephane Nicoll 94ed07d9cb Merge pull request #28372 from zhangmingqi09
* pr/28372:
  Update copyright year of changed file
  Fix github issue reference in RequestMappingHandlerMapping

Closes gh-28372
2022-04-24 09:57:02 +02:00
Stephane Nicoll b81c62d064 Update copyright year of changed file
See gh-28372
2022-04-24 09:56:39 +02:00
zhangmingqi09 ca1a11acac Fix github issue reference in RequestMappingHandlerMapping
See gh-28372
2022-04-24 09:55:20 +02:00
Stephane Nicoll c261d40610 Merge pull request #28340 from koenpunt
* pr/28340:
  Update copyright year of changed file
  Fix method reference in Kotlin documentation

Closes gh-28340
2022-04-14 14:11:28 +02:00
Stephane Nicoll 3017955eff Update copyright year of changed file
See gh-28340
2022-04-14 14:09:54 +02:00
Koen Punt 22c82ff206 Fix method reference in Kotlin documentation
See gh-28340
2022-04-14 14:09:02 +02:00
Jerome Prinet f54952481b Update Gradle Enterprise plugin to 3.9
Closes gh-28338
2022-04-14 11:04:22 +02:00
Spring Builds 9e733b09e2 Next development version (v5.3.20-SNAPSHOT) 2022-04-13 09:24:33 +00:00
1346 changed files with 19297 additions and 11475 deletions
@@ -1,10 +1,13 @@
name: "Validate Gradle Wrapper"
on: [push, pull_request]
permissions:
contents: read
jobs:
validation:
name: "Validation"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: gradle/wrapper-validation-action@v1
+6 -1
View File
@@ -21,11 +21,14 @@ classes/
/build
buildSrc/build
/spring-*/build
/spring-core/graalvm/build
/spring-core/kotlin-coroutines/build
/framework-bom/build
/framework-docs/build
/integration-tests/build
/src/asciidoc/build
target/
/target/
# Eclipse artifacts, including WTP generated manifests
.classpath
@@ -43,4 +46,6 @@ atlassian-ide-plugin.xml
.gradletasknamecache
# VS Code
.vscode/
.vscode/
cached-antora-playbook.yml
+32 -22
View File
@@ -1,23 +1,33 @@
Juergen Hoeller <jhoeller@pivotal.io> jhoeller <jhoeller@vmware.com>
<jhoeller@pivotal.io> <jhoeller@vmware.com>
<jhoeller@pivotal.io> <jhoeller@gopivotal.com>
<rstoyanchev@pivotal.io> <rstoyanchev@vmware.com>
<rstoyanchev@pivotal.io> <rstoyanchev@gopivotal.com>
<pwebb@pivotal.io> <pwebb@vmware.com>
<pwebb@pivotal.io> <pwebb@gopivotal.com>
<cbeams@pivotal.io> <cbeams@vmware.com>
<cbeams@pivotal.io> <cbeams@gopivotal.com>
<cbeams@pivotal.io> <cbeams@gmail.com>
<apoutsma@pivotal.io> <apoutsma@vmware.com>
<apoutsma@pivotal.io> <apoutsma@gopivotal.com>
<apoutsma@pivotal.io> <poutsma@mac.com>
<ogierke@pivotal.io> <ogierke@vmware.com>
<ogierke@pivotal.io> <ogierke@gopivotal.com>
<dsyer@pivotal.io> <dsyer@vmware.com>
<dsyer@pivotal.io> <dsyer@gopivotal.com>
<dsyer@pivotal.io> <david_syer@hotmail.com>
<aclement@pivotal.io> <aclement@vmware.com>
<aclement@pivotal.io> <aclement@gopivotal.com>
<aclement@pivotal.io> <andrew.clement@gmail.com>
Juergen Hoeller <jhoeller@vmware.com>
Juergen Hoeller <jhoeller@vmware.com> <jhoeller@pivotal.io>
Juergen Hoeller <jhoeller@vmware.com> <jhoeller@gopivotal.com>
Rossen Stoyanchev <rstoyanchev@vmware.com>
Rossen Stoyanchev <rstoyanchev@vmware.com> <rstoyanchev@pivotal.io>
Rossen Stoyanchev <rstoyanchev@vmware.com> <rstoyanchev@gopivotal.com>
Phillip Webb <pwebb@vmware.com>
Phillip Webb <pwebb@vmware.com> <pwebb@pivotal.io>
Phillip Webb <pwebb@vmware.com> <pwebb@gopivotal.com>
Chris Beams <cbeams@vmware.com>
Chris Beams <cbeams@vmware.com> <cbeams@pivotal.io>
Chris Beams <cbeams@vmware.com> <cbeams@gopivotal.com>
Arjen Poutsma <apoutsma@vmware.com>
Arjen Poutsma <apoutsma@vmware.com> <apoutsma@pivotal.io>
Arjen Poutsma <apoutsma@vmware.com> <apoutsma@gopivotal.com>
Arjen Poutsma <apoutsma@vmware.com> <poutsma@mac.com>
Oliver Drotbohm <odrotbohm@vmware.com>
Oliver Drotbohm <odrotbohm@vmware.com> <ogierke@vmware.com>
Oliver Drotbohm <odrotbohm@vmware.com> <ogierke@pivotal.io>
Oliver Drotbohm <odrotbohm@vmware.com> <ogierke@gopivotal.com>
Dave Syer <dsyer@vmware.com>
Dave Syer <dsyer@vmware.com> <dsyer@pivotal.io>
Dave Syer <dsyer@vmware.com> <dsyer@gopivotal.com>
Dave Syer <dsyer@vmware.com> <david_syer@hotmail.com>
Andy Clement <aclement@vmware.com>
Andy Clement <aclement@vmware.com> <aclement@pivotal.io>
Andy Clement <aclement@vmware.com> <aclement@gopivotal.com>
Andy Clement <aclement@vmware.com> <andrew.clement@gmail.com>
Sam Brannen <sbrannen@vmware.com>
Sam Brannen <sbrannen@vmware.com> <sbrannen@pivotal.io>
Sam Brannen <sbrannen@vmware.com> <sam@sambrannen.com>
<dmitry.katsubo@gmail.com> <dmitry.katsubo@gmai.com>
Nick Williams <nicholas@nicholaswilliams.net> Nicholas Williams <nicholas@nicholaswilliams.net>
Nick Williams <nicholas@nicholaswilliams.net>
+1 -1
View File
@@ -1,3 +1,3 @@
# Enable auto-env through the sdkman_auto_env config
# Add key=value pairs of SDKs to use below
java=8.0.322-librca
java=8.0.382-librca
+3 -3
View File
@@ -14,16 +14,16 @@ For access to artifacts or a distribution zip, see the [Spring Framework Artifac
## Documentation
The Spring Framework maintains reference documentation ([published](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/) and [source](src/docs/asciidoc)), Github [wiki pages](https://github.com/spring-projects/spring-framework/wiki), and an
The Spring Framework maintains reference documentation ([published](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/) and [source](src/docs/asciidoc)), GitHub [wiki pages](https://github.com/spring-projects/spring-framework/wiki), and an
[API reference](https://docs.spring.io/spring-framework/docs/current/javadoc-api/). There are also [guides and tutorials](https://spring.io/guides) across Spring projects.
## Micro-Benchmarks
See the [Micro-Benchmarks](https://github.com/spring-projects/spring-framework/wiki/Micro-Benchmarks) Wiki page.
See the [Micro-Benchmarks](https://github.com/spring-projects/spring-framework/wiki/Micro-Benchmarks) wiki page.
## Build from Source
See the [Build from Source](https://github.com/spring-projects/spring-framework/wiki/Build-from-Source) Wiki page and the [CONTRIBUTING.md](CONTRIBUTING.md) file.
See the [Build from Source](https://github.com/spring-projects/spring-framework/wiki/Build-from-Source) wiki page and the [CONTRIBUTING.md](CONTRIBUTING.md) file.
## Continuous Integration Builds
+44 -39
View File
@@ -1,17 +1,17 @@
plugins {
id 'io.spring.dependency-management' version '1.0.11.RELEASE' apply false
id 'io.spring.nohttp' version '0.0.10'
id "io.freefair.aspectj" version '6.2.0' apply false
id 'io.freefair.aspectj' version '6.2.0' apply false
id 'org.jetbrains.dokka' version '1.6.10' apply false
id 'org.jetbrains.kotlin.jvm' version '1.5.32' apply false
id "org.jetbrains.kotlin.plugin.serialization" version "1.5.32" apply false
id 'org.jetbrains.kotlin.plugin.serialization' version "1.5.32" apply false
id 'org.asciidoctor.jvm.convert' version '3.3.2'
id 'org.asciidoctor.jvm.pdf' version '3.3.2'
id "org.unbroken-dome.xjc" version '2.0.0' apply false
id "com.github.ben-manes.versions" version '0.39.0'
id "com.github.johnrengelman.shadow" version '7.0.0' apply false
id 'org.unbroken-dome.xjc' version '2.0.0' apply false
id 'com.github.ben-manes.versions' version '0.39.0'
id 'com.github.johnrengelman.shadow' version '7.0.0' apply false
id 'de.undercouch.download' version '4.1.2'
id "me.champeau.jmh" version "0.6.6" apply false
id 'me.champeau.jmh' version "0.6.6" apply false
}
ext {
@@ -27,19 +27,19 @@ configure(allprojects) { project ->
dependencyManagement {
imports {
mavenBom "com.fasterxml.jackson:jackson-bom:2.12.6"
mavenBom "io.netty:netty-bom:4.1.75.Final"
mavenBom "io.projectreactor:reactor-bom:2020.0.18"
mavenBom "com.fasterxml.jackson:jackson-bom:2.12.7"
mavenBom "io.netty:netty-bom:4.1.101.Final"
mavenBom "io.projectreactor:reactor-bom:2020.0.38"
mavenBom "io.r2dbc:r2dbc-bom:Arabba-SR13"
mavenBom "io.rsocket:rsocket-bom:1.1.2"
mavenBom "org.eclipse.jetty:jetty-bom:9.4.46.v20220331"
mavenBom "io.rsocket:rsocket-bom:1.1.3"
mavenBom "org.eclipse.jetty:jetty-bom:9.4.53.v20231009"
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.5.32"
mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.5.2"
mavenBom "org.jetbrains.kotlinx:kotlinx-serialization-bom:1.2.2"
mavenBom "org.junit:junit-bom:5.8.2"
}
dependencies {
dependencySet(group: 'org.apache.logging.log4j', version: '2.17.2') {
dependencySet(group: 'org.apache.logging.log4j', version: '2.21.1') {
entry 'log4j-api'
entry 'log4j-core'
entry 'log4j-jul'
@@ -67,9 +67,9 @@ configure(allprojects) { project ->
dependency "io.reactivex:rxjava:1.3.8"
dependency "io.reactivex:rxjava-reactive-streams:1.2.1"
dependency "io.reactivex.rxjava2:rxjava:2.2.21"
dependency "io.reactivex.rxjava3:rxjava:3.1.3"
dependency "io.smallrye.reactive:mutiny:1.4.0"
dependency "io.projectreactor.tools:blockhound:1.0.6.RELEASE"
dependency "io.reactivex.rxjava3:rxjava:3.1.8"
dependency "io.smallrye.reactive:mutiny:1.9.0"
dependency "io.projectreactor.tools:blockhound:1.0.8.RELEASE"
dependency "com.caucho:hessian:4.0.63"
dependency "com.fasterxml:aalto-xml:1.3.1"
@@ -79,11 +79,11 @@ configure(allprojects) { project ->
dependency "com.google.code.gson:gson:2.8.9"
dependency "com.google.protobuf:protobuf-java-util:3.19.3"
dependency "com.googlecode.protobuf-java-format:protobuf-java-format:1.4"
dependency("com.thoughtworks.xstream:xstream:1.4.18") {
dependency("com.thoughtworks.xstream:xstream:1.4.19") {
exclude group: "xpp3", name: "xpp3_min"
exclude group: "xmlpull", name: "xmlpull"
}
dependency "org.apache.johnzon:johnzon-jsonb:1.2.16"
dependency "org.apache.johnzon:johnzon-jsonb:1.2.18"
dependency("org.codehaus.jettison:jettison:1.3.8") {
exclude group: "stax", name: "stax-api"
}
@@ -92,11 +92,11 @@ configure(allprojects) { project ->
entry 'jibx-run'
}
dependency "org.ogce:xpp3:1.1.6"
dependency "org.yaml:snakeyaml:1.30"
dependency "org.yaml:snakeyaml:1.33"
dependency "com.h2database:h2:2.1.210"
dependency "com.h2database:h2:2.1.214"
dependency "com.github.ben-manes.caffeine:caffeine:2.9.3"
dependency "com.github.librepdf:openpdf:1.3.27"
dependency "com.github.librepdf:openpdf:1.3.33"
dependency "com.rometools:rome:1.18.0"
dependency "commons-io:commons-io:2.5"
dependency "io.vavr:vavr:0.10.4"
@@ -124,22 +124,22 @@ configure(allprojects) { project ->
dependency "org.ehcache:jcache:1.0.1"
dependency "org.ehcache:ehcache:3.4.0"
dependency "org.hibernate:hibernate-core:5.4.33.Final"
dependency "org.hibernate:hibernate-validator:6.2.3.Final"
dependency "org.hibernate:hibernate-validator:6.2.5.Final"
dependency "org.webjars:webjars-locator-core:0.48"
dependency "org.webjars:underscorejs:1.8.3"
dependencySet(group: 'org.apache.tomcat', version: '9.0.62') {
dependencySet(group: 'org.apache.tomcat', version: '9.0.82') {
entry 'tomcat-util'
entry('tomcat-websocket') {
exclude group: "org.apache.tomcat", name: "tomcat-servlet-api"
exclude group: "org.apache.tomcat", name: "tomcat-websocket-api"
}
}
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.62') {
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.82') {
entry 'tomcat-embed-core'
entry 'tomcat-embed-websocket'
}
dependencySet(group: 'io.undertow', version: '2.2.17.Final') {
dependencySet(group: 'io.undertow', version: '2.2.28.Final') {
entry 'undertow-core'
entry('undertow-servlet') {
exclude group: "org.jboss.spec.javax.servlet", name: "jboss-servlet-api_4.0_spec"
@@ -150,7 +150,7 @@ configure(allprojects) { project ->
}
}
dependency "org.eclipse.jetty:jetty-reactive-httpclient:1.1.11"
dependency "org.eclipse.jetty:jetty-reactive-httpclient:1.1.13"
dependency 'org.apache.httpcomponents.client5:httpclient5:5.1.3'
dependency 'org.apache.httpcomponents.core5:httpcore5-reactive:5.1.3'
dependency("org.apache.httpcomponents:httpclient:4.5.13") {
@@ -188,17 +188,17 @@ configure(allprojects) { project ->
exclude group: "junit", name: "junit"
}
dependency "org.testng:testng:7.4.0"
dependency "org.junit.support:testng-engine:1.0.1"
dependency "org.hamcrest:hamcrest:2.1"
dependency "org.junit.support:testng-engine:1.0.4"
dependency "org.hamcrest:hamcrest:2.2"
dependency "org.awaitility:awaitility:3.1.6"
dependency "org.assertj:assertj-core:3.22.0"
dependency "org.assertj:assertj-core:3.24.2"
dependencySet(group: 'org.xmlunit', version: '2.9.0') {
entry 'xmlunit-assertj'
entry('xmlunit-matchers') {
exclude group: "org.hamcrest", name: "hamcrest-core"
}
}
dependencySet(group: 'org.mockito', version: '4.4.0') {
dependencySet(group: 'org.mockito', version: '4.9.0') { // spring-beans tests fail with 4.10+
entry('mockito-core') {
exclude group: "org.hamcrest", name: "hamcrest-core"
}
@@ -206,10 +206,10 @@ configure(allprojects) { project ->
}
dependency "io.mockk:mockk:1.12.1"
dependency("net.sourceforge.htmlunit:htmlunit:2.60.0") {
dependency("net.sourceforge.htmlunit:htmlunit:2.70.0") {
exclude group: "commons-logging", name: "commons-logging"
}
dependency("org.seleniumhq.selenium:htmlunit-driver:2.60.0") {
dependency("org.seleniumhq.selenium:htmlunit-driver:2.70.0") {
exclude group: "commons-logging", name: "commons-logging"
}
dependency("org.seleniumhq.selenium:selenium-java:3.141.59") {
@@ -217,8 +217,8 @@ configure(allprojects) { project ->
exclude group: "io.netty", name: "netty"
}
dependency "org.skyscreamer:jsonassert:1.5.0"
dependency "com.jayway.jsonpath:json-path:2.6.0"
dependency "org.bouncycastle:bcpkix-jdk15on:1.66"
dependency "com.jayway.jsonpath:json-path:2.7.0"
dependency "org.bouncycastle:bcpkix-jdk18on:1.71"
dependencySet(group: 'org.apache.tiles', version: '3.0.8') {
entry 'tiles-api'
@@ -238,7 +238,7 @@ configure(allprojects) { project ->
dependency "com.ibm.websphere:uow:6.0.2.17"
dependency "com.jamonapi:jamon:2.82"
dependency "joda-time:joda-time:2.10.13"
dependency "org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.10"
dependency "org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.12"
dependency "org.javamoney:moneta:1.3"
dependency "com.sun.activation:javax.activation:1.2.0"
@@ -340,7 +340,7 @@ configure([rootProject] + javaProjects) { project ->
}
checkstyle {
toolVersion = "10.1"
toolVersion = "10.12.5"
configDirectory.set(rootProject.file("src/checkstyle"))
}
@@ -377,9 +377,9 @@ configure([rootProject] + javaProjects) { project ->
"https://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
"https://www.ehcache.org/apidocs/2.10.4/",
"https://www.quartz-scheduler.org/api/2.3.0/",
"https://fasterxml.github.io/jackson-core/javadoc/2.10/",
"https://fasterxml.github.io/jackson-databind/javadoc/2.10/",
"https://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.10/",
"https://www.javadoc.io/doc/com.fasterxml.jackson.core/jackson-core/2.12.7/",
"https://www.javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind/2.12.7/",
"https://www.javadoc.io/doc/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.12.7/",
"https://hc.apache.org/httpcomponents-client-5.1.x/current/httpclient5/apidocs/",
"https://projectreactor.io/docs/test/release/api/",
"https://junit.org/junit4/javadoc/4.13.2/",
@@ -415,7 +415,7 @@ configure(rootProject) {
source.exclude "**/test-output/**"
allowlistFile = project.file("src/nohttp/allowlist.lines")
def rootPath = file(rootDir).toPath()
def projectDirs = allprojects.collect { it.projectDir } + "${rootDir}/buildSrc"
def projectDirs = allprojects.collect { it.projectDir } + "${rootDir}/spring-core-test" + "${rootDir}/buildSrc" + "${rootDir}/framework-docs"
projectDirs.forEach { dir ->
[ 'bin', 'build', 'out', '.settings' ]
.collect { rootPath.relativize(new File(dir, it).toPath()) }
@@ -426,6 +426,10 @@ configure(rootProject) {
}
}
tasks.named("checkstyleNohttp").configure {
maxHeapSize = "1g"
}
publishing {
publications {
mavenJava(MavenPublication) {
@@ -435,4 +439,5 @@ configure(rootProject) {
}
}
}
}
+3
View File
@@ -15,3 +15,6 @@ changelog:
sort: "title"
labels:
- "type: dependency-upgrade"
contributors:
exclude:
names: ["bclozel", "jhoeller", "poutsma", "rstoyanchev", "sbrannen", "sdeleuze", "snicoll"]
+1 -2
View File
@@ -1,11 +1,10 @@
FROM ubuntu:focal-20220404
FROM ubuntu:jammy-20230624
ADD setup.sh /setup.sh
ADD get-jdk-url.sh /get-jdk-url.sh
RUN ./setup.sh java8
ENV JAVA_HOME /opt/openjdk/java8
ENV JDK11 /opt/openjdk/java11
ENV JDK17 /opt/openjdk/java17
ENV PATH $JAVA_HOME/bin:$PATH
+4 -10
View File
@@ -3,18 +3,12 @@ set -e
case "$1" in
java8)
echo "https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u322-b06/OpenJDK8U-jdk_x64_linux_hotspot_8u322b06.tar.gz"
echo "https://github.com/bell-sw/Liberica/releases/download/8u372+7/bellsoft-jdk8u372+7-linux-amd64.tar.gz"
;;
java11)
echo "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.14.1%2B1/OpenJDK11U-jdk_x64_linux_hotspot_11.0.14.1_1.tar.gz"
java17)
echo "https://github.com/bell-sw/Liberica/releases/download/17.0.7+7/bellsoft-jdk17.0.7+7-linux-amd64.tar.gz"
;;
java17)
echo "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.2%2B8/OpenJDK17U-jdk_x64_linux_hotspot_17.0.2_8.tar.gz"
;;
java18)
echo "https://github.com/adoptium/temurin18-binaries/releases/download/jdk-18%2B36/OpenJDK18U-jdk_x64_linux_hotspot_18_36.tar.gz"
;;
*)
*)
echo $"Unknown java version"
exit 1
esac
+1 -3
View File
@@ -14,15 +14,13 @@ rm -rf /var/lib/apt/lists/*
curl https://raw.githubusercontent.com/spring-io/concourse-java-scripts/v0.0.4/concourse-java.sh > /opt/concourse-java.sh
curl --output /opt/concourse-release-scripts.jar https://repo.spring.io/release/io/spring/concourse/releasescripts/concourse-release-scripts/0.3.2/concourse-release-scripts-0.3.2.jar
###########################################################
# JAVA
###########################################################
mkdir -p /opt/openjdk
pushd /opt/openjdk > /dev/null
for jdk in java8 java11 java17
for jdk in java8 java17
do
JDK_URL=$( /get-jdk-url.sh $jdk )
mkdir $jdk
+1
View File
@@ -1,5 +1,6 @@
github-repo: "https://github.com/spring-projects/spring-framework.git"
github-repo-name: "spring-projects/spring-framework"
sonatype-staging-profile: "org.springframework"
docker-hub-organization: "springci"
artifactory-server: "https://repo.spring.io"
branch: "5.3.x"
+25 -98
View File
@@ -12,7 +12,7 @@ anchors:
SONATYPE_USERNAME: ((sonatype-username))
SONATYPE_PASSWORD: ((sonatype-password))
SONATYPE_URL: ((sonatype-url))
SONATYPE_STAGING_PROFILE_ID: ((sonatype-staging-profile-id))
SONATYPE_STAGING_PROFILE: ((sonatype-staging-profile))
artifactory-task-params: &artifactory-task-params
ARTIFACTORY_SERVER: ((artifactory-server))
ARTIFACTORY_USERNAME: ((artifactory-username))
@@ -23,7 +23,6 @@ anchors:
docker-resource-source: &docker-resource-source
username: ((docker-hub-username))
password: ((docker-hub-password))
tag: ((milestone))
slack-fail-params: &slack-fail-params
text: >
:concourse-failed: <https://ci.spring.io/teams/${BUILD_TEAM_NAME}/pipelines/${BUILD_PIPELINE_NAME}/jobs/${BUILD_JOB_NAME}/builds/${BUILD_NAME}|${BUILD_PIPELINE_NAME} ${BUILD_JOB_NAME} failed!>
@@ -44,31 +43,31 @@ resource_types:
- name: registry-image
type: registry-image
source:
<<: *docker-resource-source
repository: concourse/registry-image-resource
tag: 1.5.0
tag: 1.7.1
- name: artifactory-resource
type: registry-image
source:
<<: *docker-resource-source
repository: springio/artifactory-resource
tag: 0.0.17
tag: 0.0.18
- name: github-release
type: registry-image
source:
<<: *docker-resource-source
repository: concourse/github-release-resource
tag: 1.5.5
tag: 1.8.0
- name: github-status-resource
type: registry-image
source:
<<: *docker-resource-source
repository: dpb587/github-status-resource
tag: master
- name: pull-request
type: registry-image
source:
repository: teliaoss/github-pr-resource
tag: v0.23.0
- name: slack-notification
type: registry-image
source:
<<: *docker-resource-source
repository: cfcommunity/slack-notification-resource
tag: latest
resources:
@@ -92,11 +91,12 @@ resources:
branch: ((branch))
paths: ["ci/images/*"]
- name: ci-image
type: docker-image
type: registry-image
icon: docker
source:
<<: *docker-resource-source
repository: ((docker-hub-organization))/spring-framework-ci
tag: ((milestone))
- name: artifactory-repo
type: artifactory-resource
icon: package-variant
@@ -105,14 +105,6 @@ resources:
username: ((artifactory-username))
password: ((artifactory-password))
build_name: ((build-name))
- name: git-pull-request
type: pull-request
icon: source-pull
source:
access_token: ((github-ci-pull-request-token))
repository: ((github-repo-name))
base_branch: ((branch))
ignore_paths: ["ci/*"]
- name: repo-status-build
type: github-status-resource
icon: eye-check-outline
@@ -121,14 +113,6 @@ resources:
access_token: ((github-ci-status-token))
branch: ((branch))
context: build
- name: repo-status-jdk11-build
type: github-status-resource
icon: eye-check-outline
source:
repository: ((github-repo-name))
access_token: ((github-ci-status-token))
branch: ((branch))
context: jdk11-build
- name: repo-status-jdk17-build
type: github-status-resource
icon: eye-check-outline
@@ -162,13 +146,20 @@ resources:
jobs:
- name: build-ci-images
plan:
- get: ci-images-git-repo
trigger: true
- in_parallel:
- get: git-repo
- get: ci-images-git-repo
trigger: true
- task: build-ci-image
privileged: true
file: git-repo/ci/tasks/build-ci-image.yml
output_mapping:
image: ci-image
vars:
ci-image-name: ci-image
<<: *docker-resource-source
- put: ci-image
params:
build: ci-images-git-repo/ci/images
dockerfile: ci-images-git-repo/ci/images/ci-image/Dockerfile
image: ci-image/image.tar
- name: build
serial: true
public: true
@@ -226,34 +217,6 @@ jobs:
"zip.type": "schema"
get_params:
threads: 8
- name: jdk11-build
serial: true
public: true
plan:
- get: ci-image
- get: git-repo
- get: every-morning
trigger: true
- put: repo-status-jdk11-build
params: { state: "pending", commit: "git-repo" }
- do:
- task: check-project
image: ci-image
file: git-repo/ci/tasks/check-project.yml
privileged: true
timeout: ((task-timeout))
params:
TEST_TOOLCHAIN: 11
<<: *build-project-task-params
on_failure:
do:
- put: repo-status-jdk11-build
params: { state: "failure", commit: "git-repo" }
- put: slack-alert
params:
<<: *slack-fail-params
- put: repo-status-jdk11-build
params: { state: "success", commit: "git-repo" }
- name: jdk17-build
serial: true
public: true
@@ -271,7 +234,7 @@ jobs:
privileged: true
timeout: ((task-timeout))
params:
TEST_TOOLCHAIN: 15
TEST_TOOLCHAIN: 17
<<: *build-project-task-params
on_failure:
do:
@@ -282,37 +245,6 @@ jobs:
<<: *slack-fail-params
- put: repo-status-jdk17-build
params: { state: "success", commit: "git-repo" }
- name: build-pull-requests
serial: true
public: true
plan:
- get: ci-image
- get: git-repo
resource: git-pull-request
trigger: true
version: every
- do:
- put: git-pull-request
params:
path: git-repo
status: pending
- task: build-pr
image: ci-image
file: git-repo/ci/tasks/build-pr.yml
privileged: true
timeout: ((task-timeout))
params:
BRANCH: ((branch))
on_success:
put: git-pull-request
params:
path: git-repo
status: success
on_failure:
put: git-pull-request
params:
path: git-repo
status: failure
- name: stage-milestone
serial: true
plan:
@@ -345,7 +277,6 @@ jobs:
download_artifacts: false
save_build_info: true
- task: promote
image: ci-image
file: git-repo/ci/tasks/promote-version.yml
params:
RELEASE_TYPE: M
@@ -390,7 +321,6 @@ jobs:
download_artifacts: false
save_build_info: true
- task: promote
image: ci-image
file: git-repo/ci/tasks/promote-version.yml
params:
RELEASE_TYPE: RC
@@ -435,7 +365,6 @@ jobs:
download_artifacts: true
save_build_info: true
- task: promote
image: ci-image
file: git-repo/ci/tasks/promote-version.yml
params:
RELEASE_TYPE: RELEASE
@@ -463,10 +392,8 @@ jobs:
groups:
- name: "builds"
jobs: ["build", "jdk11-build", "jdk17-build"]
jobs: ["build", "jdk17-build"]
- name: "releases"
jobs: ["stage-milestone", "stage-rc", "stage-release", "promote-milestone", "promote-rc", "promote-release", "create-github-release"]
- name: "ci-images"
jobs: ["build-ci-images"]
- name: "pull-requests"
jobs: [ "build-pull-requests" ]
+1 -1
View File
@@ -4,6 +4,6 @@ set -e
source $(dirname $0)/common.sh
pushd git-repo > /dev/null
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK11,JDK15 \
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17 \
-PmainToolchain=${MAIN_TOOLCHAIN} -PtestToolchain=${TEST_TOOLCHAIN} --no-daemon --max-workers=4 check
popd > /dev/null
+2 -2
View File
@@ -6,11 +6,11 @@ CONFIG_DIR=git-repo/ci/config
version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
export BUILD_INFO_LOCATION=$(pwd)/artifactory-repo/build-info.json
java -jar /opt/concourse-release-scripts.jar \
java -jar /concourse-release-scripts.jar \
--spring.config.location=${CONFIG_DIR}/release-scripts.yml \
publishToCentral $RELEASE_TYPE $BUILD_INFO_LOCATION artifactory-repo || { exit 1; }
java -jar /opt/concourse-release-scripts.jar \
java -jar /concourse-release-scripts.jar \
--spring.config.location=${CONFIG_DIR}/release-scripts.yml \
promote $RELEASE_TYPE $BUILD_INFO_LOCATION || { exit 1; }
-8
View File
@@ -1,8 +0,0 @@
#!/bin/bash
export BUILD_INFO_LOCATION=$(pwd)/artifactory-repo/build-info.json
version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
java -jar /opt/concourse-release-scripts.jar syncToCentral "RELEASE" $BUILD_INFO_LOCATION || { exit 1; }
echo "Sync complete"
echo $version > version/version
+29
View File
@@ -0,0 +1,29 @@
---
platform: linux
image_resource:
type: registry-image
source:
repository: concourse/oci-build-task
tag: 0.10.0
username: ((docker-hub-username))
password: ((docker-hub-password))
inputs:
- name: ci-images-git-repo
outputs:
- name: image
caches:
- path: ci-image-cache
params:
CONTEXT: ci-images-git-repo/ci/images
DOCKERFILE: ci-images-git-repo/ci/images/ci-image/Dockerfile
DOCKER_HUB_AUTH: ((docker-hub-auth))
run:
path: /bin/sh
args:
- "-c"
- |
mkdir -p /root/.docker
cat > /root/.docker/config.json <<EOF
{ "auths": { "https://index.docker.io/v1/": { "auth": "$DOCKER_HUB_AUTH" }}}
EOF
build
+2
View File
@@ -5,6 +5,8 @@ image_resource:
source:
repository: springio/github-changelog-generator
tag: '0.0.7'
username: ((docker-hub-username))
password: ((docker-hub-password))
inputs:
- name: git-repo
- name: artifactory-repo
+8 -1
View File
@@ -1,5 +1,12 @@
---
platform: linux
image_resource:
type: registry-image
source:
repository: springio/concourse-release-scripts
tag: '0.3.4'
username: ((docker-hub-username))
password: ((docker-hub-password))
inputs:
- name: git-repo
- name: artifactory-repo
@@ -13,6 +20,6 @@ params:
SONATYPE_USER:
SONATYPE_PASSWORD:
SONATYPE_URL:
SONATYPE_STAGING_PROFILE_ID:
SONATYPE_STAGING_PROFILE:
run:
path: git-repo/ci/scripts/promote-version.sh
+3 -3
View File
@@ -1,5 +1,5 @@
version=5.3.19
org.gradle.jvmargs=-Xmx1536M
version=5.3.31
org.gradle.jvmargs=-Xmx2048m
org.gradle.caching=true
org.gradle.parallel=true
kotlin.stdlib.default.dependency=false
kotlin.stdlib.default.dependency=false
+4 -5
View File
@@ -3,7 +3,7 @@ configurations {
}
dependencies {
asciidoctorExt("io.spring.asciidoctor:spring-asciidoctor-extensions-block-switch:0.5.0")
asciidoctorExt("io.spring.asciidoctor:spring-asciidoctor-extensions-block-switch:0.6.1")
}
repositories {
@@ -73,9 +73,8 @@ pluginManager.withPlugin("kotlin") {
}
task downloadResources(type: Download) {
def version = "0.2.5"
src "https://repo.spring.io/release/io/spring/docresources/" +
"spring-doc-resources/$version/spring-doc-resources-${version}.zip"
src "https://repo.spring.io/artifactory/snapshot/io/spring/docresources/" +
"spring-doc-resources/0.2.6-SNAPSHOT/spring-doc-resources-0.2.6-20210308.231804-2.zip"
dest project.file("$buildDir/docs/spring-doc-resources.zip")
onlyIfModified true
useETag "all"
@@ -153,7 +152,7 @@ asciidoctorPdf {
task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'asciidoctorPdf', 'dokkaHtmlMultiModule']) {
group = "Distribution"
description = "Builds -${archiveClassifier} archive containing api and reference " +
"for deployment at https://docs.spring.io/spring-framework/docs."
"for deployment at https://docs.spring.io/spring-framework/docs/."
archiveBaseName.set("spring-framework")
archiveClassifier.set("docs")
+2
View File
@@ -72,6 +72,7 @@ eclipse.classpath.file.whenMerged {
// Include project specific settings
task eclipseSettings(type: Copy) {
from rootProject.files(
'src/eclipse/org.eclipse.core.resources.prefs',
'src/eclipse/org.eclipse.jdt.core.prefs',
'src/eclipse/org.eclipse.jdt.ui.prefs')
into project.file('.settings/')
@@ -79,6 +80,7 @@ task eclipseSettings(type: Copy) {
}
task cleanEclipseSettings(type: Delete) {
delete project.file('.settings/org.eclipse.core.resources.prefs')
delete project.file('.settings/org.eclipse.jdt.core.prefs')
delete project.file('.settings/org.eclipse.jdt.ui.prefs')
}
+4 -15
View File
@@ -81,6 +81,10 @@ plugins.withType(JavaPlugin) {
javaLauncher = javaToolchains.launcherFor {
languageVersion = testLanguageVersion
}
if(testLanguageVersion == JavaLanguageVersion.of(17)) {
jvmArgs(["--add-opens=java.base/java.lang=ALL-UNNAMED",
"--add-opens=java.base/java.util=ALL-UNNAMED"])
}
}
}
}
@@ -130,21 +134,6 @@ pluginManager.withPlugin("kotlin") {
}
}
}
if (testToolchainConfigured()) {
def testLanguageVersion = testToolchainLanguageVersion()
def compiler = javaToolchains.compilerFor {
languageVersion = testLanguageVersion
}
// See https://kotlinlang.org/docs/gradle.html#attributes-specific-for-jvm
def javaVersion = testLanguageVersion.toString() == '8' ? '1.8' : testLanguageVersion.toString()
compileTestKotlin {
kotlinOptions {
jvmTarget = javaVersion
jdkHome = compiler.get().metadata.installationPath.asFile.absolutePath
}
}
}
}
// Configure the JMH plugin to use the toolchain for generating and running JMH bytecode
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+1 -1
View File
@@ -31,6 +31,6 @@ You'll notice these files are already intentionally in .gitignore. The same poli
## FAQ
Q. What about IntelliJ IDEA's own [Gradle support](https://confluence.jetbrains.net/display/IDEADEV/Gradle+integration)?
Q. What about IntelliJ IDEA's own [Gradle support](https://www.jetbrains.com/help/idea/gradle.html)?
A. Keep an eye on https://youtrack.jetbrains.com/issue/IDEA-53476
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@ import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatException;
/**
* Integration tests for advice invocation order for advice configured via the
@@ -52,7 +52,7 @@ class AopNamespaceHandlerAdviceOrderIntegrationTests {
assertThat(aspect.invocations).containsExactly("around - start", "before", "around - end", "after", "after returning");
aspect.invocations.clear();
assertThatExceptionOfType(Exception.class).isThrownBy(() -> echo.echo(new Exception()));
assertThatException().isThrownBy(() -> echo.echo(new Exception()));
assertThat(aspect.invocations).containsExactly("around - start", "before", "around - end", "after", "after throwing");
}
}
@@ -69,7 +69,7 @@ class AopNamespaceHandlerAdviceOrderIntegrationTests {
assertThat(aspect.invocations).containsExactly("around - start", "before", "around - end", "after returning", "after");
aspect.invocations.clear();
assertThatExceptionOfType(Exception.class).isThrownBy(() -> echo.echo(new Exception()));
assertThatException().isThrownBy(() -> echo.echo(new Exception()));
assertThat(aspect.invocations).containsExactly("around - start", "before", "around - end", "after throwing", "after");
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@ import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatException;
/**
* Integration tests for advice invocation order for advice configured via
@@ -65,8 +65,7 @@ class AspectJAutoProxyAdviceOrderIntegrationTests {
assertThat(aspect.invocations).containsExactly("around - start", "before", "after returning", "after", "around - end");
aspect.invocations.clear();
assertThatExceptionOfType(Exception.class).isThrownBy(
() -> echo.echo(new Exception()));
assertThatException().isThrownBy(() -> echo.echo(new Exception()));
assertThat(aspect.invocations).containsExactly("around - start", "before", "after throwing", "after", "around - end");
}
}
@@ -95,8 +94,7 @@ class AspectJAutoProxyAdviceOrderIntegrationTests {
assertThat(aspect.invocations).containsExactly("around - start", "before", "after returning", "after", "around - end");
aspect.invocations.clear();
assertThatExceptionOfType(Exception.class).isThrownBy(
() -> echo.echo(new Exception()));
assertThatException().isThrownBy(() -> echo.echo(new Exception()));
assertThat(aspect.invocations).containsExactly("around - start", "before", "after throwing", "after", "around - end");
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Repository;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatException;
/**
* Integration tests for the @EnableCaching annotation.
@@ -62,8 +62,7 @@ class EnableCachingIntegrationTests {
// this test is a bit fragile, but gets the job done, proving that an
// attempt was made to look up the AJ aspect. It's due to classpath issues
// in .integration-tests that it's not found.
assertThatExceptionOfType(Exception.class).isThrownBy(
ctx::refresh)
assertThatException().isThrownBy(ctx::refresh)
.withMessageContaining("AspectJCachingConfiguration");
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,8 +60,8 @@ class ScheduledAndTransactionalAnnotationIntegrationTests {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(Config.class, JdkProxyTxConfig.class, RepoConfigA.class);
assertThatExceptionOfType(BeanCreationException.class)
.isThrownBy(ctx::refresh)
.withCauseInstanceOf(IllegalStateException.class);
.isThrownBy(ctx::refresh)
.withCauseInstanceOf(IllegalStateException.class);
}
@Test
@@ -70,7 +70,7 @@ class ScheduledAndTransactionalAnnotationIntegrationTests {
ctx.register(Config.class, SubclassProxyTxConfig.class, RepoConfigA.class);
ctx.refresh();
Thread.sleep(100); // allow @Scheduled method to be called several times
Thread.sleep(200); // allow @Scheduled method to be called several times
MyRepository repository = ctx.getBean(MyRepository.class);
CallCountingTransactionManager txManager = ctx.getBean(CallCountingTransactionManager.class);
@@ -85,7 +85,7 @@ class ScheduledAndTransactionalAnnotationIntegrationTests {
ctx.register(Config.class, JdkProxyTxConfig.class, RepoConfigB.class);
ctx.refresh();
Thread.sleep(100); // allow @Scheduled method to be called several times
Thread.sleep(200); // allow @Scheduled method to be called several times
MyRepositoryWithScheduledMethod repository = ctx.getBean(MyRepositoryWithScheduledMethod.class);
CallCountingTransactionManager txManager = ctx.getBean(CallCountingTransactionManager.class);
@@ -100,7 +100,7 @@ class ScheduledAndTransactionalAnnotationIntegrationTests {
ctx.register(AspectConfig.class, MyRepositoryWithScheduledMethodImpl.class);
ctx.refresh();
Thread.sleep(100); // allow @Scheduled method to be called several times
Thread.sleep(200); // allow @Scheduled method to be called several times
MyRepositoryWithScheduledMethod repository = ctx.getBean(MyRepositoryWithScheduledMethod.class);
assertThat(AopUtils.isCglibProxy(repository)).isTrue();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@ import org.springframework.transaction.interceptor.BeanFactoryTransactionAttribu
import org.springframework.transaction.testfixture.CallCountingTransactionManager;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatException;
/**
* Integration tests for the @EnableTransactionManagement annotation.
@@ -98,7 +98,7 @@ class EnableTransactionManagementIntegrationTests {
// this test is a bit fragile, but gets the job done, proving that an
// attempt was made to look up the AJ aspect. It's due to classpath issues
// in .integration-tests that it's not found.
assertThatExceptionOfType(Exception.class)
assertThatException()
.isThrownBy(ctx::refresh)
.withMessageContaining("AspectJJtaTransactionManagementConfiguration");
}
+2 -2
View File
@@ -7,8 +7,8 @@ pluginManagement {
}
plugins {
id "com.gradle.enterprise" version "3.8.1"
id "io.spring.ge.conventions" version "0.0.9"
id "com.gradle.enterprise" version "3.12.1"
id "io.spring.ge.conventions" version "0.0.13"
}
include "spring-aop"
@@ -63,7 +63,7 @@ public interface Joinpoint {
/**
* Return the static part of this joinpoint.
* <p>The static part is an accessible object on which a chain of
* interceptors are installed.
* interceptors is installed.
*/
@Nonnull
AccessibleObject getStaticPart();
@@ -36,7 +36,7 @@ public interface IntroductionAwareMethodMatcher extends MethodMatcher {
* @param targetClass the target class
* @param hasIntroductions {@code true} if the object on whose behalf we are
* asking is the subject on one or more introductions; {@code false} otherwise
* @return whether or not this method matches statically
* @return whether this method matches statically
*/
boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions);
@@ -60,7 +60,7 @@ public interface MethodMatcher {
* will be made.
* @param method the candidate method
* @param targetClass the target class
* @return whether or not this method matches statically
* @return whether this method matches statically
*/
boolean matches(Method method, Class<?> targetClass);
@@ -70,7 +70,7 @@ public interface MethodMatcher {
* runtime even if the 2-arg matches method returns {@code true}?
* <p>Can be invoked when an AOP proxy is created, and need not be invoked
* again before each method invocation,
* @return whether or not a runtime match via the 3-arg
* @return whether a runtime match via the 3-arg
* {@link #matches(java.lang.reflect.Method, Class, Object[])} method
* is required if static matching passed
*/
@@ -18,7 +18,7 @@ package org.springframework.aop;
/**
* Marker interface implemented by all AOP proxies. Used to detect
* whether or not objects are Spring-generated proxies.
* whether objects are Spring-generated proxies.
*
* @author Rob Harrop
* @since 2.0.1
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -368,7 +368,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
* to which argument name. There are multiple strategies for determining
* this binding, which are arranged in a ChainOfResponsibility.
*/
public final synchronized void calculateArgumentBindings() {
public final void calculateArgumentBindings() {
// The simple case... nothing to bind.
if (this.argumentsIntrospected || this.parameterTypes.length == 0) {
return;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,6 +38,14 @@ import org.springframework.util.StringUtils;
* for an advice method from the pointcut expression, returning, and throwing clauses.
* If an unambiguous interpretation is not available, it returns {@code null}.
*
* <h3>Algorithm Summary</h3>
* <p>If an unambiguous binding can be deduced, then it is.
* If the advice requirements cannot possibly be satisfied, then {@code null}
* is returned. By setting the {@link #setRaiseExceptions(boolean) raiseExceptions}
* property to {@code true}, descriptive exceptions will be thrown instead of
* returning {@code null} in the case that the parameter names cannot be discovered.
*
* <h3>Algorithm Details</h3>
* <p>This class interprets arguments in the following way:
* <ol>
* <li>If the first parameter of the method is of type {@link JoinPoint}
@@ -65,15 +73,15 @@ import org.springframework.util.StringUtils;
* zero we proceed to the next stage. If {@code a} &gt; 1 then an
* {@code AmbiguousBindingException} is raised. If {@code a} == 1,
* and there are no unbound arguments of type {@code Annotation+},
* then an {@code IllegalArgumentException} is raised. if there is
* then an {@code IllegalArgumentException} is raised. If there is
* exactly one such argument, then the corresponding parameter name is
* assigned the value from the pointcut expression.</li>
* <li>If a returningName has been set, and there are no unbound arguments
* <li>If a {@code returningName} has been set, and there are no unbound arguments
* then an {@code IllegalArgumentException} is raised. If there is
* more than one unbound argument then an
* {@code AmbiguousBindingException} is raised. If there is exactly
* one unbound argument then the corresponding parameter name is assigned
* the value &lt;returningName&gt;.</li>
* the value of the {@code returningName}.</li>
* <li>If there remain unbound arguments, then the pointcut expression is
* examined once more for {@code this}, {@code target}, and
* {@code args} pointcut expressions used in the binding form (binding
@@ -99,20 +107,12 @@ import org.springframework.util.StringUtils;
* <p>The behavior on raising an {@code IllegalArgumentException} or
* {@code AmbiguousBindingException} is configurable to allow this discoverer
* to be used as part of a chain-of-responsibility. By default the condition will
* be logged and the {@code getParameterNames(..)} method will simply return
* be logged and the {@link #getParameterNames(Method)} method will simply return
* {@code null}. If the {@link #setRaiseExceptions(boolean) raiseExceptions}
* property is set to {@code true}, the conditions will be thrown as
* {@code IllegalArgumentException} and {@code AmbiguousBindingException},
* respectively.
*
* <p>Was that perfectly clear? ;)
*
* <p>Short version: If an unambiguous binding can be deduced, then it is.
* If the advice requirements cannot possibly be satisfied, then {@code null}
* is returned. By setting the {@link #setRaiseExceptions(boolean) raiseExceptions}
* property to {@code true}, descriptive exceptions will be thrown instead of
* returning {@code null} in the case that the parameter names cannot be discovered.
*
* @author Adrian Colyer
* @author Juergen Hoeller
* @since 2.0
@@ -158,7 +158,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
/** The pointcut expression associated with the advice, as a simple String. */
@Nullable
private String pointcutExpression;
private final String pointcutExpression;
private boolean raiseExceptions;
@@ -197,7 +197,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
/**
* If {@code afterReturning} advice binds the return value, the
* returning variable name must be specified.
* {@code returning} variable name must be specified.
* @param returningName the name of the returning variable
*/
public void setReturningName(@Nullable String returningName) {
@@ -206,18 +206,17 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
/**
* If {@code afterThrowing} advice binds the thrown value, the
* throwing variable name must be specified.
* {@code throwing} variable name must be specified.
* @param throwingName the name of the throwing variable
*/
public void setThrowingName(@Nullable String throwingName) {
this.throwingName = throwingName;
}
/**
* Deduce the parameter names for an advice method.
* <p>See the {@link AspectJAdviceParameterNameDiscoverer class level javadoc}
* for this class for details of the algorithm used.
* <p>See the {@link AspectJAdviceParameterNameDiscoverer class-level javadoc}
* for this class for details on the algorithm used.
* @param method the target {@link Method}
* @return the parameter names
*/
@@ -316,13 +315,13 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
private void bindParameterName(int index, String name) {
private void bindParameterName(int index, @Nullable String name) {
this.parameterNameBindings[index] = name;
this.numberOfRemainingUnboundArguments--;
}
/**
* If the first parameter is of type JoinPoint or ProceedingJoinPoint,bind "thisJoinPoint" as
* If the first parameter is of type JoinPoint or ProceedingJoinPoint, bind "thisJoinPoint" as
* parameter name and return true, else return false.
*/
private boolean maybeBindThisJoinPoint() {
@@ -367,8 +366,8 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
if (throwableIndex == -1) {
throw new IllegalStateException("Binding of throwing parameter '" + this.throwingName
+ "' could not be completed as no available arguments are a subtype of Throwable");
throw new IllegalStateException("Binding of throwing parameter '" + this.throwingName +
"' could not be completed as no available arguments are a subtype of Throwable");
}
else {
bindParameterName(throwableIndex, this.throwingName);
@@ -400,7 +399,6 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
}
/**
* Parse the string pointcut expression looking for:
* &#64;this, &#64;target, &#64;args, &#64;within, &#64;withincode, &#64;annotation.
@@ -465,7 +463,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
}
/*
/**
* If the token starts meets Java identifier conventions, it's in.
*/
@Nullable
@@ -533,7 +531,6 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
}
if (varNames.size() > 1) {
throw new AmbiguousBindingException("Found " + varNames.size() +
" candidate this(), target() or args() variables but only one unbound argument slot");
@@ -609,7 +606,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
// else varNames.size must be 0 and we have nothing to bind.
}
/*
/**
* We've found the start of a binding pointcut at the given index into the
* token array. Now we need to extract the pointcut body and return it.
*/
@@ -709,7 +706,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
return false;
}
/*
/**
* Return {@code true} if the given argument type is a subclass
* of the given supertype.
*/
@@ -737,7 +734,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
return count;
}
/*
/**
* Find the argument index with the given type, and bind the given
* {@code varName} in that position.
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -248,8 +248,8 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
/**
* If a pointcut expression has been specified in XML, the user cannot
* write {@code and} as "&&" (though &amp;&amp; will work).
* We also allow {@code and} between two pointcut sub-expressions.
* write "and" as "&&" (though {@code &amp;&amp;} will work).
* <p>We also allow "and" between two pointcut sub-expressions.
* <p>This method converts back to {@code &&} for the AspectJ pointcut parser.
*/
private String replaceBooleanOperators(String pcExpr) {
@@ -378,7 +378,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to evaluate join point for arguments " + Arrays.asList(args) +
logger.debug("Failed to evaluate join point for arguments " + Arrays.toString(args) +
" - falling back to non-match", ex);
}
return false;
@@ -527,7 +527,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
return false;
}
AspectJExpressionPointcut otherPc = (AspectJExpressionPointcut) other;
return ObjectUtils.nullSafeEquals(this.getExpression(), otherPc.getExpression()) &&
return ObjectUtils.nullSafeEquals(getExpression(), otherPc.getExpression()) &&
ObjectUtils.nullSafeEquals(this.pointcutDeclarationScope, otherPc.pointcutDeclarationScope) &&
ObjectUtils.nullSafeEquals(this.pointcutParameterNames, otherPc.pointcutParameterNames) &&
ObjectUtils.nullSafeEquals(this.pointcutParameterTypes, otherPc.pointcutParameterTypes);
@@ -535,7 +535,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
@Override
public int hashCode() {
int hashCode = ObjectUtils.nullSafeHashCode(this.getExpression());
int hashCode = ObjectUtils.nullSafeHashCode(getExpression());
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.pointcutDeclarationScope);
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.pointcutParameterNames);
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.pointcutParameterTypes);
@@ -39,7 +39,7 @@ import org.springframework.lang.Nullable;
public interface AspectJAdvisorFactory {
/**
* Determine whether or not the given class is an aspect, as reported
* Determine whether the given class is an aspect, as reported
* by AspectJ's {@link org.aspectj.lang.reflect.AjTypeSystem}.
* <p>Will simply return {@code false} if the supposed aspect is
* invalid (such as an extension of a concrete aspect class).
@@ -47,7 +47,7 @@ public interface AspectJAdvisorFactory {
* such as those with unsupported instantiation models.
* Use the {@link #validate} method to handle these cases if necessary.
* @param clazz the supposed annotation-style AspectJ class
* @return whether or not this class is recognized by AspectJ as an aspect class
* @return whether this class is recognized by AspectJ as an aspect class
*/
boolean isAspect(Class<?> clazz);
@@ -67,7 +67,7 @@ public class AspectMetadata implements Serializable {
/**
* Spring AOP pointcut corresponding to the per clause of the
* aspect. Will be the Pointcut.TRUE canonical instance in the
* aspect. Will be the {@code Pointcut.TRUE} canonical instance in the
* case of a singleton, otherwise an AspectJExpressionPointcut.
*/
private final Pointcut perClausePointcut;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,10 +23,6 @@ import org.springframework.lang.Nullable;
* Subinterface of {@link org.springframework.aop.aspectj.AspectInstanceFactory}
* that returns {@link AspectMetadata} associated with AspectJ-annotated classes.
*
* <p>Ideally, AspectInstanceFactory would include this method itself, but because
* AspectMetadata uses Java-5-only {@link org.aspectj.lang.reflect.AjType},
* we need to split out this subinterface.
*
* @author Rod Johnson
* @since 2.0
* @see AspectMetadata
@@ -35,13 +31,13 @@ import org.springframework.lang.Nullable;
public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactory {
/**
* Return the AspectJ AspectMetadata for this factory's aspect.
* Get the AspectJ AspectMetadata for this factory's aspect.
* @return the aspect metadata
*/
AspectMetadata getAspectMetadata();
/**
* Return the best possible creation mutex for this factory.
* Get the best possible creation mutex for this factory.
* @return the mutex object (may be {@code null} for no mutex to use)
* @since 4.3
*/
@@ -60,8 +60,8 @@ public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProx
* <li>Otherwise the advice declared first gets highest precedence (i.e., runs
* first).</li>
* </ul>
* <p><b>Important:</b> Advisors are sorted in precedence order, from highest
* precedence to lowest. "On the way in" to a join point, the highest precedence
* <p><b>Important:</b> Advisors are sorted in precedence order, from the highest
* precedence to the lowest. "On the way in" to a join point, the highest precedence
* advisor should run first. "On the way out" of a join point, the highest
* precedence advisor should run last.
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -314,7 +314,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
}
/**
* Add all of the given advisors to this proxy configuration.
* Add all the given advisors to this proxy configuration.
* @param advisors the advisors to register
*/
public void addAdvisors(Advisor... advisors) {
@@ -322,7 +322,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
}
/**
* Add all of the given advisors to this proxy configuration.
* Add all the given advisors to this proxy configuration.
* @param advisors the advisors to register
*/
public void addAdvisors(Collection<Advisor> advisors) {
@@ -521,6 +521,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
copy.copyFrom(this);
copy.targetSource = EmptyTargetSource.forClass(getTargetClass(), getTargetSource().isStatic());
copy.advisorChainFactory = this.advisorChainFactory;
copy.methodCache = this.methodCache;
copy.interfaces = new ArrayList<>(this.interfaces);
copy.advisors = new ArrayList<>(this.advisors);
return copy;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -283,8 +283,8 @@ class CglibAopProxy implements AopProxy, Serializable {
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean exposeProxy = this.advised.isExposeProxy();
boolean isStatic = this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls).
@@ -424,10 +424,9 @@ class CglibAopProxy implements AopProxy, Serializable {
/**
* Method interceptor used for static targets with no advice chain. The call
* is passed directly back to the target. Used when the proxy needs to be
* exposed and it can't be determined that the method won't return
* {@code this}.
* Method interceptor used for static targets with no advice chain. The call is
* passed directly back to the target. Used when the proxy needs to be exposed
* and it can't be determined that the method won't return {@code this}.
*/
private static class StaticUnadvisedInterceptor implements MethodInterceptor, Serializable {
@@ -899,9 +898,9 @@ class CglibAopProxy implements AopProxy, Serializable {
// Proxy is not yet available, but that shouldn't matter.
List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
boolean haveAdvice = !chain.isEmpty();
boolean isFrozen = this.advised.isFrozen();
boolean exposeProxy = this.advised.isExposeProxy();
boolean isStatic = this.advised.getTargetSource().isStatic();
boolean isFrozen = this.advised.isFrozen();
if (haveAdvice || !isFrozen) {
// If exposing the proxy, then AOP_PROXY must be used.
if (exposeProxy) {
@@ -970,6 +969,9 @@ class CglibAopProxy implements AopProxy, Serializable {
if (this.advised.isExposeProxy() != otherAdvised.isExposeProxy()) {
return false;
}
if (this.advised.isOpaque() != otherAdvised.isOpaque()) {
return false;
}
if (this.advised.getTargetSource().isStatic() != otherAdvised.getTargetSource().isStatic()) {
return false;
}
@@ -1016,10 +1018,6 @@ class CglibAopProxy implements AopProxy, Serializable {
Advice advice = advisor.getAdvice();
hashCode = 13 * hashCode + advice.getClass().hashCode();
}
hashCode = 13 * hashCode + (this.advised.isFrozen() ? 1 : 0);
hashCode = 13 * hashCode + (this.advised.isExposeProxy() ? 1 : 0);
hashCode = 13 * hashCode + (this.advised.isOptimize() ? 1 : 0);
hashCode = 13 * hashCode + (this.advised.isOpaque() ? 1 : 0);
return hashCode;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -72,8 +72,8 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
* NOTE: We could avoid the code duplication between this class and the CGLIB
* proxies by refactoring "invoke" into a template method. However, this approach
* adds at least 10% performance overhead versus a copy-paste solution, so we sacrifice
* elegance for performance. (We have a good test suite to ensure that the different
* proxies behave the same :-)
* elegance for performance (we have a good test suite to ensure that the different
* proxies behave the same :-)).
* This way, we can also more easily take advantage of minor optimizations in each class.
*/
@@ -123,7 +123,33 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
return Proxy.newProxyInstance(determineClassLoader(classLoader), this.proxiedInterfaces, this);
}
/**
* Determine whether the JDK bootstrap or platform loader has been suggested ->
* use higher-level loader which can see Spring infrastructure classes instead.
*/
private ClassLoader determineClassLoader(@Nullable ClassLoader classLoader) {
if (classLoader == null) {
// JDK bootstrap loader -> use spring-aop ClassLoader instead.
return getClass().getClassLoader();
}
if (classLoader.getParent() == null) {
// Potentially the JDK platform loader on JDK 9+
ClassLoader aopClassLoader = getClass().getClassLoader();
ClassLoader aopParent = aopClassLoader.getParent();
while (aopParent != null) {
if (classLoader == aopParent) {
// Suggested ClassLoader is ancestor of spring-aop ClassLoader
// -> use spring-aop ClassLoader itself instead.
return aopClassLoader;
}
aopParent = aopParent.getParent();
}
}
// Regular case: use suggested ClassLoader as-is.
return classLoader;
}
/**
@@ -198,7 +224,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// Check whether we have any advice. If we don't, we can fall back on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,7 +50,7 @@ import org.springframework.util.ObjectUtils;
/**
* {@link org.springframework.beans.factory.FactoryBean} implementation that builds an
* AOP proxy based on beans in Spring {@link org.springframework.beans.factory.BeanFactory}.
* AOP proxy based on beans in a Spring {@link org.springframework.beans.factory.BeanFactory}.
*
* <p>{@link org.aopalliance.intercept.MethodInterceptor MethodInterceptors} and
* {@link org.springframework.aop.Advisor Advisors} are identified by a list of bean
@@ -61,10 +61,11 @@ import org.springframework.util.ObjectUtils;
*
* <p>Global interceptors and advisors can be added at the factory level. The specified
* ones are expanded in an interceptor list where an "xxx*" entry is included in the
* list, matching the given prefix with the bean names (e.g. "global*" would match
* both "globalBean1" and "globalBean2", "*" all defined interceptors). The matching
* interceptors get applied according to their returned order value, if they implement
* the {@link org.springframework.core.Ordered} interface.
* list, matching the given prefix with the bean names &mdash; for example, "global*"
* would match both "globalBean1" and "globalBean2"; whereas, "*" would match all
* defined interceptors. The matching interceptors get applied according to their
* returned order value, if they implement the {@link org.springframework.core.Ordered}
* interface.
*
* <p>Creates a JDK proxy when proxy interfaces are given, and a CGLIB proxy for the
* actual target class if not. Note that the latter will only work if the target class
@@ -75,7 +76,7 @@ import org.springframework.util.ObjectUtils;
* This won't work for existing prototype references, which are independent. However,
* it will work for prototypes subsequently obtained from the factory. Changes to
* interception will work immediately on singletons (including existing references).
* However, to change interfaces or target it's necessary to obtain a new instance
* However, to change interfaces or a target it's necessary to obtain a new instance
* from the factory. This means that singleton instances obtained from the factory
* do not have the same object identity. However, they do have the same interceptors
* and target, and changing any reference will change all objects.
@@ -406,7 +407,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
if (namedBeanClass != null) {
return (Advisor.class.isAssignableFrom(namedBeanClass) || Advice.class.isAssignableFrom(namedBeanClass));
}
// Treat it as an target bean if we can't tell.
// Treat it as a target bean if we can't tell.
if (logger.isDebugEnabled()) {
logger.debug("Could not determine type of bean with name '" + beanName +
"' - assuming it is neither an Advisor nor an Advice");
@@ -424,7 +425,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
if (!this.advisorChainInitialized && !ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
"- cannot resolve interceptor names " + Arrays.toString(this.interceptorNames));
}
// Globals can't be last unless we specified a targetSource using the property...
@@ -119,7 +119,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
/**
* Indicates whether or not the proxy should be frozen. Overridden from super
* Indicates whether the proxy should be frozen. Overridden from super
* to prevent the configuration from becoming frozen too early.
*/
private boolean freezeProxy = false;
@@ -145,9 +145,9 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
/**
* Set whether or not the proxy should be frozen, preventing advice
* Set whether the proxy should be frozen, preventing advice
* from being added to it once it is created.
* <p>Overridden from the super class to prevent the proxy configuration
* <p>Overridden from the superclass to prevent the proxy configuration
* from being frozen before the proxy is created.
*/
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Convenient superclass for
@@ -81,6 +82,11 @@ public abstract class AbstractBeanFactoryBasedTargetSourceCreator
return this.beanFactory;
}
private ConfigurableBeanFactory getConfigurableBeanFactory() {
Assert.state(this.beanFactory != null, "BeanFactory not set");
return this.beanFactory;
}
//---------------------------------------------------------------------
// Implementation of the TargetSourceCreator interface
@@ -104,7 +110,7 @@ public abstract class AbstractBeanFactoryBasedTargetSourceCreator
// We need to override just this bean definition, as it may reference other beans
// and we're happy to take the parent's definition for those.
// Always use prototype scope if demanded.
BeanDefinition bd = this.beanFactory.getMergedBeanDefinition(beanName);
BeanDefinition bd = getConfigurableBeanFactory().getMergedBeanDefinition(beanName);
GenericBeanDefinition bdCopy = new GenericBeanDefinition(bd);
if (isPrototypeBased()) {
bdCopy.setScope(BeanDefinition.SCOPE_PROTOTYPE);
@@ -126,7 +132,7 @@ public abstract class AbstractBeanFactoryBasedTargetSourceCreator
protected DefaultListableBeanFactory getInternalBeanFactoryForBean(String beanName) {
synchronized (this.internalBeanFactories) {
return this.internalBeanFactories.computeIfAbsent(beanName,
name -> buildInternalBeanFactory(this.beanFactory));
name -> buildInternalBeanFactory(getConfigurableBeanFactory()));
}
}
@@ -0,0 +1,10 @@
/**
* Various {@link org.springframework.aop.framework.autoproxy.TargetSourceCreator}
* implementations for use with Spring's AOP auto-proxying support.
*/
@NonNullApi
@NonNullFields
package org.springframework.aop.framework.autoproxy.target;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
@@ -56,7 +56,7 @@ public abstract class AbstractTraceInterceptor implements MethodInterceptor, Ser
protected transient Log defaultLogger = LogFactory.getLog(getClass());
/**
* Indicates whether or not proxy class names should be hidden when using dynamic loggers.
* Indicates whether proxy class names should be hidden when using dynamic loggers.
* @see #setUseDynamicLogger
*/
private boolean hideProxyClassNames = false;
@@ -119,7 +119,7 @@ public abstract class AbstractTraceInterceptor implements MethodInterceptor, Ser
/**
* Determines whether or not logging is enabled for the particular {@code MethodInvocation}.
* Determines whether logging is enabled for the particular {@code MethodInvocation}.
* If not, the method invocation proceeds as normal, otherwise the method invocation is passed
* to the {@code invokeUnderTrace} method for handling.
* @see #invokeUnderTrace(org.aopalliance.intercept.MethodInvocation, org.apache.commons.logging.Log)
@@ -36,7 +36,7 @@ public interface AsyncUncaughtExceptionHandler {
* Handle the given uncaught exception thrown from an asynchronous method.
* @param ex the exception thrown from the asynchronous method
* @param method the asynchronous method
* @param params the parameters used to invoked the method
* @param params the parameters used to invoke the method
*/
void handleUncaughtException(Throwable ex, Method method, Object... params);
@@ -217,7 +217,7 @@ public abstract class AopUtils {
* out a pointcut for a class.
* @param pc the static or dynamic pointcut to check
* @param targetClass the class to test
* @param hasIntroductions whether or not the advisor chain
* @param hasIntroductions whether the advisor chain
* for this bean includes any introductions
* @return whether the pointcut can apply on any method
*/
@@ -261,7 +261,7 @@ public abstract class AopUtils {
/**
* Can the given advisor apply at all on the given class?
* This is an important test as it can be used to optimize
* out a advisor for a class.
* out an advisor for a class.
* @param advisor the advisor to check
* @param targetClass class we're testing
* @return whether the pointcut can apply on any method
@@ -272,11 +272,11 @@ public abstract class AopUtils {
/**
* Can the given advisor apply at all on the given class?
* <p>This is an important test as it can be used to optimize out a advisor for a class.
* <p>This is an important test as it can be used to optimize out an advisor for a class.
* This version also takes into account introductions (for IntroductionAwareMethodMatchers).
* @param advisor the advisor to check
* @param targetClass class we're testing
* @param hasIntroductions whether or not the advisor chain for this bean includes
* @param hasIntroductions whether the advisor chain for this bean includes
* any introductions
* @return whether the pointcut can apply on any method
*/
@@ -43,7 +43,7 @@ public class DefaultPointcutAdvisor extends AbstractGenericPointcutAdvisor imple
/**
* Create an empty DefaultPointcutAdvisor.
* <p>Advice must be set before use using setter methods.
* <p>Advice must be set before using setter methods.
* Pointcut will normally be set also, but defaults to {@code Pointcut.TRUE}.
*/
public DefaultPointcutAdvisor() {
@@ -90,7 +90,7 @@ public abstract class MethodMatchers {
* @param targetClass the target class
* @param hasIntroductions {@code true} if the object on whose behalf we are
* asking is the subject on one or more introductions; {@code false} otherwise
* @return whether or not this method matches statically
* @return whether this method matches statically
*/
public static boolean matches(MethodMatcher mm, Method method, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(mm, "MethodMatcher must not be null");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,8 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.aop.TargetSource;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
@@ -57,15 +59,18 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
protected final Log logger = LogFactory.getLog(getClass());
/** Name of the target bean we will create on each invocation. */
@Nullable
private String targetBeanName;
/** Class of the target. */
@Nullable
private volatile Class<?> targetClass;
/**
* BeanFactory that owns this TargetSource. We need to hold onto this
* reference so that we can create new prototype instances as necessary.
*/
@Nullable
private BeanFactory beanFactory;
@@ -86,6 +91,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
* Return the name of the target bean in the factory.
*/
public String getTargetBeanName() {
Assert.state(this.targetBeanName != null, "Target bean name not set");
return this.targetBeanName;
}
@@ -115,11 +121,13 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
* Return the owning BeanFactory.
*/
public BeanFactory getBeanFactory() {
Assert.state(this.beanFactory != null, "BeanFactory not set");
return this.beanFactory;
}
@Override
@Nullable
public Class<?> getTargetClass() {
Class<?> targetClass = this.targetClass;
if (targetClass != null) {
@@ -128,7 +136,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
synchronized (this) {
// Full check within synchronization, entering the BeanFactory interaction algorithm only once...
targetClass = this.targetClass;
if (targetClass == null && this.beanFactory != null) {
if (targetClass == null && this.beanFactory != null && this.targetBeanName != null) {
// Determine type of the target bean.
targetClass = this.beanFactory.getType(this.targetBeanName);
if (targetClass == null) {
@@ -182,18 +190,16 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
@Override
public int hashCode() {
int hashCode = getClass().hashCode();
hashCode = 13 * hashCode + ObjectUtils.nullSafeHashCode(this.beanFactory);
hashCode = 13 * hashCode + ObjectUtils.nullSafeHashCode(this.targetBeanName);
return hashCode;
return getClass().hashCode() * 13 + ObjectUtils.nullSafeHashCode(this.targetBeanName);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(getClass().getSimpleName());
sb.append(" for target bean '").append(this.targetBeanName).append('\'');
if (this.targetClass != null) {
sb.append(" of type [").append(this.targetClass.getName()).append(']');
Class<?> targetClass = this.targetClass;
if (targetClass != null) {
sb.append(" of type [").append(targetClass.getName()).append(']');
}
return sb.toString();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,6 +46,7 @@ public abstract class AbstractLazyCreationTargetSource implements TargetSource {
protected final Log logger = LogFactory.getLog(getClass());
/** The lazily initialized target object. */
@Nullable
private Object lazyTarget;
@@ -37,7 +37,7 @@ import org.springframework.lang.Nullable;
* {@link AbstractPrototypeBasedTargetSource} can be used to create objects
* in order to put them into the pool.
*
* <p>Subclasses must also implement some of the monitoring methods from the
* <p>Subclasses must also implement some monitoring methods from the
* {@link PoolingConfig} interface. The {@link #getPoolingConfigMixin()} method
* makes these stats available on proxied objects through an IntroductionAdvisor.
*
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -70,6 +70,7 @@ public final class EmptyTargetSource implements TargetSource, Serializable {
// Instance implementation
//---------------------------------------------------------------------
@Nullable
private final Class<?> targetClass;
private final boolean isStatic;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -95,8 +95,7 @@ public class HotSwappableTargetSource implements TargetSource, Serializable {
/**
* Two HotSwappableTargetSources are equal if the current target
* objects are equal.
* Two HotSwappableTargetSources are equal if the current target objects are equal.
*/
@Override
public boolean equals(Object other) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -82,14 +82,8 @@ public class SingletonTargetSource implements TargetSource, Serializable {
*/
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof SingletonTargetSource)) {
return false;
}
SingletonTargetSource otherTargetSource = (SingletonTargetSource) other;
return this.target.equals(otherTargetSource.target);
return (this == other || (other instanceof SingletonTargetSource &&
this.target.equals(((SingletonTargetSource) other).target)));
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -58,7 +58,12 @@ public class ThreadLocalTargetSource extends AbstractPrototypeBasedTargetSource
* is meant to be per thread per instance of the ThreadLocalTargetSource class.
*/
private final ThreadLocal<Object> targetInThread =
new NamedThreadLocal<>("Thread-local instance of bean '" + getTargetBeanName() + "'");
new NamedThreadLocal<Object>("Thread-local instance of bean") {
@Override
public String toString() {
return super.toString() + " '" + getTargetBeanName() + "'";
}
};
/**
* Set of managed targets, enabling us to keep track of the targets we've created.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -142,11 +142,11 @@ public class TrickyAspectJPointcutExpressionTests {
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public static @interface Log {
@interface Log {
}
public static interface TestService {
public interface TestService {
public String sayHello();
}
@@ -931,7 +931,7 @@ abstract class AbstractMakeModifiable {
return setter.getDeclaringClass().getMethod(getterName);
}
catch (NoSuchMethodException ex) {
// must be write only
// must be write-only
return null;
}
}
@@ -48,7 +48,7 @@ public class IntroductionBenchmarkTests {
}
}
public static interface Counter {
public interface Counter {
int getCount();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,10 @@
package org.springframework.aop.framework;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.accessibility.Accessible;
@@ -44,7 +47,7 @@ import org.springframework.core.annotation.Order;
import org.springframework.core.testfixture.TimeStamped;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatRuntimeException;
/**
* Also tests AdvisedSupport and ProxyCreatorSupport superclasses.
@@ -277,7 +280,7 @@ public class ProxyFactoryTests {
assertThat(config.getAdvisors().length == oldCount).isTrue();
assertThatExceptionOfType(RuntimeException.class)
assertThatRuntimeException()
.as("Existing object won't implement this interface any more")
.isThrownBy(ts::getTimeStamp); // Existing reference will fail
@@ -380,6 +383,43 @@ public class ProxyFactoryTests {
assertThat(proxy.getName()).isEqualTo("tb");
}
@Test
public void testCharSequenceProxy() {
CharSequence target = "test";
ProxyFactory pf = new ProxyFactory(target);
ClassLoader cl = target.getClass().getClassLoader();
CharSequence proxy = (CharSequence) pf.getProxy(cl);
assertThat(proxy.toString()).isEqualTo(target);
}
@Test
public void testDateProxy() {
Date target = new Date();
ProxyFactory pf = new ProxyFactory(target);
pf.setProxyTargetClass(true);
ClassLoader cl = target.getClass().getClassLoader();
Date proxy = (Date) pf.getProxy(cl);
assertThat(proxy.getTime()).isEqualTo(target.getTime());
}
@Test
public void testJdbcSavepointProxy() throws SQLException {
Savepoint target = new Savepoint() {
@Override
public int getSavepointId() throws SQLException {
return 1;
}
@Override
public String getSavepointName() throws SQLException {
return "sp";
}
};
ProxyFactory pf = new ProxyFactory(target);
ClassLoader cl = Savepoint.class.getClassLoader();
Savepoint proxy = (Savepoint) pf.getProxy(cl);
assertThat(proxy.getSavepointName()).isEqualTo("sp");
}
@Order(2)
public static class A implements Runnable {
@@ -391,7 +431,7 @@ public class ProxyFactoryTests {
@Order(1)
public static class B implements Runnable{
public static class B implements Runnable {
@Override
public void run() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.aop.testfixture.advice.MyThrowsHandler;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatException;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.BDDMockito.given;
@@ -63,9 +64,7 @@ public class ThrowsAdviceInterceptorTests {
Exception ex = new Exception();
MethodInvocation mi = mock(MethodInvocation.class);
given(mi.proceed()).willThrow(ex);
assertThatExceptionOfType(Exception.class).isThrownBy(() ->
ti.invoke(mi))
.isSameAs(ex);
assertThatException().isThrownBy(() -> ti.invoke(mi)).isSameAs(ex);
assertThat(th.getCalls()).isEqualTo(0);
}
@@ -78,9 +77,7 @@ public class ThrowsAdviceInterceptorTests {
given(mi.getMethod()).willReturn(Object.class.getMethod("hashCode"));
given(mi.getThis()).willReturn(new Object());
given(mi.proceed()).willThrow(ex);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() ->
ti.invoke(mi))
.isSameAs(ex);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() -> ti.invoke(mi)).isSameAs(ex);
assertThat(th.getCalls()).isEqualTo(1);
assertThat(th.getCalls("ioException")).isEqualTo(1);
}
@@ -93,9 +90,7 @@ public class ThrowsAdviceInterceptorTests {
ConnectException ex = new ConnectException("");
MethodInvocation mi = mock(MethodInvocation.class);
given(mi.proceed()).willThrow(ex);
assertThatExceptionOfType(ConnectException.class).isThrownBy(() ->
ti.invoke(mi))
.isSameAs(ex);
assertThatExceptionOfType(ConnectException.class).isThrownBy(() -> ti.invoke(mi)).isSameAs(ex);
assertThat(th.getCalls()).isEqualTo(1);
assertThat(th.getCalls("remoteException")).isEqualTo(1);
}
@@ -118,9 +113,7 @@ public class ThrowsAdviceInterceptorTests {
ConnectException ex = new ConnectException("");
MethodInvocation mi = mock(MethodInvocation.class);
given(mi.proceed()).willThrow(ex);
assertThatExceptionOfType(Throwable.class).isThrownBy(() ->
ti.invoke(mi))
.isSameAs(t);
assertThatExceptionOfType(Throwable.class).isThrownBy(() -> ti.invoke(mi)).isSameAs(t);
assertThat(th.getCalls()).isEqualTo(1);
assertThat(th.getCalls("remoteException")).isEqualTo(1);
}
@@ -307,7 +307,7 @@ public class DelegatingIntroductionInterceptorTests {
}
private static interface SubTimeStamped extends TimeStamped {
private interface SubTimeStamped extends TimeStamped {
}
}
@@ -35,7 +35,7 @@ public abstract aspect AbstractDependencyInjectionAspect {
mostSpecificSubTypeConstruction() && !preConstructionConfiguration();
/**
* Select least specific super type that is marked for DI
* Select least specific supertype that is marked for DI
* (so that injection occurs only once with pre-construction injection).
*/
public abstract pointcut leastSpecificSuperTypeConstruction();
@@ -26,7 +26,7 @@ import org.springframework.context.annotation.Import;
/**
* Signals the current application context to apply dependency injection to
* non-managed classes that are instantiated outside of the Spring bean factory
* non-managed classes that are instantiated outside the Spring bean factory
* (typically classes annotated with the
* {@link org.springframework.beans.factory.annotation.Configurable @Configurable}
* annotation).
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,9 @@ import org.junit.jupiter.api.Test;
import org.springframework.transaction.testfixture.CallCountingTransactionManager;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatException;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatRuntimeException;
/**
* @author Rod Johnson
@@ -104,44 +106,44 @@ public class TransactionAspectTests {
@Test
public void defaultCommitOnAnnotatedClass() throws Throwable {
Exception ex = new Exception();
assertThatExceptionOfType(Exception.class).isThrownBy(() ->
testRollback(() -> annotationOnlyOnClassWithNoInterface.echo(ex), false))
assertThatException()
.isThrownBy(() -> testRollback(() -> annotationOnlyOnClassWithNoInterface.echo(ex), false))
.isSameAs(ex);
}
@Test
public void defaultRollbackOnAnnotatedClass() throws Throwable {
RuntimeException ex = new RuntimeException();
assertThatExceptionOfType(RuntimeException.class).isThrownBy(() ->
testRollback(() -> annotationOnlyOnClassWithNoInterface.echo(ex), true))
assertThatRuntimeException()
.isThrownBy(() -> testRollback(() -> annotationOnlyOnClassWithNoInterface.echo(ex), true))
.isSameAs(ex);
}
@Test
public void defaultCommitOnSubclassOfAnnotatedClass() throws Throwable {
Exception ex = new Exception();
assertThatExceptionOfType(Exception.class).isThrownBy(() ->
testRollback(() -> new SubclassOfClassWithTransactionalAnnotation().echo(ex), false))
assertThatException()
.isThrownBy(() -> testRollback(() -> new SubclassOfClassWithTransactionalAnnotation().echo(ex), false))
.isSameAs(ex);
}
@Test
public void defaultCommitOnSubclassOfClassWithTransactionalMethodAnnotated() throws Throwable {
Exception ex = new Exception();
assertThatExceptionOfType(Exception.class).isThrownBy(() ->
testRollback(() -> new SubclassOfClassWithTransactionalMethodAnnotation().echo(ex), false))
assertThatException()
.isThrownBy(() -> testRollback(() -> new SubclassOfClassWithTransactionalMethodAnnotation().echo(ex), false))
.isSameAs(ex);
}
@Test
public void noCommitOnImplementationOfAnnotatedInterface() throws Throwable {
final Exception ex = new Exception();
Exception ex = new Exception();
testNotTransactional(() -> new ImplementsAnnotatedInterface().echo(ex), ex);
}
@Test
public void noRollbackOnImplementationOfAnnotatedInterface() throws Throwable {
final Exception rollbackProvokingException = new RuntimeException();
Exception rollbackProvokingException = new RuntimeException();
testNotTransactional(() -> new ImplementsAnnotatedInterface().echo(rollbackProvokingException),
rollbackProvokingException);
}
@@ -165,8 +167,9 @@ public class TransactionAspectTests {
protected void testNotTransactional(TransactionOperationCallback toc, Throwable expected) throws Throwable {
txManager.clear();
assertThat(txManager.begun).isEqualTo(0);
assertThatExceptionOfType(Throwable.class).isThrownBy(
toc::performTransactionalOperation).isSameAs(expected);
assertThatExceptionOfType(Throwable.class)
.isThrownBy(toc::performTransactionalOperation)
.isSameAs(expected);
assertThat(txManager.begun).isEqualTo(0);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1004,18 +1004,20 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
*/
protected abstract static class PropertyHandler {
@Nullable
private final Class<?> propertyType;
private final boolean readable;
private final boolean writable;
public PropertyHandler(Class<?> propertyType, boolean readable, boolean writable) {
public PropertyHandler(@Nullable Class<?> propertyType, boolean readable, boolean writable) {
this.propertyType = propertyType;
this.readable = readable;
this.writable = writable;
}
@Nullable
public Class<?> getPropertyType() {
return this.propertyType;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.URL;
import java.time.temporal.Temporal;
@@ -30,6 +31,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -62,7 +64,7 @@ import org.springframework.util.StringUtils;
* <p>Mainly for internal use within the framework, but to some degree also
* useful for application classes. Consider
* <a href="https://commons.apache.org/proper/commons-beanutils/">Apache Commons BeanUtils</a>,
* <a href="https://hotelsdotcom.github.io/bull/">BULL - Bean Utils Light Library</a>,
* <a href="https://github.com/ExpediaGroup/bull">BULL - Bean Utils Light Library</a>,
* or similar third-party frameworks for more comprehensive bean utilities.
*
* @author Rod Johnson
@@ -247,7 +249,8 @@ public abstract class BeanUtils {
// A single public constructor
return (Constructor<T>) ctors[0];
}
else if (ctors.length == 0){
else if (ctors.length == 0) {
// No public constructors -> check non-public
ctors = clazz.getDeclaredConstructors();
if (ctors.length == 1) {
// A single non-public constructor, e.g. from a non-public record type
@@ -786,38 +789,28 @@ public abstract class BeanUtils {
if (editable != null) {
if (!editable.isInstance(target)) {
throw new IllegalArgumentException("Target class [" + target.getClass().getName() +
"] not assignable to Editable class [" + editable.getName() + "]");
"] not assignable to editable class [" + editable.getName() + "]");
}
actualEditable = editable;
}
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
Set<String> ignoredProps = (ignoreProperties != null ? new HashSet<>(Arrays.asList(ignoreProperties)) : null);
CachedIntrospectionResults sourceResults = (actualEditable != source.getClass() ?
CachedIntrospectionResults.forClass(source.getClass()) : null);
for (PropertyDescriptor targetPd : targetPds) {
Method writeMethod = targetPd.getWriteMethod();
if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
if (writeMethod != null && (ignoredProps == null || !ignoredProps.contains(targetPd.getName()))) {
PropertyDescriptor sourcePd = (sourceResults != null ?
sourceResults.getPropertyDescriptor(targetPd.getName()) : targetPd);
if (sourcePd != null) {
Method readMethod = sourcePd.getReadMethod();
if (readMethod != null) {
ResolvableType sourceResolvableType = ResolvableType.forMethodReturnType(readMethod);
ResolvableType targetResolvableType = ResolvableType.forMethodParameter(writeMethod, 0);
// Ignore generic types in assignable check if either ResolvableType has unresolvable generics.
boolean isAssignable =
(sourceResolvableType.hasUnresolvableGenerics() || targetResolvableType.hasUnresolvableGenerics() ?
ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType()) :
targetResolvableType.isAssignableFrom(sourceResolvableType));
if (isAssignable) {
if (isAssignable(writeMethod, readMethod)) {
try {
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
}
ReflectionUtils.makeAccessible(readMethod);
Object value = readMethod.invoke(source);
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
writeMethod.setAccessible(true);
}
ReflectionUtils.makeAccessible(writeMethod);
writeMethod.invoke(target, value);
}
catch (Throwable ex) {
@@ -831,6 +824,24 @@ public abstract class BeanUtils {
}
}
private static boolean isAssignable(Method writeMethod, Method readMethod) {
Type paramType = writeMethod.getGenericParameterTypes()[0];
if (paramType instanceof Class) {
return ClassUtils.isAssignable((Class<?>) paramType, readMethod.getReturnType());
}
else if (paramType.equals(readMethod.getGenericReturnType())) {
return true;
}
else {
ResolvableType sourceType = ResolvableType.forMethodReturnType(readMethod);
ResolvableType targetType = ResolvableType.forMethodParameter(writeMethod, 0);
// Ignore generic types in assignable check if either ResolvableType has unresolvable generics.
return (sourceType.hasUnresolvableGenerics() || targetType.hasUnresolvableGenerics() ?
ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType()) :
targetType.isAssignableFrom(sourceType));
}
}
/**
* Inner class to avoid a hard dependency on Kotlin at runtime.
@@ -891,7 +902,6 @@ public abstract class BeanUtils {
}
return kotlinConstructor.callBy(argParameters);
}
}
}
@@ -82,7 +82,7 @@ public interface BeanWrapper extends ConfigurablePropertyAccessor {
* Obtain the property descriptor for a specific property
* of the wrapped object.
* @param propertyName the property to obtain the descriptor for
* (may be a nested path, but no indexed/mapped property)
* (may be a nested path, but not an indexed/mapped property)
* @return the property descriptor for the specified property
* @throws InvalidPropertyException if there is no such property
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.Collections;
import java.util.HashSet;
@@ -96,8 +97,6 @@ public final class CachedIntrospectionResults {
*/
public static final String IGNORE_BEANINFO_PROPERTY_NAME = "spring.beaninfo.ignore";
private static final PropertyDescriptor[] EMPTY_PROPERTY_DESCRIPTOR_ARRAY = {};
private static final boolean shouldIntrospectorIgnoreBeaninfoClasses =
SpringProperties.getFlag(IGNORE_BEANINFO_PROPERTY_NAME);
@@ -249,9 +248,22 @@ public final class CachedIntrospectionResults {
return beanInfo;
}
}
return (shouldIntrospectorIgnoreBeaninfoClasses ?
BeanInfo beanInfo = (shouldIntrospectorIgnoreBeaninfoClasses ?
Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) :
Introspector.getBeanInfo(beanClass));
// Immediately remove class from Introspector cache to allow for proper garbage
// collection on class loader shutdown; we cache it in CachedIntrospectionResults
// in a GC-friendly manner. This is necessary (again) for the JDK ClassInfo cache.
Class<?> classToFlush = beanClass;
do {
Introspector.flushFromCaches(classToFlush);
classToFlush = classToFlush.getSuperclass();
}
while (classToFlush != null && classToFlush != Object.class);
return beanInfo;
}
@@ -292,10 +304,12 @@ public final class CachedIntrospectionResults {
// Only allow all name variants of Class properties
continue;
}
if (pd.getWriteMethod() == null && pd.getPropertyType() != null &&
(ClassLoader.class.isAssignableFrom(pd.getPropertyType()) ||
ProtectionDomain.class.isAssignableFrom(pd.getPropertyType()))) {
// Ignore ClassLoader and ProtectionDomain read-only properties - no need to bind to those
if (URL.class == beanClass && "content".equals(pd.getName())) {
// Only allow URL attribute introspection, not content resolution
continue;
}
if (pd.getWriteMethod() == null && isInvalidReadOnlyPropertyType(pd.getPropertyType(), beanClass)) {
// Ignore read-only properties such as ClassLoader - no need to bind to those
continue;
}
if (logger.isTraceEnabled()) {
@@ -344,10 +358,9 @@ public final class CachedIntrospectionResults {
// GenericTypeAwarePropertyDescriptor leniently resolves a set* write method
// against a declared read method, so we prefer read method descriptors here.
pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
if (pd.getWriteMethod() == null && pd.getPropertyType() != null &&
(ClassLoader.class.isAssignableFrom(pd.getPropertyType()) ||
ProtectionDomain.class.isAssignableFrom(pd.getPropertyType()))) {
// Ignore ClassLoader and ProtectionDomain read-only properties - no need to bind to those
if (pd.getWriteMethod() == null &&
isInvalidReadOnlyPropertyType(pd.getPropertyType(), beanClass)) {
// Ignore read-only properties such as ClassLoader - no need to bind to those
continue;
}
this.propertyDescriptors.put(pd.getName(), pd);
@@ -379,8 +392,7 @@ public final class CachedIntrospectionResults {
if (Modifier.isStatic(method.getModifiers()) ||
method.getDeclaringClass() == Object.class || method.getDeclaringClass() == Class.class ||
method.getParameterCount() > 0 || method.getReturnType() == void.class ||
ClassLoader.class.isAssignableFrom(method.getReturnType()) ||
ProtectionDomain.class.isAssignableFrom(method.getReturnType())) {
isInvalidReadOnlyPropertyType(method.getReturnType(), method.getDeclaringClass())) {
return false;
}
try {
@@ -393,6 +405,13 @@ public final class CachedIntrospectionResults {
}
}
private boolean isInvalidReadOnlyPropertyType(@Nullable Class<?> returnType, Class<?> beanClass) {
return (returnType != null && (ClassLoader.class.isAssignableFrom(returnType) ||
ProtectionDomain.class.isAssignableFrom(returnType) ||
(AutoCloseable.class.isAssignableFrom(returnType) &&
!AutoCloseable.class.isAssignableFrom(beanClass))));
}
BeanInfo getBeanInfo() {
return this.beanInfo;
@@ -416,7 +435,7 @@ public final class CachedIntrospectionResults {
}
PropertyDescriptor[] getPropertyDescriptors() {
return this.propertyDescriptors.values().toArray(EMPTY_PROPERTY_DESCRIPTOR_ARRAY);
return this.propertyDescriptors.values().toArray(PropertyDescriptorUtils.EMPTY_PROPERTY_DESCRIPTOR_ARRAY);
}
private PropertyDescriptor buildGenericTypeAwarePropertyDescriptor(Class<?> beanClass, PropertyDescriptor pd) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -129,7 +129,6 @@ public class DirectFieldAccessor extends AbstractNestablePropertyAccessor {
ReflectionUtils.makeAccessible(this.field);
return this.field.get(getWrappedInstance());
}
catch (IllegalAccessException ex) {
throw new InvalidPropertyException(getWrappedClass(),
this.field.getName(), "Field is not accessible", ex);
@@ -327,7 +327,7 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
/**
* Register the specified property as "processed" in the sense
* of some processor calling the corresponding setter method
* outside of the PropertyValue(s) mechanism.
* outside the PropertyValue(s) mechanism.
* <p>This will lead to {@code true} being returned from
* a {@link #contains} call for the specified property.
* @param propertyName the name of the property.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,9 +17,15 @@
package org.springframework.beans;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
@@ -32,6 +38,80 @@ import org.springframework.util.ObjectUtils;
*/
abstract class PropertyDescriptorUtils {
public static final PropertyDescriptor[] EMPTY_PROPERTY_DESCRIPTOR_ARRAY = {};
/**
* Simple introspection algorithm for basic set/get/is accessor methods,
* building corresponding JavaBeans property descriptors for them.
* <p>This just supports the basic JavaBeans conventions, without indexed
* properties or any customizers, and without other BeanInfo metadata.
* For standard JavaBeans introspection, use the JavaBeans Introspector.
* @param beanClass the target class to introspect
* @return a collection of property descriptors
* @throws IntrospectionException from introspecting the given bean class
* @since 5.3.24
* @see SimpleBeanInfoFactory
* @see java.beans.Introspector#getBeanInfo(Class)
*/
public static Collection<? extends PropertyDescriptor> determineBasicProperties(Class<?> beanClass)
throws IntrospectionException {
Map<String, BasicPropertyDescriptor> pdMap = new TreeMap<>();
for (Method method : beanClass.getMethods()) {
String methodName = method.getName();
boolean setter;
int nameIndex;
if (methodName.startsWith("set") && method.getParameterCount() == 1) {
setter = true;
nameIndex = 3;
}
else if (methodName.startsWith("get") && method.getParameterCount() == 0 && method.getReturnType() != Void.TYPE) {
setter = false;
nameIndex = 3;
}
else if (methodName.startsWith("is") && method.getParameterCount() == 0 && method.getReturnType() == boolean.class) {
setter = false;
nameIndex = 2;
}
else {
continue;
}
String propertyName = Introspector.decapitalize(methodName.substring(nameIndex));
if (propertyName.isEmpty()) {
continue;
}
BasicPropertyDescriptor pd = pdMap.get(propertyName);
if (pd != null) {
if (setter) {
if (pd.getWriteMethod() == null ||
pd.getWriteMethod().getParameterTypes()[0].isAssignableFrom(method.getParameterTypes()[0])) {
pd.setWriteMethod(method);
}
else {
pd.addWriteMethod(method);
}
}
else {
if (pd.getReadMethod() == null ||
(pd.getReadMethod().getReturnType() == method.getReturnType() && method.getName().startsWith("is"))) {
pd.setReadMethod(method);
}
}
}
else {
pd = new BasicPropertyDescriptor(propertyName, (!setter ? method : null), (setter ? method : null));
pdMap.put(propertyName, pd);
}
}
return pdMap.values();
}
/**
* See {@link java.beans.FeatureDescriptor}.
*/
@@ -173,4 +253,72 @@ abstract class PropertyDescriptorUtils {
pd.isBound() == otherPd.isBound() && pd.isConstrained() == otherPd.isConstrained());
}
/**
* PropertyDescriptor for {@link #determineBasicProperties(Class)},
* not performing any early type determination for
* {@link #setReadMethod}/{@link #setWriteMethod}.
* @since 5.3.24
*/
private static class BasicPropertyDescriptor extends PropertyDescriptor {
@Nullable
private Method readMethod;
@Nullable
private Method writeMethod;
private final List<Method> alternativeWriteMethods = new ArrayList<>();
public BasicPropertyDescriptor(String propertyName, @Nullable Method readMethod, @Nullable Method writeMethod)
throws IntrospectionException {
super(propertyName, readMethod, writeMethod);
}
@Override
public void setReadMethod(@Nullable Method readMethod) {
this.readMethod = readMethod;
}
@Override
@Nullable
public Method getReadMethod() {
return this.readMethod;
}
@Override
public void setWriteMethod(@Nullable Method writeMethod) {
this.writeMethod = writeMethod;
}
public void addWriteMethod(Method writeMethod) {
if (this.writeMethod != null) {
this.alternativeWriteMethods.add(this.writeMethod);
this.writeMethod = null;
}
this.alternativeWriteMethods.add(writeMethod);
}
@Override
@Nullable
public Method getWriteMethod() {
if (this.writeMethod == null && !this.alternativeWriteMethods.isEmpty()) {
if (this.readMethod == null) {
return this.alternativeWriteMethods.get(0);
}
else {
for (Method method : this.alternativeWriteMethods) {
if (this.readMethod.getReturnType().isAssignableFrom(method.getParameterTypes()[0])) {
this.writeMethod = method;
break;
}
}
}
}
return this.writeMethod;
}
}
}
@@ -22,7 +22,7 @@ package org.springframework.beans;
* {@link org.springframework.beans.PropertyEditorRegistry property editor registry}.
*
* <p>This is particularly useful when you need to use the same set of
* property editors in several different situations: write a corresponding
* property editors in several situations: write a corresponding
* registrar and reuse that in each case.
*
* @author Juergen Hoeller
@@ -0,0 +1,71 @@
/*
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans;
import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.beans.SimpleBeanInfo;
import java.util.Collection;
import org.springframework.core.Ordered;
import org.springframework.lang.NonNull;
/**
* {@link BeanInfoFactory} implementation that bypasses the standard {@link java.beans.Introspector}
* for faster introspection, reduced to basic property determination (as commonly needed in Spring).
*
* <p>To be configured via a {@code META-INF/spring.factories} file with the following content,
* overriding other custom {@code org.springframework.beans.BeanInfoFactory} declarations:
* {@code org.springframework.beans.BeanInfoFactory=org.springframework.beans.SimpleBeanInfoFactory}
*
* <p>Ordered at {@code Ordered.LOWEST_PRECEDENCE - 1} to override {@link ExtendedBeanInfoFactory}
* (registered by default in 5.3) if necessary while still allowing other user-defined
* {@link BeanInfoFactory} types to take precedence.
*
* @author Juergen Hoeller
* @since 5.3.24
* @see ExtendedBeanInfoFactory
* @see CachedIntrospectionResults
*/
public class SimpleBeanInfoFactory implements BeanInfoFactory, Ordered {
@Override
@NonNull
public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
Collection<? extends PropertyDescriptor> pds =
PropertyDescriptorUtils.determineBasicProperties(beanClass);
return new SimpleBeanInfo() {
@Override
public BeanDescriptor getBeanDescriptor() {
return new BeanDescriptor(beanClass);
}
@Override
public PropertyDescriptor[] getPropertyDescriptors() {
return pds.toArray(PropertyDescriptorUtils.EMPTY_PROPERTY_DESCRIPTOR_ARRAY);
}
};
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE - 1;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -136,7 +136,10 @@ public interface BeanFactory {
* <p>Translates aliases back to the corresponding canonical bean name.
* <p>Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to retrieve
* @return an instance of the bean
* @return an instance of the bean.
* Note that the return value will never be {@code null} but possibly a stub for
* {@code null} returned from a factory method, to be checked via {@code equals(null)}.
* Consider using {@link #getBeanProvider(Class)} for resolving optional dependencies.
* @throws NoSuchBeanDefinitionException if there is no bean with the specified name
* @throws BeansException if the bean could not be obtained
*/
@@ -152,7 +155,11 @@ public interface BeanFactory {
* <p>Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to retrieve
* @param requiredType type the bean must match; can be an interface or superclass
* @return an instance of the bean
* @return an instance of the bean.
* Note that the return value will never be {@code null}. In case of a stub for
* {@code null} from a factory method having been resolved for the requested bean, a
* {@code BeanNotOfRequiredTypeException} against the NullBean stub will be raised.
* Consider using {@link #getBeanProvider(Class)} for resolving optional dependencies.
* @throws NoSuchBeanDefinitionException if there is no such bean definition
* @throws BeanNotOfRequiredTypeException if the bean is not of the required type
* @throws BeansException if the bean could not be created
@@ -45,7 +45,7 @@ import org.springframework.lang.Nullable;
*
* <p><b>The container is only responsible for managing the lifecycle of the FactoryBean
* instance, not the lifecycle of the objects created by the FactoryBean.</b> Therefore,
* a destroy method on an exposed bean object (such as {@link java.io.Closeable#close()}
* a destroy method on an exposed bean object (such as {@link java.io.Closeable#close()})
* will <i>not</i> be called automatically. Instead, a FactoryBean should implement
* {@link DisposableBean} and delegate any such close call to the underlying object.
*
@@ -108,7 +108,7 @@ public interface FactoryBean<T> {
* been fully initialized. It must not rely on state created during
* initialization; of course, it can still use such state if available.
* <p><b>NOTE:</b> Autowiring will simply ignore FactoryBeans that return
* {@code null} here. Therefore it is highly recommended to implement
* {@code null} here. Therefore, it is highly recommended to implement
* this method properly, using the current state of the FactoryBean.
* @return the type of object that this FactoryBean creates,
* or {@code null} if not known at the time of the call
@@ -343,7 +343,7 @@ public interface ListableBeanFactory extends BeanFactory {
/**
* Find an {@link Annotation} of {@code annotationType} on the specified bean,
* traversing its interfaces and super classes if no annotation can be found on
* traversing its interfaces and superclasses if no annotation can be found on
* the given class itself, as well as checking the bean's factory method (if any).
* @param beanName the name of the bean to look for annotations on
* @param annotationType the type of annotation to look for
@@ -361,7 +361,7 @@ public interface ListableBeanFactory extends BeanFactory {
/**
* Find an {@link Annotation} of {@code annotationType} on the specified bean,
* traversing its interfaces and super classes if no annotation can be found on
* traversing its interfaces and superclasses if no annotation can be found on
* the given class itself, as well as checking the bean's factory method (if any).
* @param beanName the name of the bean to look for annotations on
* @param annotationType the type of annotation to look for
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
package org.springframework.beans.factory.annotation;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
@@ -62,6 +63,10 @@ import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -144,6 +149,9 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
@Nullable
private ConfigurableListableBeanFactory beanFactory;
@Nullable
private MetadataReaderFactory metadataReaderFactory;
private final Set<String> lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache = new ConcurrentHashMap<>(256);
@@ -238,6 +246,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
"AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory: " + beanFactory);
}
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
this.metadataReaderFactory = new SimpleMetadataReaderFactory(this.beanFactory.getBeanClassLoader());
}
@@ -438,7 +447,6 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
}
}
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
@@ -464,12 +472,11 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
final List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
final List<InjectionMetadata.InjectedElement> fieldElements = new ArrayList<>();
ReflectionUtils.doWithLocalFields(targetClass, field -> {
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
@@ -480,10 +487,11 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
fieldElements.add(new AutowiredFieldElement(field, required));
}
});
final List<InjectionMetadata.InjectedElement> methodElements = new ArrayList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
@@ -505,11 +513,12 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
methodElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
elements.addAll(0, sortMethodElements(methodElements, targetClass));
elements.addAll(0, fieldElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
@@ -563,7 +572,9 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
* @param type the type of the bean
* @return the target beans, or an empty Collection if no bean of this type is found
* @throws BeansException if bean retrieval failed
* @deprecated since 5.3.24 since it is unused in the meantime
*/
@Deprecated
protected <T> Map<String, T> findAutowireCandidates(Class<T> type) throws BeansException {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory configured - " +
@@ -572,6 +583,47 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
return BeanFactoryUtils.beansOfTypeIncludingAncestors(this.beanFactory, type);
}
/**
* Sort the method elements via ASM for deterministic declaration order if possible.
*/
private List<InjectionMetadata.InjectedElement> sortMethodElements(
List<InjectionMetadata.InjectedElement> methodElements, Class<?> targetClass) {
if (this.metadataReaderFactory != null && methodElements.size() > 1) {
// Try reading the class file via ASM for deterministic declaration order...
// Unfortunately, the JVM's standard reflection returns methods in arbitrary
// order, even between different runs of the same application on the same JVM.
try {
AnnotationMetadata asm =
this.metadataReaderFactory.getMetadataReader(targetClass.getName()).getAnnotationMetadata();
Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Autowired.class.getName());
if (asmMethods.size() >= methodElements.size()) {
List<InjectionMetadata.InjectedElement> candidateMethods = new ArrayList<>(methodElements);
List<InjectionMetadata.InjectedElement> selectedMethods = new ArrayList<>(asmMethods.size());
for (MethodMetadata asmMethod : asmMethods) {
for (Iterator<InjectionMetadata.InjectedElement> it = candidateMethods.iterator(); it.hasNext();) {
InjectionMetadata.InjectedElement element = it.next();
if (element.getMember().getName().equals(asmMethod.getMethodName())) {
selectedMethods.add(element);
it.remove();
break;
}
}
}
if (selectedMethods.size() == methodElements.size()) {
// All reflection-detected methods found in ASM method set -> proceed
return selectedMethods;
}
}
}
catch (IOException ex) {
logger.debug("Failed to read class file via ASM for determining @Autowired method order", ex);
// No worries, let's continue with the reflection metadata we started with...
}
}
return methodElements;
}
/**
* Register the specified bean as dependent on the autowired beans.
*/
@@ -593,7 +645,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
* Resolve the specified cached method argument or field value.
*/
@Nullable
private Object resolvedCachedArgument(@Nullable String beanName, @Nullable Object cachedArgument) {
private Object resolveCachedArgument(@Nullable String beanName, @Nullable Object cachedArgument) {
if (cachedArgument instanceof DependencyDescriptor) {
DependencyDescriptor descriptor = (DependencyDescriptor) cachedArgument;
Assert.state(this.beanFactory != null, "No BeanFactory available");
@@ -628,10 +680,12 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
Object value;
if (this.cached) {
try {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
value = resolveCachedArgument(beanName, this.cachedFieldValue);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
catch (BeansException ex) {
// Unexpected target bean mismatch for cached argument -> re-resolve
this.cached = false;
logger.debug("Failed to resolve cached argument", ex);
value = resolveFieldValue(field, bean, beanName);
}
}
@@ -648,7 +702,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Set<String> autowiredBeanNames = new LinkedHashSet<>(2);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
Object value;
@@ -660,21 +714,23 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
}
synchronized (this) {
if (!this.cached) {
Object cachedFieldValue = null;
if (value != null || this.required) {
cachedFieldValue = desc;
Object cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
if (value != null && autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName);
}
}
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
else {
this.cachedFieldValue = null;
// cached flag remains false
}
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
}
return value;
@@ -708,10 +764,12 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
Object[] arguments;
if (this.cached) {
try {
arguments = resolveCachedArguments(beanName);
arguments = resolveCachedArguments(beanName, this.cachedMethodArguments);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
catch (BeansException ex) {
// Unexpected target bean mismatch for cached argument -> re-resolve
this.cached = false;
logger.debug("Failed to resolve cached argument", ex);
arguments = resolveMethodArguments(method, bean, beanName);
}
}
@@ -730,14 +788,13 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
}
@Nullable
private Object[] resolveCachedArguments(@Nullable String beanName) {
Object[] cachedMethodArguments = this.cachedMethodArguments;
private Object[] resolveCachedArguments(@Nullable String beanName, @Nullable Object[] cachedMethodArguments) {
if (cachedMethodArguments == null) {
return null;
}
Object[] arguments = new Object[cachedMethodArguments.length];
for (int i = 0; i < arguments.length; i++) {
arguments[i] = resolvedCachedArgument(beanName, cachedMethodArguments[i]);
arguments[i] = resolveCachedArgument(beanName, cachedMethodArguments[i]);
}
return arguments;
}
@@ -747,7 +804,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
int argumentCount = method.getParameterCount();
Object[] arguments = new Object[argumentCount];
DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
Set<String> autowiredBeanNames = new LinkedHashSet<>(argumentCount * 2);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
for (int i = 0; i < arguments.length; i++) {
@@ -756,7 +813,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
currDesc.setContainingClass(bean.getClass());
descriptors[i] = currDesc;
try {
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeanNames, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
@@ -770,26 +827,27 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
synchronized (this) {
if (!this.cached) {
if (arguments != null) {
DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);
registerDependentBeans(beanName, autowiredBeans);
if (autowiredBeans.size() == argumentCount) {
Iterator<String> it = autowiredBeans.iterator();
DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, argumentCount);
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == argumentCount) {
Iterator<String> it = autowiredBeanNames.iterator();
Class<?>[] paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
if (beanFactory.containsBean(autowiredBeanName) &&
if (arguments[i] != null && beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
descriptors[i], autowiredBeanName, paramTypes[i]);
descriptors[i], autowiredBeanName);
}
}
}
this.cachedMethodArguments = cachedMethodArguments;
this.cached = true;
}
else {
this.cachedMethodArguments = null;
// cached flag remains false
}
this.cached = true;
}
}
return arguments;
@@ -805,17 +863,14 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
private final String shortcut;
private final Class<?> requiredType;
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcut, Class<?> requiredType) {
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcut) {
super(original);
this.shortcut = shortcut;
this.requiredType = requiredType;
}
@Override
public Object resolveShortcut(BeanFactory beanFactory) {
return beanFactory.getBean(this.shortcut, this.requiredType);
return beanFactory.getBean(this.shortcut, getDependencyType());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@ import java.util.Set;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.DependencyDescriptor;
@@ -137,7 +138,7 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
* as a <em>qualifier</em>, the bean must 'match' against the annotation as
* well as any attributes it may contain. The bean definition must contain
* the same qualifier or match by meta attributes. A "value" attribute will
* fallback to match against the bean name or an alias if a qualifier or
* fall back to match against the bean name or an alias if a qualifier or
* attribute does not match.
* @see Qualifier
*/
@@ -186,7 +187,7 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
if (isQualifier(metaType)) {
foundMeta = true;
// Only accept fallback match if @Qualifier annotation has a value...
// Otherwise it is just a marker for a custom qualifier annotation.
// Otherwise, it is just a marker for a custom qualifier annotation.
if ((fallbackToMeta && ObjectUtils.isEmpty(AnnotationUtils.getValue(metaAnn))) ||
!checkQualifier(bdHolder, metaAnn, typeConverter)) {
return false;
@@ -240,10 +241,11 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
}
}
if (targetAnnotation == null) {
BeanFactory beanFactory = getBeanFactory();
// Look for matching annotation on the target class
if (getBeanFactory() != null) {
if (beanFactory != null) {
try {
Class<?> beanType = getBeanFactory().getType(bdHolder.getBeanName());
Class<?> beanType = beanFactory.getType(bdHolder.getBeanName());
if (beanType != null) {
targetAnnotation = AnnotationUtils.getAnnotation(ClassUtils.getUserClass(beanType), type);
}
@@ -30,7 +30,7 @@ import org.springframework.beans.BeansException;
*
* <p>A {@code BeanFactoryPostProcessor} may interact with and modify bean
* definitions, but never bean instances. Doing so may cause premature bean
* instantiation, violating the container and causing unintended side-effects.
* instantiation, violating the container and causing unintended side effects.
* If bean instance interaction is required, consider implementing
* {@link BeanPostProcessor} instead.
*
@@ -65,7 +65,7 @@ public class ConstructorArgumentValues {
/**
* Copy all given argument values into this object, using separate holder
* instances to keep the values independent from the original object.
* instances to keep the values independent of the original object.
* <p>Note: Identical ValueHolder instances will only be registered once,
* to allow for merging and re-merging of argument value definitions. Distinct
* ValueHolder instances carrying the same content are of course allowed.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -155,7 +155,7 @@ public abstract class YamlProcessor {
* resources. Each resource is parsed in turn and the documents inside checked against
* the {@link #setDocumentMatchers(DocumentMatcher...) matchers}. If a document
* matches it is passed into the callback, along with its representation as Properties.
* Depending on the {@link #setResolutionMethod(ResolutionMethod)} not all of the
* Depending on the {@link #setResolutionMethod(ResolutionMethod)} not all the
* documents will be parsed.
* @param callback a callback to delegate to once matching documents are found
* @see #createYaml()
@@ -184,8 +184,9 @@ public abstract class YamlProcessor {
protected Yaml createYaml() {
LoaderOptions loaderOptions = new LoaderOptions();
loaderOptions.setAllowDuplicateKeys(false);
return new Yaml(new FilteringConstructor(loaderOptions), new Representer(),
new DumperOptions(), loaderOptions);
DumperOptions dumperOptions = new DumperOptions();
return new Yaml(new FilteringConstructor(loaderOptions), new Representer(dumperOptions),
dumperOptions, loaderOptions);
}
private boolean process(MatchCallback callback, Yaml yaml, Resource resource) {
@@ -124,7 +124,7 @@ public class BeanComponentDefinition extends BeanDefinitionHolder implements Com
}
/**
* This implementations expects the other object to be of type BeanComponentDefinition
* This implementation expects the other object to be of type BeanComponentDefinition
* as well, in addition to the superclass's equality requirements.
*/
@Override
@@ -50,13 +50,13 @@ import org.springframework.beans.factory.config.BeanReference;
* {@link #getBeanReferences}, tools may wish to inspect all {@link BeanDefinition BeanDefinitions} to gather
* the full set of {@link BeanReference BeanReferences}. Implementations are required to provide
* all {@link BeanReference BeanReferences} that are required to validate the configuration of the
* overall logical entity as well as those required to provide full user visualisation of the configuration.
* overall logical entity as well as those required to provide full user visualization of the configuration.
* It is expected that certain {@link BeanReference BeanReferences} will not be important to
* validation or to the user view of the configuration and as such these may be omitted. A tool may wish to
* display any additional {@link BeanReference BeanReferences} sourced through the supplied
* {@link BeanDefinition BeanDefinitions} but this is not considered to be a typical case.
*
* <p>Tools can determine the important of contained {@link BeanDefinition BeanDefinitions} by checking the
* <p>Tools can determine the importance of contained {@link BeanDefinition BeanDefinitions} by checking the
* {@link BeanDefinition#getRole role identifier}. The role is essentially a hint to the tool as to how
* important the configuration provider believes a {@link BeanDefinition} is to the end user. It is expected
* that tools will <strong>not</strong> display all {@link BeanDefinition BeanDefinitions} for a given
@@ -1,5 +1,5 @@
/**
* Support package for the Java 6 ServiceLoader facility.
* Support package for the Java {@link java.util.ServiceLoader} facility.
*/
@NonNullApi
@NonNullFields
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1504,13 +1504,13 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
Set<String> autowiredBeanNames = new LinkedHashSet<>(propertyNames.length * 2);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
// even if it technically is an unsatisfied, non-simple property.
if (Object.class != pd.getPropertyType()) {
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
@@ -945,7 +945,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
}
/**
* Specify whether or not the configured initializer method is the default.
* Specify whether the configured initializer method is the default.
* <p>The default value is {@code true} for a locally specified init method
* but switched to {@code false} for a shared setting in a defaults section
* (e.g. {@code bean init-method} versus {@code beans default-init-method}
@@ -984,7 +984,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
}
/**
* Specify whether or not the configured destroy method is the default.
* Specify whether the configured destroy method is the default.
* <p>The default value is {@code true} for a locally specified destroy method
* but switched to {@code false} for a shared setting in a defaults section
* (e.g. {@code bean destroy-method} versus {@code beans default-destroy-method}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -161,7 +161,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
/** Cache of pre-filtered post-processors. */
@Nullable
private volatile BeanPostProcessorCache beanPostProcessorCache;
private BeanPostProcessorCache beanPostProcessorCache;
/** Map from scope identifier String to corresponding Scope. */
private final Map<String, Scope> scopes = new LinkedHashMap<>(8);
@@ -593,7 +593,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
// Setup the types that we want to match against
// Set up the types that we want to match against
Class<?> classToMatch = typeToMatch.resolve();
if (classToMatch == null) {
classToMatch = FactoryBean.class;
@@ -944,10 +944,12 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// Remove from old position, if any
this.beanPostProcessors.remove(beanPostProcessor);
// Add to end of list
this.beanPostProcessors.add(beanPostProcessor);
synchronized (this.beanPostProcessors) {
// Remove from old position, if any
this.beanPostProcessors.remove(beanPostProcessor);
// Add to end of list
this.beanPostProcessors.add(beanPostProcessor);
}
}
/**
@@ -957,8 +959,12 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* @see #addBeanPostProcessor
*/
public void addBeanPostProcessors(Collection<? extends BeanPostProcessor> beanPostProcessors) {
this.beanPostProcessors.removeAll(beanPostProcessors);
this.beanPostProcessors.addAll(beanPostProcessors);
synchronized (this.beanPostProcessors) {
// Remove from old position, if any
this.beanPostProcessors.removeAll(beanPostProcessors);
// Add to end of list
this.beanPostProcessors.addAll(beanPostProcessors);
}
}
@Override
@@ -980,26 +986,34 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* @since 5.3
*/
BeanPostProcessorCache getBeanPostProcessorCache() {
BeanPostProcessorCache bpCache = this.beanPostProcessorCache;
if (bpCache == null) {
bpCache = new BeanPostProcessorCache();
for (BeanPostProcessor bp : this.beanPostProcessors) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
bpCache.instantiationAware.add((InstantiationAwareBeanPostProcessor) bp);
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
bpCache.smartInstantiationAware.add((SmartInstantiationAwareBeanPostProcessor) bp);
synchronized (this.beanPostProcessors) {
BeanPostProcessorCache bppCache = this.beanPostProcessorCache;
if (bppCache == null) {
bppCache = new BeanPostProcessorCache();
for (BeanPostProcessor bpp : this.beanPostProcessors) {
if (bpp instanceof InstantiationAwareBeanPostProcessor) {
bppCache.instantiationAware.add((InstantiationAwareBeanPostProcessor) bpp);
if (bpp instanceof SmartInstantiationAwareBeanPostProcessor) {
bppCache.smartInstantiationAware.add((SmartInstantiationAwareBeanPostProcessor) bpp);
}
}
if (bpp instanceof DestructionAwareBeanPostProcessor) {
bppCache.destructionAware.add((DestructionAwareBeanPostProcessor) bpp);
}
if (bpp instanceof MergedBeanDefinitionPostProcessor) {
bppCache.mergedDefinition.add((MergedBeanDefinitionPostProcessor) bpp);
}
}
if (bp instanceof DestructionAwareBeanPostProcessor) {
bpCache.destructionAware.add((DestructionAwareBeanPostProcessor) bp);
}
if (bp instanceof MergedBeanDefinitionPostProcessor) {
bpCache.mergedDefinition.add((MergedBeanDefinitionPostProcessor) bp);
}
this.beanPostProcessorCache = bppCache;
}
this.beanPostProcessorCache = bpCache;
return bppCache;
}
}
private void resetBeanPostProcessorCache() {
synchronized (this.beanPostProcessors) {
this.beanPostProcessorCache = null;
}
return bpCache;
}
/**
@@ -2014,27 +2028,27 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
@Override
public BeanPostProcessor set(int index, BeanPostProcessor element) {
BeanPostProcessor result = super.set(index, element);
beanPostProcessorCache = null;
resetBeanPostProcessorCache();
return result;
}
@Override
public boolean add(BeanPostProcessor o) {
boolean success = super.add(o);
beanPostProcessorCache = null;
resetBeanPostProcessorCache();
return success;
}
@Override
public void add(int index, BeanPostProcessor element) {
super.add(index, element);
beanPostProcessorCache = null;
resetBeanPostProcessorCache();
}
@Override
public BeanPostProcessor remove(int index) {
BeanPostProcessor result = super.remove(index);
beanPostProcessorCache = null;
resetBeanPostProcessorCache();
return result;
}
@@ -2042,7 +2056,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
public boolean remove(Object o) {
boolean success = super.remove(o);
if (success) {
beanPostProcessorCache = null;
resetBeanPostProcessorCache();
}
return success;
}
@@ -2051,7 +2065,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
public boolean removeAll(Collection<?> c) {
boolean success = super.removeAll(c);
if (success) {
beanPostProcessorCache = null;
resetBeanPostProcessorCache();
}
return success;
}
@@ -2060,7 +2074,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
public boolean retainAll(Collection<?> c) {
boolean success = super.retainAll(c);
if (success) {
beanPostProcessorCache = null;
resetBeanPostProcessorCache();
}
return success;
}
@@ -2069,7 +2083,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
public boolean addAll(Collection<? extends BeanPostProcessor> c) {
boolean success = super.addAll(c);
if (success) {
beanPostProcessorCache = null;
resetBeanPostProcessorCache();
}
return success;
}
@@ -2078,7 +2092,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
public boolean addAll(int index, Collection<? extends BeanPostProcessor> c) {
boolean success = super.addAll(index, c);
if (success) {
beanPostProcessorCache = null;
resetBeanPostProcessorCache();
}
return success;
}
@@ -2087,7 +2101,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
public boolean removeIf(Predicate<? super BeanPostProcessor> filter) {
boolean success = super.removeIf(filter);
if (success) {
beanPostProcessorCache = null;
resetBeanPostProcessorCache();
}
return success;
}
@@ -2095,7 +2109,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
@Override
public void replaceAll(UnaryOperator<BeanPostProcessor> operator) {
super.replaceAll(operator);
beanPostProcessorCache = null;
resetBeanPostProcessorCache();
}
}
@@ -293,7 +293,7 @@ public final class BeanDefinitionBuilder {
}
/**
* Set whether or not this definition is abstract.
* Set whether this definition is abstract.
*/
public BeanDefinitionBuilder setAbstract(boolean flag) {
this.beanDefinition.setAbstract(flag);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -134,7 +134,7 @@ class BeanDefinitionValueResolver {
return resolveInnerBean(argName, innerBeanName, bd);
}
else if (value instanceof DependencyDescriptor) {
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
Set<String> autowiredBeanNames = new LinkedHashSet<>(2);
Object result = this.beanFactory.resolveDependency(
(DependencyDescriptor) value, this.beanName, autowiredBeanNames, this.typeConverter);
for (String autowiredBeanName : autowiredBeanNames) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,6 +45,7 @@ import org.springframework.beans.TypeConverter;
import org.springframework.beans.TypeMismatchException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.InjectionPoint;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
@@ -85,12 +86,6 @@ class ConstructorResolver {
private static final Object[] EMPTY_ARGS = new Object[0];
/**
* Marker for autowired arguments in a cached argument array, to be replaced
* by a {@linkplain #resolveAutowiredArgument resolved autowired argument}.
*/
private static final Object autowiredArgumentMarker = new Object();
private static final NamedThreadLocal<InjectionPoint> currentInjectionPoint =
new NamedThreadLocal<>("Current injection point");
@@ -729,7 +724,7 @@ class ConstructorResolver {
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
Set<String> allAutowiredBeanNames = new LinkedHashSet<>(paramTypes.length * 2);
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
Class<?> paramType = paramTypes[paramIndex];
@@ -764,8 +759,8 @@ class ConstructorResolver {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Could not convert argument value of type [" +
ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
}
Object sourceHolder = valueHolder.getSource();
if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
@@ -788,11 +783,17 @@ class ConstructorResolver {
"] - did you specify the correct bean references as arguments?");
}
try {
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);
args.rawArguments[paramIndex] = autowiredArgument;
args.arguments[paramIndex] = autowiredArgument;
args.preparedArguments[paramIndex] = autowiredArgumentMarker;
ConstructorDependencyDescriptor desc = new ConstructorDependencyDescriptor(methodParam, true);
Set<String> autowiredBeanNames = new LinkedHashSet<>(2);
Object arg = resolveAutowiredArgument(
desc, paramType, beanName, autowiredBeanNames, converter, fallback);
if (arg != null) {
setShortcutIfPossible(desc, paramType, autowiredBeanNames);
}
allAutowiredBeanNames.addAll(autowiredBeanNames);
args.rawArguments[paramIndex] = arg;
args.arguments[paramIndex] = arg;
args.preparedArguments[paramIndex] = desc;
args.resolveNecessary = true;
}
catch (BeansException ex) {
@@ -802,14 +803,7 @@ class ConstructorResolver {
}
}
for (String autowiredBeanName : autowiredBeanNames) {
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName +
"' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
" to bean named '" + autowiredBeanName + "'");
}
}
registerDependentBeans(executable, beanName, allAutowiredBeanNames);
return args;
}
@@ -829,31 +823,61 @@ class ConstructorResolver {
Object[] resolvedArgs = new Object[argsToResolve.length];
for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
Object argValue = argsToResolve[argIndex];
MethodParameter methodParam = MethodParameter.forExecutable(executable, argIndex);
if (argValue == autowiredArgumentMarker) {
argValue = resolveAutowiredArgument(methodParam, beanName, null, converter, true);
Class<?> paramType = paramTypes[argIndex];
boolean convertNecessary = false;
if (argValue instanceof ConstructorDependencyDescriptor) {
ConstructorDependencyDescriptor descriptor = (ConstructorDependencyDescriptor) argValue;
try {
argValue = resolveAutowiredArgument(descriptor, paramType, beanName,
null, converter, true);
}
catch (BeansException ex) {
// Unexpected target bean mismatch for cached argument -> re-resolve
Set<String> autowiredBeanNames = null;
if (descriptor.hasShortcut()) {
// Reset shortcut and try to re-resolve it in this thread...
descriptor.setShortcut(null);
autowiredBeanNames = new LinkedHashSet<>(2);
}
logger.debug("Failed to resolve cached argument", ex);
argValue = resolveAutowiredArgument(descriptor, paramType, beanName,
autowiredBeanNames, converter, true);
if (autowiredBeanNames != null && !descriptor.hasShortcut()) {
// We encountered as stale shortcut before, and the shortcut has
// not been re-resolved by another thread in the meantime...
if (argValue != null) {
setShortcutIfPossible(descriptor, paramType, autowiredBeanNames);
}
registerDependentBeans(executable, beanName, autowiredBeanNames);
}
}
}
else if (argValue instanceof BeanMetadataElement) {
argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
convertNecessary = true;
}
else if (argValue instanceof String) {
argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd);
convertNecessary = true;
}
Class<?> paramType = paramTypes[argIndex];
try {
resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam);
}
catch (TypeMismatchException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(argValue) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
if (convertNecessary) {
MethodParameter methodParam = MethodParameter.forExecutable(executable, argIndex);
try {
argValue = converter.convertIfNecessary(argValue, paramType, methodParam);
}
catch (TypeMismatchException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(argValue) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
}
}
resolvedArgs[argIndex] = argValue;
}
return resolvedArgs;
}
protected Constructor<?> getUserDeclaredConstructor(Constructor<?> constructor) {
private Constructor<?> getUserDeclaredConstructor(Constructor<?> constructor) {
Class<?> declaringClass = constructor.getDeclaringClass();
Class<?> userClass = ClassUtils.getUserClass(declaringClass);
if (userClass != declaringClass) {
@@ -869,23 +893,22 @@ class ConstructorResolver {
}
/**
* Template method for resolving the specified argument which is supposed to be autowired.
* Resolve the specified argument which is supposed to be autowired.
*/
@Nullable
protected Object resolveAutowiredArgument(MethodParameter param, String beanName,
Object resolveAutowiredArgument(DependencyDescriptor descriptor, Class<?> paramType, String beanName,
@Nullable Set<String> autowiredBeanNames, TypeConverter typeConverter, boolean fallback) {
Class<?> paramType = param.getParameterType();
if (InjectionPoint.class.isAssignableFrom(paramType)) {
InjectionPoint injectionPoint = currentInjectionPoint.get();
if (injectionPoint == null) {
throw new IllegalStateException("No current InjectionPoint available for " + param);
throw new IllegalStateException("No current InjectionPoint available for " + descriptor);
}
return injectionPoint;
}
try {
return this.beanFactory.resolveDependency(
new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
return this.beanFactory.resolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter);
}
catch (NoUniqueBeanDefinitionException ex) {
throw ex;
@@ -908,6 +931,31 @@ class ConstructorResolver {
}
}
private void setShortcutIfPossible(
ConstructorDependencyDescriptor descriptor, Class<?> paramType, Set<String> autowiredBeanNames) {
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (this.beanFactory.containsBean(autowiredBeanName) &&
this.beanFactory.isTypeMatch(autowiredBeanName, paramType)) {
descriptor.setShortcut(autowiredBeanName);
}
}
}
private void registerDependentBeans(
Executable executable, String beanName, Set<String> autowiredBeanNames) {
for (String autowiredBeanName : autowiredBeanNames) {
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName + "' via " +
(executable instanceof Constructor ? "constructor" : "factory method") +
" to bean named '" + autowiredBeanName + "'");
}
}
}
static InjectionPoint setCurrentInjectionPoint(@Nullable InjectionPoint injectionPoint) {
InjectionPoint old = currentInjectionPoint.get();
if (injectionPoint != null) {
@@ -985,7 +1033,7 @@ class ConstructorResolver {
/**
* Delegate for checking Java 6's {@link ConstructorProperties} annotation.
* Delegate for checking Java's {@link ConstructorProperties} annotation.
*/
private static class ConstructorPropertiesChecker {
@@ -1006,4 +1054,35 @@ class ConstructorResolver {
}
}
/**
* DependencyDescriptor marker for constructor arguments,
* for differentiating between a provided DependencyDescriptor instance
* and an internally built DependencyDescriptor for autowiring purposes.
*/
@SuppressWarnings("serial")
private static class ConstructorDependencyDescriptor extends DependencyDescriptor {
@Nullable
private volatile String shortcut;
public ConstructorDependencyDescriptor(MethodParameter methodParameter, boolean required) {
super(methodParameter, required);
}
public void setShortcut(@Nullable String shortcut) {
this.shortcut = shortcut;
}
public boolean hasShortcut() {
return (this.shortcut != null);
}
@Override
public Object resolveShortcut(BeanFactory beanFactory) {
String shortcut = this.shortcut;
return (shortcut != null ? beanFactory.getBean(shortcut, getDependencyType()) : null);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -280,7 +280,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
/**
* Return the dependency comparator for this BeanFactory (may be {@code null}.
* Return the dependency comparator for this BeanFactory (may be {@code null}).
* @since 4.0
*/
@Nullable
@@ -585,7 +585,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (!matchFound) {
// In case of FactoryBean, try to match FactoryBean instance itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
}
}
}
if (matchFound) {
@@ -959,7 +961,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
StartupStep smartInitialize = getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
@@ -2165,20 +2167,25 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Nullable
public Object getOrderSource(Object obj) {
String beanName = this.instancesToBeanNames.get(obj);
if (beanName == null || !containsBeanDefinition(beanName)) {
if (beanName == null) {
return null;
}
RootBeanDefinition beanDefinition = getMergedLocalBeanDefinition(beanName);
List<Object> sources = new ArrayList<>(2);
Method factoryMethod = beanDefinition.getResolvedFactoryMethod();
if (factoryMethod != null) {
sources.add(factoryMethod);
try {
RootBeanDefinition beanDefinition = (RootBeanDefinition) getMergedBeanDefinition(beanName);
List<Object> sources = new ArrayList<>(2);
Method factoryMethod = beanDefinition.getResolvedFactoryMethod();
if (factoryMethod != null) {
sources.add(factoryMethod);
}
Class<?> targetType = beanDefinition.getTargetType();
if (targetType != null && targetType != obj.getClass()) {
sources.add(targetType);
}
return sources.toArray();
}
Class<?> targetType = beanDefinition.getTargetType();
if (targetType != null && targetType != obj.getClass()) {
sources.add(targetType);
catch (NoSuchBeanDefinitionException ex) {
return null;
}
return sources.toArray();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -102,7 +102,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
private boolean singletonsCurrentlyInDestruction = false;
/** Disposable bean instances: bean name to disposable instance. */
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
private final Map<String, DisposableBean> disposableBeans = new LinkedHashMap<>();
/** Map between containing bean names: bean name to Set of bean names that the bean contains. */
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
@@ -340,7 +340,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
* (within the entire factory).
* @param beanName the name of the bean
*/
public boolean isSingletonCurrentlyInCreation(String beanName) {
public boolean isSingletonCurrentlyInCreation(@Nullable String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
@@ -447,17 +447,17 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
}
String canonicalName = canonicalName(beanName);
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
if (dependentBeans == null || dependentBeans.isEmpty()) {
return false;
}
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
alreadySeen.add(beanName);
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
alreadySeen.add(beanName);
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
@@ -554,7 +554,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
// Destroy the corresponding DisposableBean instance.
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
disposableBean = this.disposableBeans.remove(beanName);
}
destroyBean(beanName, disposableBean);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -68,8 +68,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
private static final String SHUTDOWN_METHOD_NAME = "shutdown";
private static final Log logger = LogFactory.getLog(DisposableBeanAdapter.class);
private static final Log logger = LogFactory.getLog(DisposableBeanAdapter.class);
private final Object bean;
@@ -214,12 +214,15 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
if (logger.isWarnEnabled()) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
// Log at warn level like below but add the exception stacktrace only with debug level
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}
}
@@ -240,12 +243,15 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
}
}
catch (Throwable ex) {
String msg = "Invocation of close method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
if (logger.isWarnEnabled()) {
String msg = "Invocation of close method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
// Log at warn level like below but add the exception stacktrace only with debug level
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}
}
@@ -320,18 +326,23 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
}
}
catch (InvocationTargetException ex) {
String msg = "Custom destroy method '" + this.destroyMethodName + "' on bean with name '" +
this.beanName + "' threw an exception";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex.getTargetException());
}
else {
logger.warn(msg + ": " + ex.getTargetException());
if (logger.isWarnEnabled()) {
String msg = "Custom destroy method '" + this.destroyMethodName + "' on bean with name '" +
this.beanName + "' threw an exception";
if (logger.isDebugEnabled()) {
// Log at warn level like below but add the exception stacktrace only with debug level
logger.warn(msg, ex.getTargetException());
}
else {
logger.warn(msg + ": " + ex.getTargetException());
}
}
}
catch (Throwable ex) {
logger.warn("Failed to invoke custom destroy method '" + this.destroyMethodName +
"' on bean with name '" + this.beanName + "'", ex);
if (logger.isWarnEnabled()) {
logger.warn("Failed to invoke custom destroy method '" + this.destroyMethodName +
"' on bean with name '" + this.beanName + "'", ex);
}
}
}
@@ -33,7 +33,7 @@ import org.springframework.util.ClassUtils;
/**
* Basic {@link AutowireCandidateResolver} that performs a full generic type
* match with the candidate's type if the dependency is declared as a generic type
* (e.g. Repository&lt;Customer&gt;).
* (e.g. {@code Repository<Customer>}).
*
* <p>This is the base class for
* {@link org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver},
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -112,7 +112,7 @@ public class LookupOverride extends MethodOverride {
@Override
public int hashCode() {
return (29 * super.hashCode() + ObjectUtils.nullSafeHashCode(this.beanName));
return super.hashCode() * 29 + ObjectUtils.nullSafeHashCode(this.beanName);
}
@Override

Some files were not shown because too many files have changed in this diff Show More