Compare commits

...
2998 Commits
Author SHA1 Message Date
Spring Builds 0d055fca80 Release v6.1.0-M4 2023-08-17 11:06:41 +00:00
Juergen Hoeller d41f546c43 Merge branch '6.0.x' 2023-08-17 10:24:34 +02:00
Juergen Hoeller c8a4026512 Revise note on non-public transactional methods for 6.0
Closes gh-31057
See gh-25582
2023-08-17 10:24:03 +02:00
Juergen Hoeller e685ff0416 Always accept existing explicit definition for same class name
See gh-25952
2023-08-16 18:46:32 +02:00
Juergen Hoeller 4bfbf7d3c8 Merge branch '6.0.x' 2023-08-16 17:56:18 +02:00
Juergen Hoeller 2111bf9b9d Upgrade to Caffeine 3.1.8 and Apache HttpComponents Core Reactive 5.2.2 2023-08-16 17:53:02 +02:00
Juergen Hoeller c72dd1ff66 Change "!void" pointcut expression to "int" for AspectJ 1.9.20 2023-08-16 17:32:26 +02:00
Sam Brannen 279e6eb423 Document best practices for inlined properties in @TestPropertySource 2023-08-16 17:27:18 +02:00
Juergen Hoeller eb65939341 Add examples for new bind/map methods on DatabaseClient
See gh-27282
See gh-26021
2023-08-16 17:02:41 +02:00
Juergen Hoeller 3f79b267b1 Merge branch '6.0.x' 2023-08-16 16:55:01 +02:00
Juergen Hoeller 43bd78913c Polishing 2023-08-16 16:52:53 +02:00
Juergen Hoeller 5458e0dccc Upgrade to Tomcat 10.1.12 and AspectJ 1.9.20 2023-08-16 16:52:45 +02:00
Sébastien Deleuze 5641d87ce8 Merge branch '6.0.x' 2023-08-16 16:06:55 +02:00
Sébastien Deleuze 78a73e5f57 Add missing Hibernate 6.2 proxy hints
This commit contributes proxy hints needed by
SharedEntityManagerCreator for
org.hibernate.query.sqm.internal.QuerySqmImpl interfaces.

Until Hibernate 6.1, those hints were erroneously provided
at GraalVM reachability metadata level. As of Hibernate 6.2,
they are not, hence the need to contribute them at Spring
Framework level.

A related smoke test has been contributed via
spring-projects/spring-aot-smoke-tests#188.

Closes gh-31050
2023-08-16 15:57:05 +02:00
Sam Brannen 24dd484471 Polish internal SequencedProperties implementation 2023-08-16 14:11:02 +02:00
Sam Brannen b43972bb54 Preserve property ordering for text blocks in @TestPropertySource
See gh-31053
2023-08-16 13:48:25 +02:00
Brian Clozel 17109b2402 Upgrade to Reactor 2023.0.0-M2
Closes gh-31014
2023-08-16 13:02:05 +02:00
Brian Clozel dbfece6c31 Upgrade to Micrometer 1.12.0-M2
Closes gh-30997
2023-08-16 13:01:54 +02:00
Juergen Hoeller 86a101ac2b Merge branch '6.0.x' 2023-08-16 12:48:43 +02:00
Juergen Hoeller c7269feeaa 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
2023-08-16 12:48:06 +02:00
Sam Brannen 1f544f113a Support resource patterns in @TestPropertySource locations
Inspired by the recently added support for resource patterns in
@PropertySource locations, this commit adds the same support for
resource locations in @TestPropertySource.

For example, assuming the `config` folder in the classpath contains
only 3 files matching the pattern `file?.properties`,

... the following:

@TestPropertySource("classpath:/config/file1.properties")
@TestPropertySource("classpath:/config/file2.properties")
@TestPropertySource("classpath:/config/file3.properties")

... or:

@TestPropertySource({
    "classpath:/config/file1.properties",
    "classpath:/config/file2.properties",
    "classpath:/config/file3.properties"
})

... can now be replaced by:

@TestPropertySource("classpath*:/config/file?.properties")

See gh-21325
Closes gh-31055
2023-08-16 12:34:20 +02:00
Sam Brannen 3a38bb48b5 Polishing 2023-08-16 12:17:58 +02:00
Sam Brannen 02d3269dbb Polishing 2023-08-16 11:44:55 +02:00
Sam Brannen d81ddcef34 Update documentation regarding repeatable @PropertySource support
See gh-30941
2023-08-16 11:37:12 +02:00
Sam Brannen 701c39a325 Update @PropertySource Javadoc regarding resource patterns
See gh-21325
2023-08-16 11:26:59 +02:00
Juergen Hoeller d77595bf2c Merge branch '6.0.x' 2023-08-16 11:00:58 +02:00
Juergen Hoeller 1e75041b00 Consistent references to scalar values vs Parameter objects
See gh-27282
2023-08-16 11:00:17 +02:00
Juergen Hoeller 0b99872704 Support for binding values from a source Map
See gh-27282
2023-08-16 10:55:26 +02:00
Juergen Hoeller b8b3e6d20c Merge branch '6.0.x'
# Conflicts:
#	spring-r2dbc/src/main/java/org/springframework/r2dbc/core/DatabaseClient.java
2023-08-15 23:52:44 +02:00
Juergen Hoeller 08bc7ed8f0 Polishing 2023-08-15 23:51:41 +02:00
Juergen Hoeller ae3bc378d6 Support for parameter/result records and beans on DatabaseClient
Includes a revision of BeanProperty/DataClassRowMapper with exclusively constructor-based configuration and without JDBC-inherited legacy settings.

Closes gh-27282
Closes gh-26021
2023-08-15 22:42:45 +02:00
Juergen Hoeller 2ab1c5b387 JdbcClient documentation update
See gh-30931
2023-08-15 22:42:25 +02:00
Sam Brannen a2f52db452 Support text blocks for inlined properties in @TestPropertySource
Prior to this commit, inlined properties could only be supplied as an
array of Strings as follows.

@TestPropertySource(properties = {
    "key1 = value1",
    "key2 = value2"
})

Although a user could supply a text block, it was previously rejected
due to a "single key-value pair per string" check in
TestPropertySourceUtils.convertInlinedPropertiesToMap(String...).

This commit removes that restriction and allows the above example to be
refactored to use a text block as follows.

@TestPropertySource(properties = """
    key1 = value1
    key2 = value2
    """
)

Closes gh-31053
2023-08-15 18:10:01 +02:00
Sam Brannen 8c2a39b5af Simplify Javadoc 2023-08-15 18:10:01 +02:00
Sébastien Deleuze 02d003127f Move ServerWebExchange Kotlin extensions
This commit moves ServerWebExchange Kotlin extensions
where they belong: in the spring-web module with the
org.springframework.web.server package, like
ServerWebExchange itself.

The extensions in the wrong location are deprecated
and semi-automated migration to the new variants is
made possible via @Deprecated + ReplaceWith(...).

Some tests have been added as well.

Closes gh-31046
2023-08-15 18:03:41 +02:00
Juergen Hoeller 57f675c537 Allow @Bean method to override scanned class matching its return type
Closes gh-31052
2023-08-15 13:55:57 +02:00
Juergen Hoeller d89e305c87 Introduce SimplePropertyRowMapper with flexible constructor/property/field mapping
Includes query(Class) method with value and property mapping support on JdbcClient.
JdbcClient's singleColumn/singleValue are declared without a Class parameter now.

Closes gh-26594
See gh-30931
2023-08-15 13:14:52 +02:00
Sam Brannen 443e3d5fa6 Polishing 2023-08-14 19:48:32 +02:00
Juergen Hoeller cf75a09011 Polishing 2023-08-14 19:39:19 +02:00
Juergen Hoeller 45c20e34e4 Merge branch '6.0.x'
# Conflicts:
#	spring-context/src/test/java/org/springframework/context/annotation/PropertySourceAnnotationTests.java
2023-08-14 19:29:14 +02:00
Juergen Hoeller 2ce75dc415 Polishing 2023-08-14 19:28:19 +02:00
Juergen Hoeller 8b3ddeed05 Test factory-bean/method placeholders as well
See gh-20189
2023-08-14 19:28:12 +02:00
Juergen Hoeller 9c74c25961 Support for resource patterns in @PropertySource locations
Closes gh-21325
2023-08-14 19:16:52 +02:00
Sam Brannen 3228502108 Polish MessageListenerContainerObservationTests 2023-08-14 17:08:56 +02:00
Brian Clozel 94fe1f4c63 Guard for Micrometer Core usage in JMS instrumentation
This commit ensures that the Observability instrumentation for
`@JmsListener` does not assume that micrometer-core is on the classpath
and guards against direct usage.

Closes gh-30335
2023-08-14 16:27:45 +02:00
Juergen Hoeller 20d27e4fb6 Merge branch '6.0.x' 2023-08-14 15:14:58 +02:00
Juergen Hoeller 389238f622 Add registerReactiveTypeOverride method to ReactiveAdapterRegistry
Closes gh-31047
2023-08-14 15:14:22 +02:00
Juergen Hoeller fd5b0e144d Reuse Reactive Streams 1.0.3 FlowAdapters for Flow.Publisher bridge
See gh-31000
2023-08-14 14:25:03 +02:00
Brian Clozel 2c895974b2 Add observability support for JMS
This commit adds observability support for Jakarta JMS support in
spring-jms support. This feature leverages the `JmsInstrumentation`
infrastructure in `io.micrometer:micrometer-core` library.

This instruments the `JmsTemplate` and the `@JmsListener` support to
record observations:

* "jms.message.publish" when the `JmsTemplate` sends a message
* "jms.message.process" when a message is processed by a `@JmsListener`
  annotated method

The observation `Convention` and `Context` implementations are shipped
with "micrometer-core".

Closes gh-30335
2023-08-13 18:24:51 +02:00
Sam Brannen bfeca4a0bf Polish contribution
See gh-30744
2023-08-13 17:03:12 +02:00
Adilson A 4979d8fded Increase code coverage in spring-core serializer package
Closes gh-30744
2023-08-13 16:26:02 +02:00
Sam Brannen f9b6aed6b6 Polishing
... for consistency with StandardAnnotationMetadata.
2023-08-13 16:21:18 +02:00
Sam Brannen 156546ad05 Make AnnotationAttributes.validated field immutable 2023-08-13 13:43:27 +02:00
Sam Brannen 1a05ba3215 Polishing 2023-08-13 12:18:26 +02:00
Sam Brannen 3bda2b7124 Find all @ComponentScan and @PropertySource annotations
Prior to this commit, Spring failed to find multiple composed
@ComponentScan and @PropertySource annotations or multiple
@ComponentScans and @PropertySources container annotations. The reason
was due to lacking support in the AnnotatedTypeMetadata API.

This commit introduces support for finding all @ComponentScan and
@PropertySource annotations by making use of the new
getMergedRepeatableAnnotationAttributes() method in
AnnotatedTypeMetadata.

Closes gh-30941
See gh-31041
2023-08-13 11:33:32 +02:00
Sam Brannen 0b902f32f6 Support finding repeatable annotations in AnnotatedTypeMetadata
AnnotatedTypeMetadata has various methods for finding annotations;
however, prior to this commit it did not provide explicit support for
repeatable annotations.

Although it is possible to craft a search "query" for repeatable
annotations using the MergedAnnotations API via getAnnotations(), that
requires intimate knowledge of the MergedAnnotations API as well as the
structure of repeatable annotations.

Furthermore, the bugs reported in gh-30941 result from the fact that
AnnotationConfigUtils attempts to use the existing functionality in
AnnotatedTypeMetadata to find repeatable annotations without success.

This commit introduces a getMergedRepeatableAnnotationAttributes()
method in AnnotatedTypeMetadata that provides dedicated support for
finding merged repeatable annotation attributes with full @AliasFor
semantics.

Closes gh-31041
2023-08-12 18:49:08 +02:00
Sam Brannen fb6c325cc0 Document @AliasFor support in AnnotatedTypeMetadata.getAnnotationAttributes()
The Javadoc for getAnnotationAttributes() states that it supports
"attribute overrides on composed annotations"; however, it actually
supports @AliasFor in general, including attribute aliases within a
given annotation.

This commit updates the Javadoc and corresponding tests to reflect that.

Closes gh-31042
2023-08-12 18:09:37 +02:00
Sam Brannen c52bfc0586 Update test names to reflect status quo
AnnotationMetadataReadingVisitor was replaced by
SimpleAnnotationMetadata in Spring Framework 5.2.
2023-08-12 18:09:37 +02:00
Sam Brannen a33b14338f Polishing annotation processing internals 2023-08-12 15:41:48 +02:00
Sam Brannen 2ede74fa9c Merge branch '6.0.x' 2023-08-12 15:14:26 +02:00
Sam Brannen 6f2a13fafd Polishing 2023-08-12 15:14:05 +02:00
Juergen Hoeller 86ca6fee16 Merge branch '6.0.x' 2023-08-12 14:52:03 +02:00
Juergen Hoeller 6baa60d454 Polishing 2023-08-12 14:51:02 +02:00
Juergen Hoeller 92410395e3 Remove outdated documentation references to WebLogic/WebSphere
See gh-22093
2023-08-12 14:50:45 +02:00
Juergen Hoeller d03af15516 Explicit note on connection pool deadlock with REQUIRES_NEW
Closes gh-26250
2023-08-12 14:50:36 +02:00
Juergen Hoeller 9ede1d07a0 Revise multiple beans resolution for custom collection types
Closes gh-30022
2023-08-12 12:48:14 +02:00
Juergen Hoeller c65b0a199e Merge branch '6.0.x'
# Conflicts:
#	spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapter.java
2023-08-12 11:35:24 +02:00
Juergen Hoeller d781f299c0 Use extracted attributes instead of annotation access
See gh-31034
2023-08-12 11:34:25 +02:00
Juergen Hoeller 6fc4898a1b Find TransactionalEventListener annotation on target method
Closes gh-31034
2023-08-12 11:19:21 +02:00
Sébastien Deleuze 1e73439955 Support Kotlin value class properties in SpEL
This commit adds support for inlined Kotlin value
class properties in SpEL by leveraging Kotlin
reflection instead of Java reflection broken
by the mangled method name.

Closes gh-30468
2023-08-11 16:54:34 +02:00
Sébastien Deleuze 566621f7e3 Merge branch '6.0.x' 2023-08-10 19:13:19 +02:00
Sébastien Deleuze 0c15be004e Use Any? in ProceedingJoinPoint Kotlin examples
This commit changes Any to Any? in ProceedingJoinPoint
Kotlin examples in order to be consistent with Java
and avoid a "NullPointerException: pjp.proceed() must
not be null" error.

Closes gh-31015
2023-08-10 19:12:55 +02:00
AlmostFamiliar 1c6ef3fe38 Use Any? in ProceedingJoinPoint Kotlin examples
This commit changes Any to Any? in ProceedingJoinPoint
Kotlin examples in order to be consistent with Java
and avoid a "NullPointerException: pjp.proceed() must
not be null" error.

See gh-31015
2023-08-10 19:12:42 +02:00
Juergen Hoeller f516431260 Merge branch '6.0.x' 2023-08-09 23:54:30 +02:00
Juergen Hoeller d254bff197 Polishing 2023-08-09 23:53:40 +02:00
Juergen Hoeller 6fc5a78252 Cancel without interruption of currently running tasks
Leave potential interruption up to scheduler shutdown.

Closes gh-31019
2023-08-09 23:53:35 +02:00
Juergen Hoeller b4c61f20e7 Mention JdbcClient in package documentation
Closes gh-31017
2023-08-09 23:18:55 +02:00
Sébastien Deleuze 0c477f14cc Polishing
See gh-28638
2023-08-09 11:14:42 +02:00
Sébastien Deleuze c38f053905 Add Kotlin value classes tests with primitive types
This commit adds more Kotlin value classes tests with
primitive types to ensure testing unwrapped use case.

See gh-28638
2023-08-09 11:12:56 +02:00
Sébastien Deleuze 88c2a25f12 Add support for Kotlin value classes in BeanUtils
This commit adds support for Kotlin value classes annotated
with @JvmInline to BeanUtils#findPrimaryConstructor.

This is only the first step, more refinements are expected
to be needed to achieve a comprehensive support of Kotlin
values classes in Spring Framework.

Closes gh-28638
2023-08-09 10:31:49 +02:00
Juergen Hoeller dd76ed7a0a Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/core/ReactiveAdapterRegistry.java
#	spring-core/src/main/java/org/springframework/util/StopWatch.java
2023-08-08 20:12:08 +02:00
Juergen Hoeller d58e48d9f5 Explicit note on FactoryBean resolution with MBeanExporter
Closes gh-21676
2023-08-08 20:11:28 +02:00
Juergen Hoeller 8973d1ad8a Polishing 2023-08-08 20:10:23 +02:00
Sam Brannen 837e8960c2 Make addPropertySourcesToEnvironment() public
This commit makes the recently introduced
addPropertySourcesToEnvironment(ConfigurableEnvironment, ResourceLoader,
List<PropertySourceDescriptor>) method in TestPropertySourceUtils public
so that it can be used by third parties (for example, Spring Boot).

Closes gh-30981
2023-08-08 11:47:15 +03:00
Stephane Nicoll 8a6c52b018 Merge pull request #30904 from izeye
* pr/30904:
  Polish AbstractReflectionParameterNameDiscovererKotlinTests

Closes gh-30904
2023-08-08 10:26:30 +02:00
Johnny Lim 7f561fb53d Polish AbstractReflectionParameterNameDiscovererKotlinTests
See gh-30904
2023-08-08 10:23:07 +02:00
Juergen Hoeller c4896aca9b Defensively register Flow bridge in delegate class
See gh-31000
2023-08-08 09:52:42 +02:00
Juergen Hoeller 3b093754c8 Rename getLastTaskInfo to lastTaskInfo (aligned with currentTaskName)
See gh-25803
2023-08-08 09:41:00 +02:00
Juergen Hoeller 8e16e5ea35 Revise StopWatch for flexible time units in nanosecond precision
Closes gh-25803
2023-08-08 01:48:58 +02:00
Juergen Hoeller dedb58f7ed Defensively register default adapters behind Reactive Streams guard
See gh-31000
2023-08-07 20:48:10 +02:00
Sam Brannen f4b5738869 Polishing 2023-08-07 17:51:37 +03:00
xumengqi 21a007bb15 Fix misspelling of applicationListenerDectector variable
Closes gh-31006
2023-08-07 16:14:55 +02:00
Juergen Hoeller d3d414c3c7 Reject @Bean method with void return type
Closes gh-31007
2023-08-07 15:00:08 +02:00
Juergen Hoeller 3c34e69cc2 Merge branch '6.0.x' 2023-08-07 14:53:01 +02:00
Juergen Hoeller 2aae0a4e0c Polishing 2023-08-07 14:51:58 +02:00
Juergen Hoeller 156b3696a7 Reinstate Introspector.flushFromCaches() call for JDK ClassInfo cache
Closes gh-27781
2023-08-07 14:51:49 +02:00
Sam Brannen 526fc391ee Use Class#componentType() for consistency with arrayType()
Java 12 introduced java.lang.Class#componentType() as a shortcut for
getComponentType().

Since we started using arrayType() in fe5560400c, this commit switches
to componentType() for consistent API usage style.
2023-08-07 12:43:40 +03:00
Sam Brannen 96fd3c10fb Update copyright headers 2023-08-07 12:08:04 +03:00
Sam Brannen fe5560400c Use Class#arrayType() where feasible
Closes gh-31002
2023-08-07 12:07:46 +03:00
Juergen Hoeller 6090eb0b42 Merge branch '6.0.x' 2023-08-06 15:00:42 +02:00
Juergen Hoeller c36174b263 Polishing 2023-08-06 14:59:44 +02:00
Juergen Hoeller 3804b1c602 Merge branch '6.0.x'
# Conflicts:
#	spring-context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java
#	spring-core/src/main/java/org/springframework/core/ReactiveAdapterRegistry.java
#	spring-r2dbc/src/test/java/org/springframework/r2dbc/connection/R2dbcTransactionManagerUnitTests.java
2023-08-06 14:26:55 +02:00
Juergen Hoeller 6e5af9dccb Polishing 2023-08-06 14:25:39 +02:00
Juergen Hoeller 40b33bca59 Compatibility with Flow-based SmallRye Mutiny 2 at runtime
Includes simple Flow.Publisher bridge without Reactor.

Closes gh-31000
2023-08-06 14:04:24 +02:00
Juergen Hoeller 3253d2de89 Introduce TransactionExecutionListener with begin/commit/rollback notifications
Includes ConfigurableTransactionManager interface for listener registration.
Includes additional introspection methods on TransactionExecution interface.
Includes default method declarations on TransactionStatus/SmartTransactionObject.

Closes gh-27479
2023-08-06 14:03:44 +02:00
Juergen Hoeller eaf54b54c3 Detect illegal bean definition override during classpath scanning
Closes gh-25952
2023-08-06 14:03:29 +02:00
Juergen Hoeller c596ff5c38 Log warn message with specific guidance in BeanPostProcessorChecker
Closes gh-24092
2023-08-06 14:03:12 +02:00
Juergen Hoeller cc90a956f7 Reject invalid afterThrowing signature on ThrowsAdvice
Closes gh-1896
2023-08-06 14:02:57 +02:00
ali dandach 6dbd684279 Optimize collection usage in CGLIB fork
Closes gh-30993
2023-08-05 16:18:09 +03:00
Sam Brannen faf3c7831f Add support for property file encoding in @TestPropertySource
Prior to this commit, property files configured (or inferred) via
@TestPropertySource were read using the default encoding of the JVM.

This commit introduces an `encoding` attribute in @TestPropertySource
which allows developers to specify an explicit encoding for test
property files.

Closes gh-30982
2023-08-05 13:47:46 +03:00
Sam Brannen 59b78cc513 Polishing 2023-08-05 10:49:39 +03:00
Sam Brannen 14911fb32f Merge branch '6.0.x' 2023-08-05 10:28:32 +03:00
Sam Brannen 4a81814dbb Check exception cause for @PropertySource(ignoreResourceNotFound) support
Prior to this commit, the ignoreResourceNotFound flag in
@PropertySource was ignored by PropertySourceProcessor if a
PropertySourceFactory threw an exception which wrapped an exception
that would otherwise be ignored -- for example, a FileNotFoundException.

To address this issue, this commit updates PropertySourceFactory so
that it catches RuntimeException and IOException and then checks if the
exception or its cause is an "ignorable" exception in terms of
ignoreResourceNotFound semantics.

Closes gh-22276
2023-08-05 10:19:43 +03:00
Sam Brannen 1451f30781 Polish PropertySourceProcessor 2023-08-05 10:19:43 +03:00
Sam Brannen 4b54ca46d3 Polish PropertySourceDescriptor 2023-08-05 10:19:43 +03:00
rstoyanchev 5115684baf Revise docs for server use of @HttpExchange
Closes gh-30980
2023-08-04 18:21:42 +03:00
rstoyanchev 6630b16771 Polishing
See gh-30980
2023-08-04 18:21:42 +03:00
Olga MaciaszekSharma d1d5b54f12 Support @HttpExchange for server-side handling
See gh-30980
2023-08-04 18:21:42 +03:00
Brian Clozel 646fd3edcc Avoid thread pinning in SseEmitter write operations
This commit changes the `synchronized` usage into a `ReentrantLock`, in
order to guard write operations with a construct that does not pin
virtual threads to the current platform thread on JDK21.

Closes gh-30996
2023-08-04 14:59:15 +02:00
Sam Brannen 9908967954 Merge branch '6.0.x' 2023-08-04 15:55:59 +03:00
Sam Brannen 169392e132 Polish StringHttpMessageConverterTests 2023-08-04 15:53:37 +03:00
Sam Brannen c050642290 Polish contribution
See gh-30942
2023-08-04 15:50:07 +03:00
Patrick Strawderman 7636eecb48 Use readNBytes in StringHttpMessageConverter when contentLength is available
When the content length is known, use readNBytes on the InputStream in
StringHttpMessageConverter, which avoids some extra copying and allocations.

Closes gh-30942
2023-08-04 15:43:10 +03:00
Sam Brannen 5fd3456f1e Merge branch '6.0.x' 2023-08-04 15:42:25 +03:00
Sam Brannen d890827bae Fisk asterisk formatting in Asciidoc 2023-08-04 15:41:39 +03:00
Sam Brannen 3758e5155c Merge branch '6.0.x' 2023-08-04 15:35:16 +03:00
xumengqi 07a1aea9c7 Skip array sort when the length of array not greater than 1
Closes gh-30934
2023-08-04 15:25:46 +03:00
Sam Brannen 376f13f8ef Update copyright headers 2023-08-04 15:02:41 +03:00
Sam Brannen 04cce0bafd Support custom properties file formats in @TestPropertySource
Spring Framework 4.3 introduced the `PropertySourceFactory` SPI for use
with `@PropertySource` on `@Configuration` classes; however, prior to
this commit there was no mechanism to support custom properties file
formats in `@TestPropertySource` for integration tests.

This commit introduces support for configuring a custom
`PropertySourceFactory` via a new `factory` attribute in
`@TestPropertySource` in order to support custom file formats such as
JSON, YAML, etc.

For example, if you create a YamlPropertySourceFactory, you can use it
in integration tests as follows.

@SpringJUnitConfig
@TestPropertySource(locations = "/test.yaml", factory = YamlPropertySourceFactory.class)
class MyTestClass { /* ... /* }

If a custom factory is not specified, traditional `*.properties` and
`*.xml` based `java.util.Properties` file formats are supported, which
was the existing behavior.

Closes gh-30981
2023-08-04 14:57:22 +03:00
Sam Brannen b80872b762 Polishing 2023-08-04 13:52:14 +03:00
Sébastien Deleuze 8feb8198fe Merge branch '6.0.x' 2023-08-04 11:30:29 +02:00
Sébastien Deleuze da7b68a643 Support Kotlin Serialization custom serializers
This commit updates WebMVC converters and WebFlux
encoders/decoders to support custom serializers
with Kotlin Serialization when specified via
a custom SerialFormat.

It also turns the serializers cache to a non-static
field in order to allow per converter/encoder/decoder
configuration.

Closes gh-30870
2023-08-04 11:25:40 +02:00
Brian Clozel c97def0b98 Merge branch '6.0.x' 2023-08-04 10:32:00 +02:00
Brian Clozel e83793ba7f Batch SSE events writes when possible
Prior to this commit, the `SseEventBuilder` would be used to create SSE
events and write them to the connection using the `ResponseBodyEmitter`.
This would send each data item one by one, effectively writing and
flushing to the network for each. Since multiple data lines are prepared
by the `SseEventBuilder`, a typical write of an SSE event performs
multiple flushes operations.

This commit adds a method on `ResponseBodyEmitter` to perform batch
writes (given a `Set<DataWithMediaType>`) and only flush once all
elements of the set have been written.
This also applies in case of early writes, where now all buffered
elements are written then flushed altogether.

Fixes gh-30912
2023-08-04 10:31:43 +02:00
Juergen Hoeller 4e863c5a75 Merge branch '6.0.x' 2023-08-04 02:40:17 +02:00
Juergen Hoeller 18966d048c Consistent equals/hashCode style (and related polishing) 2023-08-04 02:39:31 +02:00
Juergen Hoeller a6ff95a69c Restore restrictive getTypeForFactoryBeanFromAttributes check
See gh-29799
See gh-30987
2023-08-04 00:56:01 +02:00
Juergen Hoeller f7c3e6480a Merge branch '6.0.x'
# Conflicts:
#	spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
2023-08-04 00:49:20 +02:00
Juergen Hoeller 7e6612a920 Sort multiple @Autowired methods on same bean class via ASM
Closes gh-30359
2023-08-04 00:47:18 +02:00
Juergen Hoeller 9333ed22f6 Avoid repeated FactoryBean targetType check
See gh-30987
2023-08-04 00:47:04 +02:00
Juergen Hoeller d868f58e6e Merge branch '6.0.x'
# Conflicts:
#	spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java
2023-08-03 18:11:08 +02:00
Juergen Hoeller 4b6fabbd2f Polishing 2023-08-03 18:10:13 +02:00
Juergen Hoeller cba2b6eaf4 Check FactoryBean targetType for generic type as well
Closes gh-30987
2023-08-03 18:10:07 +02:00
Juergen Hoeller 84b3335e71 Apply array editor to collection of same element type as well
Closes gh-24845
2023-08-03 17:55:54 +02:00
Juergen Hoeller c3e18bc173 Retain metadata during bean creation even with cacheBeanMetadata=false
Closes gh-23795
Closes gh-25749
2023-08-03 17:55:47 +02:00
Sébastien Deleuze c942c04aa0 Support resource bundle custom file extensions
This commit allows to configure custom file
extensions in ReloadableResourceBundleMessageSource
thanks to a new setFileExtensions setter.

Combined with setPropertiesPersister, it allows
custom implementations supporting any kind of
property file.

Closes gh-18990
2023-08-03 14:29:29 +02:00
rstoyanchev ad80b94e14 Allow BindParam on a field
See gh-30947
2023-08-03 15:11:08 +03:00
Sam Brannen 34747baed0 Fix broken links to AOT sections 2023-08-03 11:27:16 +03:00
rstoyanchev 8513ec7440 Update documentation for data binding improvements
Closes gh-30952
2023-08-02 17:21:33 +03:00
Sam Brannen 7c5b2db5bf Suppress warnings in tests 2023-08-02 11:09:56 +03:00
Sam Brannen 2e07a72119 Delete duplicate DummyFactory 2023-08-02 11:09:15 +03:00
Sam Brannen 9ba5622efd Update outdated Javadoc for PathPatternParser.defaultInstance
Spring Framework 6.0 changed the default value of
matchOptionalTrailingSeparator from true to false.

Closes gh-30976
2023-08-02 10:35:00 +03:00
Sam Brannen 3ff81a47c9 Polish PathPatternParser 2023-08-02 10:33:34 +03:00
Sam Brannen dcec61ab7a Remove obsolete dependency on picocli
The dependency on picocli was removed from the code in commit 019785a72e.

This commit removes the dependency management from the build.

See gh-28825
2023-08-02 09:54:32 +03:00
Philippe Marschall 4922e0e439 Give spring-core access to org.jboss.vfs for VfsUtils support on WildFly
This commit gives spring-core access to the org.jboss.vfs module to make
VfsUtils work out of the box on WildFly 28+.

Closes gh-30973
2023-08-02 09:45:28 +03:00
Juergen Hoeller 7adacd5ce5 Upgrade to Netty 4.1.96 2023-08-02 01:34:18 +02:00
Juergen Hoeller 08d89f7aac Avoid Aalto XML parser override 2023-08-02 01:32:29 +02:00
Juergen Hoeller d250a5155a Consistent dependency declarations 2023-08-02 00:56:50 +02:00
Juergen Hoeller 52176edcbf Polishing 2023-08-02 00:06:49 +02:00
Juergen Hoeller ae279eaced Polishing 2023-08-01 23:52:48 +02:00
Juergen Hoeller 18e72d5c01 Always use given fallback producer in case of TypeBootstrapContext
Closes gh-30924
2023-08-01 23:52:33 +02:00
Sam Brannen 148f5c459e Update copyright headers 2023-08-01 14:54:09 +03:00
Rossen Stoyanchev 667eb42a63 Polishing
See gh-30952
2023-08-01 07:50:06 +03:00
Sam Brannen bd23798323 Polish Javadoc for PropertySourceDescriptor 2023-08-03 14:33:53 +03:00
Sam Brannen 961084dfe0 Merge branch '6.0.x' 2023-08-03 11:27:37 +03:00
Sam Brannen 3e5aa8d734 Fail on error by default during test AOT processing
Prior to this commit, if an error was encountered during build-time AOT
processing, the error was logged at WARN/DEBUG level, and processing
continued.

With this commit, test AOT processing now fails on error by default. In
addition, the `failOnError` mode can be disabled by setting the
`spring.test.aot.processing.failOnError` Spring/System property to
`false`.

Closes gh-30977
2023-08-03 10:59:46 +03:00
Sam Brannen 1bfcaecc9b Polishing 2023-08-03 10:42:34 +03:00
Stephane Nicoll eed14214b5 Document 'preferredConstructors' attribute escape hatch with AOT
See gh-30917
2023-08-02 16:40:13 +02:00
Sam Brannen 4b7d1e3a2c Delete duplicate DummyFactory 2023-08-02 11:29:15 +03:00
Sam Brannen 08a99e275e Merge branch '6.0.x' 2023-08-02 11:26:43 +03:00
Sam Brannen 44d14811d3 Suppress deprecation warnings in test fixtures 2023-08-02 10:51:03 +03:00
Sam Brannen 900ee11f3b Merge branch '6.0.x' 2023-08-02 10:35:54 +03:00
Sam Brannen 89b85c81a7 Polishing 2023-08-02 10:21:06 +03:00
Sam Brannen 51aaaae94e Merge branch '6.0.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
2023-08-02 09:56:47 +03:00
Sam Brannen aa10d23de4 Merge branch '6.0.x' 2023-08-02 09:48:42 +03:00
Juergen Hoeller 10610a6f54 Merge branch '6.0.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
2023-08-02 01:42:27 +02:00
Juergen Hoeller 5e26786bab Fix malformed javadoc 2023-08-02 01:13:27 +02:00
Juergen Hoeller 3b1af692cc Merge branch '6.0.x'
# Conflicts:
#	spring-beans/spring-beans.gradle
#	spring-context/spring-context.gradle
#	spring-orm/spring-orm.gradle
#	spring-test/spring-test.gradle
#	spring-web/spring-web.gradle
#	spring-webflux/spring-webflux.gradle
2023-08-02 01:04:31 +02:00
Juergen Hoeller b9ae996dfc Merge branch '6.0.x'
# Conflicts:
#	spring-context/spring-context.gradle
#	spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java
#	spring-context/src/test/java/org/springframework/scheduling/annotation/EnableSchedulingTests.java
#	spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java
#	spring-test/spring-test.gradle
#	spring-webmvc/spring-webmvc.gradle
2023-08-02 00:16:55 +02:00
Juergen Hoeller 2d50b758c4 Deprecate applyBeanPostProcessorsBefore/AfterInitialization
Closes gh-30974
2023-08-01 23:28:06 +02:00
Juergen Hoeller 450cc212a2 Support for transactional listeners with reactive transactions
TransactionalApplicationListener and TransactionalEventListener automatically detect a reactive TransactionContext as the event source and register the synchronization accordingly. TransactionalEventPublisher is a convenient delegate for publishing corresponding events with the current TransactionContext as event source. This can also serve as a guideline for similar reactive event purposes.

Closes gh-27515
Closes gh-21025
Closes gh-30244
2023-08-01 23:27:38 +02:00
Juergen Hoeller a9d100eeee Support for always executing specific listeners in original thread
See gh-30244
2023-08-01 23:26:35 +02:00
Sam Brannen dde8f4489f Polish MappedInterceptor 2023-08-01 16:19:26 +03:00
Sam Brannen f9f7a7cd78 Polish contribution
See gh-30971
2023-08-01 16:19:26 +03:00
graceyu 6de95a2b37 Provide methods for obtaining include/exclude patterns in MappedInterceptor
Prior to this commit, MappedInterceptor had a getPathPatterns() method
that returned the include patterns.

This commit introduces getIncludePathPatterns() (which effectively
replaces getPathPatterns()) and getExcludePathPatterns(). In addition,
this commit deprecates getPathPatterns().

Closes gh-30971
2023-08-01 15:57:43 +03:00
Sam Brannen f00756bc7c Update copyright headers 2023-08-01 14:55:04 +03:00
Sam Brannen b00d120514 Merge branch '6.0.x' 2023-08-01 14:54:41 +03:00
Sam Brannen 2dc4eea62f Remove native image hints for TransactionDefinition constants
Closes gh-30854
2023-08-01 14:46:07 +03:00
Sam Brannen db8fa4d505 Polish DataSize 2023-08-01 11:20:40 +03:00
Sam Brannen 525621c4d8 Polish contribution
See gh-30710
2023-08-01 11:19:54 +03:00
Patrick Strawderman 01e90bbd0e Use Long.parseLong(CharSequence,...) to avoid intermediate String creation
Where possible, switch to the Long.parseLong variant that accepts a
start and end index for the supplied CharSequence, thus avoiding making
unnecessary copies of the String input.

Closes gh-30710
2023-08-01 10:53:30 +03:00
Sam Brannen af1c06917d Upgrade to JUnit 5.10
Closes gh-30970
2023-08-01 10:28:50 +03:00
Sam Brannen bcff7d74cd Replace map entry traversal with switch expression
See gh-30851
2023-07-31 16:23:47 +03:00
Sam Brannen 170d6bfdad Clean up warnings in tests 2023-07-31 16:17:48 +03:00
Sam Brannen 2f7046f572 Deprecate org.springframework.core.Constants utility
Closes gh-30851
2023-07-31 16:08:47 +03:00
Sam Brannen 3b8dd0a5ac Assert JmsAccessor.setSessionAcknowledgeMode() values
See gh-30851
2023-07-31 16:08:47 +03:00
Sam Brannen 9da318af96 Assert JmsActivationSpecConfig.setAcknowledgeMode() values
See gh-30851
2023-07-31 16:08:47 +03:00
Sam Brannen b45bfcafc2 Assert DefaultMessageListenerContainer.setCacheLevel() values
See gh-30851
2023-07-31 16:08:47 +03:00
Sam Brannen 81181c346a Assert SimpleTriggerFactoryBean.setMisfireInstruction() values
See gh-30851
2023-07-31 16:08:47 +03:00
Sam Brannen 1378cce9fb Assert CronTriggerFactoryBean.setMisfireInstruction() values
See gh-30851
2023-07-31 16:08:47 +03:00
Sam Brannen 12f765c133 Assert XmlBeanDefinitionReader.setValidationMode() values
See gh-30851
2023-07-31 16:08:47 +03:00
Sam Brannen 06c6af9b0d Stop using Constants utility in IsolationLevelDataSourceRouter
See gh-30851
2023-07-31 16:08:47 +03:00
Sam Brannen 181c814e69 Polish IsolationLevelDataSourceRouter 2023-07-31 16:08:47 +03:00
Sam Brannen 0eda44186a Polish tests for configuration constants
See gh-30851
2023-07-31 16:08:47 +03:00
Sam Brannen 48eb477755 Assert LazyConnectionDataSourceProxy.setDefaultTransactionIsolation() values
See gh-30851
2023-07-31 15:11:52 +03:00
rstoyanchev c43d2e2edc Polishing
Closes gh-30959
2023-07-31 14:52:58 +03:00
Olga MaciaszekSharma 0d4010841e Update docs for HTTP interface clients return values
See gh-30959
2023-07-31 14:52:58 +03:00
Sam Brannen cc9278666d Stop using Constants utility in LazyConnectionDataSourceProxy
See gh-30851
2023-07-31 13:56:49 +03:00
Sam Brannen c87925cee7 Polish LazyConnectionDataSourceProxy 2023-07-31 13:56:49 +03:00
rstoyanchev 5b6c127283 Polishing
Closes gh-30936
2023-07-28 12:46:58 +03:00
Olga MaciaszekSharma 4cd9e2e9b0 Support @RSocketExchange for annotated responders
See gh-30936
2023-07-28 04:23:00 +03:00
Juergen Hoeller 376223c87d Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/core/task/SimpleAsyncTaskExecutor.java
2023-07-27 21:48:42 +02:00
Juergen Hoeller abbea39855 Polishing 2023-07-27 21:47:54 +02:00
Juergen Hoeller ce80637891 Add option for graceful shutdown (setTaskTerminationTimeout)
See gh-30956
2023-07-27 21:39:58 +02:00
rstoyanchev 78d0dbb519 Ensure handling of 404 errors for static resources
Closes gh-30930
2023-07-27 22:13:10 +03:00
Rossen Stoyanchev 85704c890e Use DispatchExceptionHandler for handler errors
See gh-30930
2023-07-27 22:13:10 +03:00
Juergen Hoeller 7681200ee7 Introduce SimpleAsyncTaskScheduler (extending SimpleAsyncTaskExecutor)
Closes gh-30956
2023-07-26 23:56:59 +02:00
Juergen Hoeller 5e4ed68fdd Merge branch '6.0.x'
# Conflicts:
#	framework-docs/modules/ROOT/pages/data-access/jdbc/core.adoc
2023-07-26 14:16:43 +02:00
Juergen Hoeller 6fd40a8f60 Upgrade to Caffeine 3.1.7 and H2 2.2.220 2023-07-26 14:15:58 +02:00
Juergen Hoeller 333249e7b0 Polishing 2023-07-26 14:07:08 +02:00
Juergen Hoeller 49c4b205e4 Documentation for common JdbcClient query/update usage
See gh-30931
2023-07-26 13:47:52 +02:00
Juergen Hoeller cf1ba98d01 Documentation for Validator invocation via validateObject
See gh-19877
2023-07-26 13:09:26 +02:00
Juergen Hoeller cb4222d2c2 Documentation for caching with CompletableFuture and reactive types
See gh-17559
See gh-17920
2023-07-26 13:07:22 +02:00
Juergen Hoeller 3437e61f98 Merge branch '6.0.x' 2023-07-26 12:08:20 +02:00
Juergen Hoeller 2573ba4a50 Polishing 2023-07-26 12:07:11 +02:00
Juergen Hoeller bbde68c49e Polishing 2023-07-25 19:12:07 +02:00
rstoyanchev 67e3d86bd8 Support declarativeBinding mode in DataBinder
Closes gh-30948
2023-07-25 18:04:21 +03:00
rstoyanchev 37eaded63d Support BindParam annotation
Allows customizing the name of the request parameter to bind a
constructor parameter to.

Closes gh-30947
2023-07-25 16:15:55 +03:00
Juergen Hoeller ccaccda6ca Polishing 2023-07-25 19:22:02 +02:00
Juergen Hoeller 5ebbb3ff3e Merge branch '6.0.x'
# Conflicts:
#	spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcOperations.java
#	spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java
#	spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java
2023-07-25 19:13:33 +02:00
Juergen Hoeller 3c02ab83ed Polishing 2023-07-25 18:11:00 +02:00
Juergen Hoeller 021161ea38 Make bean property method accessible as well (for non-public types)
See gh-19877
2023-07-25 18:10:43 +02:00
Juergen Hoeller 019c34f480 Introduce JdbcClient as a fluent facade for query/update execution
Delegates to JdbcTemplate/NamedParameterJdbcTemplate underneath the covers.
Supports parameter objects/records through SimplePropertySqlParameterSource.

Closes gh-30931
2023-07-25 18:10:30 +02:00
Juergen Hoeller b9ba0fc572 Polishing 2023-07-24 11:26:48 +02:00
Juergen Hoeller 4a319c3c33 Merge branch '6.0.x' 2023-07-24 11:23:04 +02:00
Juergen Hoeller fdf1418dfb Polishing 2023-07-24 11:21:13 +02:00
Juergen Hoeller 5bcf5c6f7c Clarify DataAccessException/ScriptException declarations for R2DBC
Closes gh-30932
2023-07-24 11:21:07 +02:00
Arjen Poutsma 52c77d89e9 Reverse order of RestClient and RestTemplate adapters in HTTP interface section 2023-07-24 09:46:05 +02:00
Juergen Hoeller 4786e2bf53 Introduce PREFERRED_CONSTRUCTORS_ATTRIBUTE on AbstractBeanDefinition
Closes gh-30917
2023-07-22 16:06:14 +02:00
Juergen Hoeller b53034fe62 Merge branch '6.0.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
2023-07-22 00:33:12 +02:00
Juergen Hoeller 87d4afda81 Upgrade to Netty 4.1.95 2023-07-22 00:31:19 +02:00
Juergen Hoeller 3a9e0ea8a7 Polishing 2023-07-22 00:31:09 +02:00
Juergen Hoeller ba46d2bf21 Polishing 2023-07-21 23:57:20 +02:00
Juergen Hoeller 27f9473422 Merge branch '6.0.x'
# Conflicts:
#	spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java
2023-07-21 20:42:56 +02:00
Juergen Hoeller 4ce1ac0dcb Polishing 2023-07-21 20:36:43 +02:00
Juergen Hoeller f99faac073 Add caching annotation support for CompletableFuture and reactive return values
Includes CompletableFuture-based retrieve operations on Spring's Cache interface.
Includes support for retrieve operations on CaffeineCache and ConcurrentMapCache.
Includes async cache mode option on CaffeineCacheManager.

Closes gh-17559
Closes gh-17920
Closes gh-30122
2023-07-21 20:27:23 +02:00
Arjen Poutsma d65d285378 Cleanup after deprecation of OkHttp3ClientHttpRequestFactory
See gh-30919
2023-07-21 10:07:05 +02:00
Arjen Poutsma efb6abc43f Deprecate OkHttp3ClientHttpRequestFactory
Closes gh-30919
2023-07-20 13:48:52 +02:00
Juergen Hoeller 3d57425dcb Return rejected value from getFieldValue in case of error
See gh-19877
2023-07-19 23:08:42 +02:00
Juergen Hoeller d4caaebab0 Merge branch '6.0.x'
# Conflicts:
#	spring-context/src/main/java/org/springframework/validation/Errors.java
#	spring-context/src/test/java/org/springframework/validation/DataBinderTests.java
2023-07-19 23:01:02 +02:00
Juergen Hoeller 8cc6dd629a Polishing 2023-07-19 22:58:27 +02:00
Juergen Hoeller 391d7f2c6a Polishing 2023-07-19 22:47:20 +02:00
Juergen Hoeller 10cb2322e9 Introduce Validator.validateObject(Object) with returned Errors
Includes failOnError method on Errors interface for use with validateObject.
Declares many Errors methods as default methods for lean SimpleErrors class.

Closes gh-19877
2023-07-19 21:56:44 +02:00
Sam Brannen 9571aa1c68 Stop using Constants utility in IsolationLevelDataSourceAdapter
See gh-30851
2023-07-19 18:05:41 +03:00
Sam Brannen 97810c84a2 Stop using Constants utility in AbstractPlatformTransactionManager
See gh-30851
2023-07-19 17:29:36 +03:00
Sam Brannen d0076f5c14 Stop using Constants utility in DefaultTransactionDefinition
See gh-30851
2023-07-19 16:35:15 +03:00
Sam Brannen c110644107 Polish TransactionSupportTests 2023-07-19 14:33:40 +03:00
Sam Brannen 05956d4028 Change MvcSimpleAsyncTaskExecutor.taskExecutorWarning to primitive boolean 2023-07-19 13:21:57 +03:00
Sam Brannen b2ca36f098 Stop using Constants utility in JmsAccessor
See gh-30851
2023-07-19 12:16:26 +03:00
Sam Brannen 15253f3448 Polish JmsAccessor[Tests] 2023-07-19 12:16:14 +03:00
Sam Brannen 4e00c988c1 Stop using Constants utility in JmsActivationSpecConfig
See gh-30851
2023-07-19 11:48:28 +03:00
Brian Clozel c88c9620b3 Upgrade to Java 21 EA 31 in CI build 2023-07-19 09:51:28 +02:00
Juergen Hoeller 2ac55659c8 Merge branch '6.0.x' 2023-07-19 01:26:05 +02:00
Juergen Hoeller c64a322e19 Polishing 2023-07-19 01:25:20 +02:00
Juergen Hoeller 25ea1f4c0f Merge branch '6.0.x'
# Conflicts:
#	spring-context/src/main/java/org/springframework/scheduling/support/CronSequenceGenerator.java
2023-07-19 00:37:06 +02:00
Juergen Hoeller 2f33e77ab4 Consistent equals/hashCode style (and related polishing) 2023-07-19 00:35:19 +02:00
Juergen Hoeller 33862d98ea Merge branch '6.0.x' 2023-07-18 22:03:03 +02:00
Juergen Hoeller bbcc788f60 Decouple exception messages for sync=true from @Cacheable 2023-07-18 22:02:09 +02:00
Juergen Hoeller 038dda97f8 Document EntityManager injection via constructors/@Autowired
Closes gh-15076
2023-07-18 22:01:57 +02:00
Juergen Hoeller c504ac5a47 Merge branch '6.0.x' 2023-07-18 12:57:18 +02:00
Juergen Hoeller 1ac0549881 Polishing 2023-07-18 12:55:32 +02:00
Juergen Hoeller 616f728afa MethodIntrospector handles overriding bridge method correctly
Closes gh-30906
2023-07-18 12:54:59 +02:00
rstoyanchev 73c06347be Update WebMvc docs on use of AsyncTaskExecutor
Closes gh-30905
2023-07-18 10:42:27 +01:00
rstoyanchev 4becce1c2b Consolidate default WebMvc executor log warnings
Closes gh-30902
2023-07-18 10:22:45 +01:00
Juergen Hoeller 161a717639 Avoid synchronization for shortcut re-resolution
See gh-30883
2023-07-16 16:22:17 +02:00
Sam Brannen 28e63e9279 Polishing 2023-07-16 14:35:22 +02:00
Sam Brannen 11de70ed08 Update Javadoc for SimpleTriggerFactoryBean.setMisfireInstructionName()
org.quartz.Trigger#MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY is also
supported.
2023-07-16 14:34:42 +02:00
Sam Brannen 9283fd2162 Update Javadoc for CronTriggerFactoryBean.setMisfireInstructionName()
org.quartz.Trigger#MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY is also
supported.
2023-07-16 14:05:24 +02:00
Sam Brannen 544f594592 Update copyright headers 2023-07-15 18:23:37 +02:00
jongwooo c21a8aa8b0 Wrap ternary operator within parentheses as outlined in Code Style
Closes gh-30358
2023-07-15 18:04:01 +02:00
Sam Brannen 30d6ec3398 Update copyright headers 2023-07-15 16:01:15 +02:00
Johnny Lim ab83972c3e Add missing @Nullable annotations in AbstractResourceResolver subclasses
See gh-30601
Closes gh-30893
2023-07-15 16:00:32 +02:00
Sam Brannen 9e3f3bee71 Consistently throw TestContextAotException in TestContextAotGenerator
See gh-30898
2023-07-15 14:55:26 +02:00
Sam Brannen 2ba9939bd8 Revise changes to DefaultGenerationContext and GeneratedClasses
In order to reduce the surface area of published APIs in the affected
classes, this commit:

- Reverts the changes made to GeneratedClasses in c354b1014d.

- Reverts the changes made to DefaultGenerationContext in a28ec3a0a8.

- Makes the DefaultGenerationContext(DefaultGenerationContext, String)
  constructor protected.

- Reworks the internals of TestContextGenerationContext to align with
  the above changes.

See gh-30861
Closes gh-30895
Closes gh-30897
2023-07-15 14:43:39 +02:00
Juergen Hoeller 3a278cc66d Polishing 2023-07-15 14:20:00 +02:00
Juergen Hoeller 6183f06846 Cache DependencyDescriptor per autowired constructor argument
Aligned with shortcut handling in AutowiredAnnotationBeanPostProcessor.
Includes minor MethodInvoker optimization for pre-resolved targetClass.

Closes gh-30883
2023-07-15 14:17:52 +02:00
Sam Brannen a34f9fa66c Update copyright headers 2023-07-15 13:10:46 +02:00
Sam Brannen f5db8bd1e8 Retain existing feature name as prefix in test AOT processing
Prior to this commit, test AOT processing failed if a feature name for
generated class names was used for more than one ApplicationContext.

For example, when generating code for org.example.MessageService with a
"Management" feature name, the "BeanDefinitions" class was named as
follows (without a uniquely identifying TestContext###_ feature name
prefix).

org/example/MessageService__ManagementBeanDefinitions.java

When another attempt was made to generate code for the MessageService
using the same "Management" feature name, a FileAlreadyExistsException
was thrown denoting that the class/file name was already in use.

To avoid such naming collisions, this commit introduces a
TestContextGenerationContext which provides a custom implementation of
withName(String) that prepends an existing feature name (if present) to
a new feature name, thereby treating any existing feature name as a
prefix to a new, nested feature name.

Consequently, code generation for the above example now results in
unique class/file names like the following (which retain the uniquely
identifying TestContext###_ prefixes).

org/example/MessageService__TestContext002_ManagementBeanDefinitions.java
org/example/MessageService__TestContext003_ManagementBeanDefinitions.java

Closes gh-30861
2023-07-15 12:02:11 +02:00
Sam Brannen 317c6fbec2 Introduce failOnError flag in TestContextAotGenerator
This commit introduces a `failOnError` flag in TestContextAotGenerator.
When set to `true`, any error encountered during AOT processing will
result in an exception that fails the overall process. When set to
`false` (the default), the previous behavior remains unchanged: a DEBUG
or WARN message will be logged, and processing will continue.

This feature is currently only used for internal testing.

See gh-30861
Closes gh-30898
2023-07-15 12:02:04 +02:00
Sam Brannen c354b1014d Make GeneratedClasses#withFeatureNamePrefix(String) public
See gh-30861
Closes gh-30897
2023-07-15 12:01:56 +02:00
Sam Brannen a28ec3a0a8 Make DefaultGenerationContext(<classes>,<files>,<hints>) constructor protected
See gh-30861
Closes gh-30895
2023-07-15 12:01:49 +02:00
Juergen Hoeller 6ad647d7ce Explicit hints for @PostConstruct methods (preventing deadlocks)
Closes gh-25074
2023-07-14 16:43:23 +02:00
rstoyanchev 8a283e39ff Update DefaultHandlerExceptionResolver logging
Reduce logging for NoResourceFoundException and NoHandlerFoundException.

Closes gh-30884
2023-07-14 15:11:19 +01:00
Juergen Hoeller 0d8a8432d1 Upgrade to ASM master (including early support for Java 22 bytecode)
Closes gh-30845
2023-07-17 21:17:15 +02:00
Sam Brannen 3a8b5111d9 Stop using Constants utility in DefaultMessageListenerContainer
See gh-30851
2023-07-16 19:14:09 +02:00
Sam Brannen b375a061df Polish DefaultMessageListenerContainer[Tests] 2023-07-16 19:13:27 +02:00
Juergen Hoeller 0e9cd2a35f Merge branch '6.0.x' 2023-07-16 16:23:15 +02:00
Sam Brannen d6230824cb Stop using Constants utility in SimpleTriggerFactoryBean
See gh-30851
2023-07-16 15:00:11 +02:00
Sam Brannen edba535c8b Stop using Constants utility in CronTriggerFactoryBean
See gh-30851
2023-07-16 15:00:11 +02:00
Sam Brannen 79cf532c2f Merge branch '6.0.x' 2023-07-16 14:36:09 +02:00
Sam Brannen f6b8ee76cd Merge branch '6.0.x' 2023-07-16 14:05:46 +02:00
Sam Brannen 635cd29599 Remove cross reference to Constants utility
See gh-30851
2023-07-16 13:50:26 +02:00
Sam Brannen 6f733512b5 Stop using Constants utility in XmlBeanDefinitionReader
See gh-30851
2023-07-16 13:29:44 +02:00
Sam Brannen d6e05ddf2d Polish XmlBeanDefinitionReaderTests 2023-07-16 13:22:48 +02:00
Sam Brannen a92bd42236 Stop using Constants utility in PropertyPlaceholderConfigurer
See gh-30851
2023-07-16 12:56:03 +02:00
Sam Brannen cebda46469 Polish PropertyPlaceholderConfigurerTests 2023-07-16 12:56:03 +02:00
Sam Brannen f01fb19318 Stop using Constants utility in CustomizableTraceInterceptor
See gh-30851
2023-07-16 12:56:03 +02:00
Sam Brannen 5e31856aaa Polish CustomizableTraceInterceptor[Tests] 2023-07-16 12:12:10 +02:00
Sam Brannen 1058fed339 Merge branch '6.0.x' 2023-07-15 18:24:00 +02:00
Sam Brannen bcd09d7ad8 Merge branch '6.0.x' 2023-07-15 16:01:47 +02:00
Sam Brannen abc56cde3d Merge branch '6.0.x' 2023-07-15 14:56:47 +02:00
Sam Brannen 889fca98ac Merge branch '6.0.x' 2023-07-15 14:45:52 +02:00
Juergen Hoeller 351a200747 Merge branch '6.0.x' 2023-07-15 14:21:05 +02:00
Sam Brannen 01ceee8de5 Polishing 2023-07-15 13:36:11 +02:00
Sam Brannen 0611192dac Enable KotlinScriptTemplateTests in Spring MVC on Java 20
See gh-29249
Closes gh-30896
2023-07-15 13:36:11 +02:00
Johnny Lim be8bfad3af Enable KotlinScriptTemplateTests in Spring WebFlux on Java 20
See gh-29249
Closes gh-30896
2023-07-15 13:35:59 +02:00
Sam Brannen 63fe45d92a Update copyright headers 2023-07-15 13:11:29 +02:00
Sam Brannen 5ce8ffd197 Merge branch '6.0.x' 2023-07-15 13:11:03 +02:00
Sam Brannen 56c7b4065d Merge branch '6.0.x' 2023-07-15 13:09:12 +02:00
Sam Brannen 680769d770 Remove obsolete private constant 2023-07-15 13:04:50 +02:00
Sam Brannen 70cf754a2f Suppress warnings in tests 2023-07-15 13:02:16 +02:00
Sam Brannen e6d360c1c6 Polishing 2023-07-15 12:58:18 +02:00
Sam Brannen 8629182822 Suppress deprecation warnings in tests 2023-07-15 12:16:38 +02:00
Juergen Hoeller 37ac3d8764 Merge branch '6.0.x' 2023-07-14 16:44:26 +02:00
Stephane Nicoll d61b9c6294 Merge pull request #22769 from lgxbslgx
* pr/22769:
  Polish "Evaluate key only if necessary"
  Evaluate key only if necessary

Closes gh-22769
2023-07-14 14:43:18 +02:00
Stephane Nicoll d8854a2f3f Polish "Evaluate key only if necessary"
See gh-22769
2023-07-14 14:43:04 +02:00
liguoxiong 806c83591c Evaluate key only if necessary
Prior to this commit a @CachePut operation would fail if the key
expression is invalid, but guarded with an unless condition as the
former was evaluated too early. This commit makes sure that key for
a put is only evaluated if the put operation is active.

Note that this does not apply for @Cacheable as the key needs to be
computed early to determine if a matching entry exists in the cache.

See gh-22769
2023-07-14 14:43:04 +02:00
Juergen Hoeller fd17df91fd Merge branch '6.0.x'
# Conflicts:
#	spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java
2023-07-14 14:38:24 +02:00
Juergen Hoeller 384246c360 Polishing 2023-07-14 14:37:34 +02:00
Juergen Hoeller e30391661d Document repeatable annotation semantics for @Scheduled
Closes gh-23959
2023-07-14 14:37:28 +02:00
Juergen Hoeller 519927421e Add support for configurable custom translator
Closes gh-24634
2023-07-14 14:17:20 +02:00
Juergen Hoeller 52c19272c6 Deprecate MBeanExporter's AUTODETECT constants
Closes gh-30874
2023-07-14 14:12:39 +02:00
Juergen Hoeller 0d5a7db238 Remove unused import
See gh-30886
2023-07-14 12:24:55 +02:00
Juergen Hoeller 064cd3b7af Merge branch '6.0.x'
# Conflicts:
#	gradle.properties
#	spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java
2023-07-14 12:18:41 +02:00
Juergen Hoeller 75f5dac16b Polishing 2023-07-14 12:16:37 +02:00
Juergen Hoeller 6957ac5324 Trigger late commit in JmsResourceSynchronization.afterCompletion if necessary
Closes gh-20817
2023-07-14 11:50:31 +02:00
Juergen Hoeller d24c131130 Expose convert(Object, TypeDescriptor) in ConversionService interface
Closes gh-25394
2023-07-14 11:49:26 +02:00
Juergen Hoeller 0ab94478fe Add since tags and code style refinements
See gh-27735
2023-07-14 11:48:37 +02:00
René Wittner 4b80b0f490 DataAccessUtils result accessors with Optional return value (#27735) 2023-07-14 11:37:09 +02:00
rstoyanchev 793581ebde Add ForwardedHeaderUtils
Closes gh-30886
2023-07-13 18:12:30 +01:00
Brian Clozel cc7f3101b7 Upgrade to Context Propagation 1.1.0-M3
Closes gh-30882
2023-07-13 11:21:30 +02:00
Spring Builds bddd3feb83 Next development version (v6.0.12-SNAPSHOT) 2023-07-13 08:37:04 +00:00
Arjen Poutsma 49c463b1d2 Polish RestClient request factories
This commit changes the default request factory from the
SimpleClientHttpRequestFactory to the JdkClientHttpRequestFactory if
available. It also adds detection logic for OkHttp and Jetty.
2023-07-13 09:24:21 +02:00
Juergen Hoeller 094eb3e236 Use varargs for array elements
See gh-1850
2023-07-13 00:55:35 +02:00
Juergen Hoeller 3fed2ec3a1 Add common SqlValue implementation for JDBC Array creation
Closes gh-1850
2023-07-13 00:28:32 +02:00
Juergen Hoeller 357d5b4e6e Merge branch '6.0.x' 2023-07-12 19:23:26 +02:00
Juergen Hoeller c873a597c7 Polishing 2023-07-12 19:21:44 +02:00
Juergen Hoeller 4152034799 Move transaction configuration check to transaction.annotation package
AbstractTransactionManagementConfiguration.transactionalEventListenerFactory() creating a RestrictedTransactionalEventListenerFactory now.

See gh-30679
2023-07-12 19:09:48 +02:00
rstoyanchev 3c9cfa8a0f Revise order of method declarations in WebFluxConfigurer
See gh-30678
2023-07-12 17:09:57 +01:00
rstoyanchev b016f385e1 Add BlockingExecutionConfigurer to WebFlux config
Closes gh-30678
2023-07-12 16:55:02 +01:00
Stephane Nicoll f40d1f2329 Merge branch '6.0.x' 2023-07-12 17:23:22 +02:00
Stephane Nicoll 4dc93bc485 Avoid ambiguous call with BeanInstanceSupplier#withGenerator
Previously, BeanInstanceSupplier had three variants of the
`withGenerator` callback, one with a bi function, one with a function,
and with a supplier. This could lead to compilation failure when the
target type has a method with the same name and a number of arguments
that match another variant.

It turns out the supplier-based variant is only used a shortcut. This
commit deprecates it and update ghe code generation to use the function
instead.

Closes gh-29278
2023-07-12 17:23:08 +02:00
Stephane Nicoll f73f1e0687 Merge branch '6.0.x' 2023-07-12 17:22:44 +02:00
Stephane Nicoll 1b09ef5051 Avoid ambiguous call with BeanInstanceSupplier#withGenerator
Previously, BeanInstanceSupplier had three variants of the
`withGenerator` callback, one with a bi function, one with a function,
and with a supplier. This could lead to compilation failure when the
target type has a method with the same name and a number of arguments
that match another variant.

It turns out the supplier-based variant is only used a shortcut. This
commit deprecates it and update ghe code generation to use the function
instead.

Closes gh-29278
2023-07-12 16:40:22 +02:00
Juergen Hoeller c1932dd307 Support for MultiValueMap elements in bean property paths
Closes gh-26297
2023-07-12 16:23:39 +02:00
Sébastien Deleuze 490ff0af5e Refine the log message printed after restoration
Closes gh-30876
2023-07-12 15:20:33 +02:00
Sam Brannen 16b9640af2 Merge branch '6.0.x' 2023-07-12 11:50:11 +02:00
Sam Brannen 68f2b0ca59 Rely on auto-boxing in tests 2023-07-12 11:49:02 +02:00
Sam Brannen 2e3fbac9a0 Merge branch '6.0.x' 2023-07-12 10:36:21 +02:00
Sam Brannen 1edc0d8002 Remove outdated Javadoc cross references 2023-07-12 10:36:02 +02:00
Sam Brannen 18c11e84f3 Merge branch '6.0.x' 2023-07-12 10:34:43 +02:00
Sam Brannen a6dc020dc4 Remove since tag 2023-07-12 10:33:24 +02:00
Sam Brannen 07422d709e Remove getAutodetectMode() in MBeanExporter
After further consideration, the team has decided to remove the
getAutodetectMode() method since its return type conflicts with the
parameter type in setAutodetectMode(int), making it an invalid bean
property.

See gh-30855
2023-07-12 10:30:38 +02:00
Brian Clozel a2da97bc4c Upgrade to Micrometer 1.12.0-M1
Closes gh-30872
2023-07-12 09:17:09 +02:00
Brian Clozel 2e809903ec Upgrade to Reactor 2023.0.0-M1
Closes gh-30856
2023-07-12 08:56:28 +02:00
Brian Clozel 6075629015 Merge branch '6.0.x' 2023-07-12 08:55:53 +02:00
Brian Clozel 768fc7e341 Upgrade to Reactor 2022.0.9
Closes gh-30871
2023-07-12 08:41:46 +02:00
Juergen Hoeller c20a2e4763 Support for indexing into any Collection/Iterable
Closes gh-907
2023-07-11 23:07:51 +02:00
Juergen Hoeller e048b093b5 ContextClosedEvent triggers early cancelling of scheduled tasks
Closes gh-24629
See gh-27090
2023-07-11 22:11:13 +02:00
rstoyanchev 57ed5bf34b Polishing contribution
Closes gh-30869
2023-07-11 19:13:22 +01:00
Olga MaciaszekSharma 8b77ed164d Add RestClientAdapter
See gh-30869
2023-07-11 19:13:22 +01:00
Sébastien Deleuze 3a8c40fd2f Merge branch '6.0.x' 2023-07-11 19:58:44 +02:00
Johnny Lim 8ecedb81b3 Add missing @Nullable annotations in ContentDisposition.Builder
Closes gh-30820
2023-07-11 19:58:29 +02:00
Juergen Hoeller 3a481a7d7f Merge branch '6.0.x' 2023-07-11 18:02:25 +02:00
Juergen Hoeller f19433f2d8 Polishing 2023-07-11 18:01:07 +02:00
Juergen Hoeller 0b02a5e073 Avoid illegal reflective access in ContextOverridingClassLoader
Closes gh-22791
2023-07-11 17:51:55 +02:00
Juergen Hoeller e2b24f3c12 Improve diagnostics for LinkageError in case of ClassLoader mismatch
Closes gh-25940
2023-07-11 17:50:44 +02:00
Juergen Hoeller c375fb1f70 Deprecate setAllowResultAccessAfterCompletion and document it as broken
Closes gh-26557
2023-07-11 17:50:31 +02:00
rstoyanchev 74972fb751 Add updateModel to BindingContext
The method includes logic that is currently in
ViewResolutionResultHandler but fits well in BindingContext and also
includes the call to saveModel method from the InitBinderBindingContext
subclass, which was called too early until now from
RequestMappingHandlerAdapter before the model has been fully updated.

This mirrors a similar method in ModelFactory on the Spring MVC side
which also combines those two tasks.

Closes gh-30821
2023-07-11 16:34:03 +01:00
Sam Brannen 15b6626a4c Merge branch '6.0.x' 2023-07-11 16:36:32 +02:00
Sam Brannen ad3e5425d4 Reduce WARN level log output during test AOT processing
Closes gh-30867
2023-07-11 16:35:07 +02:00
rstoyanchev c61d011076 Support RestClient in MockRestServiceServer
Closes gh-30821
2023-07-11 14:46:02 +01:00
Sam Brannen 8448f597b1 Merge branch '6.0.x' 2023-07-11 15:41:51 +02:00
Sam Brannen c418118683 Polishing 2023-07-11 15:37:55 +02:00
Sam Brannen fb3f30832c Delete obsolete constant in AnnotationConfigUtils
See gh-30695
2023-07-11 15:33:28 +02:00
Sébastien Deleuze 950c43b4e7 Merge branch '6.0.x' 2023-07-11 14:07:34 +02:00
Sébastien Deleuze a275d942d2 Update STOMP documentation with the new guidelines
This commit changes the documentation to advise using
https://github.com/stomp-js/stompjs library on client
side and to configure by default WebSocket without
SockJS as browsers and proxies now have a pretty good
WebSocket support.

Closes gh-30857
2023-07-11 14:07:15 +02:00
rstoyanchev 39e74d89e1 Merge branch '6.0.x' 2023-07-11 11:17:41 +01:00
rstoyanchev 20afa3265a Encapsulate full path initialization 2023-07-11 11:10:20 +01:00
Sam Brannen dc4fcef884 Merge branch '6.0.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
2023-07-11 11:08:59 +02:00
Sam Brannen df50c8db3e Upgrade to micrometer-bom 1.10.9 and context-propagation 1.0.4
Closes gh-30860
2023-07-11 10:58:11 +02:00
Arjen Poutsma d04d7b2e57 Add request binding to functional endpoints
This commit introduces form binding to ServerRequest in both WebMVC.fn
and WebFlux.fn's, in the form of a bind(Class) method.

Closes gh-25943
2023-07-11 09:52:39 +02:00
rstoyanchev a3e37597aa Add ReactiveHttpRequestValues
Separate collection and handling of reactive request values into a
subclass of HttpRequestValues.

Closes gh-30117
2023-07-11 07:42:04 +01:00
Sam Brannen 679b668bbb Avoid need for reflection hints for MBeanExporter in native image
Prior to this commit, MBeanExporter used
org.springframework.core.Constants which used reflection to find
constant fields in the MBeanExporter class. Consequently, one had to
register reflection hints in order to use MBeanExporter in a GraalVM
native image.

This commit addresses this by replacing the use of the `Constants`
class with a simple java.util.Map which maps constant names to constant
values for the autodetect constants defined in MBeanExporter.

See gh-30851
Closes gh-30846
2023-07-10 19:01:44 +02:00
Sam Brannen 676daa990b Reorganize methods in MBeanExporter 2023-07-10 18:28:45 +02:00
Sam Brannen 7c7fa69558 Introduce getAutodetectMode() in MBeanExporter
Closes gh-30855
2023-07-10 18:26:33 +02:00
Sam Brannen 9ad92b16b0 Polish MBeanExporterTests 2023-07-10 18:20:39 +02:00
Juergen Hoeller 3b899fe7e2 Handle JDBC warnings in case of a statement exception as well
Closes gh-23106
2023-07-10 17:17:30 +02:00
rstoyanchev 3209cf5c7a Add Reactor classpath checks in argument resolvers
HTTP interface client argument resolvers for RequestBody and
RequestPart now handle reactive input conditionally.

See gh-30117
2023-07-10 16:03:11 +01:00
Rossen Stoyanchev 22376c2efa Polishing
See gh-30117
2023-07-10 11:24:30 +01:00
rstoyanchev 47667ab990 Collapse hierarchy under HttpServiceMethodTests
See gh-30117
2023-07-10 10:56:32 +01:00
Rossen Stoyanchev 068dc7db28 Remove use of TestHttpClientAdapter
Now that HttpClientAdapter is deprecated and replaced by HttpExchangeAdapter
and ReactorHttpExchangeAdapter, our tests should use the new contracts.

See gh-30117
2023-07-10 10:36:16 +01:00
rstoyanchev 3be4c0a893 Replace Void with void on exchange method
See gh-30117
2023-07-10 09:10:14 +01:00
Sébastien Deleuze c91041b675 Improve RSocketClientToServer*IntegrationTests reliability
Those new delays seems to make tests more reliable.

Closes gh-30844
2023-07-09 18:39:50 +02:00
Juergen Hoeller a17cf742b2 Polishing 2023-07-09 16:55:21 +02:00
Juergen Hoeller a102cd5f32 Tolerate isCandidateClass call with null as annotation type
Closes gh-30842
2023-07-09 16:52:54 +02:00
Juergen Hoeller d03b6aa1d6 Reinstate support for legacy JSR-250 Resource annotation
This merges the existing support for the legacy JSR-250 PostConstruct/PreDestroy annotations into CommonAnnotationBeanPostProcessor itself, opening up the InitDestroyAnnotationBeanPostProcessor base class for multiple init/destroy methods in a single post-processor. This removes the need for a separate JSR-250 InitDestroyAnnotationBeanPostProcessor in AnnotationConfigUtils.

Closes gh-30695
2023-07-09 16:52:17 +02:00
Sam Brannen b32b4f3a59 Polish DefaultSingletonBeanRegistryTests 2023-07-09 15:32:20 +02:00
Sam Brannen 502997d8e9 Further simplify DefaultSingletonBeanRegistry.isDependent()
See gh-30839
2023-07-09 15:32:20 +02:00
bnbakp0582 fb4ad2f3ba Simplify DefaultSingletonBeanRegistry.isDependent()
Move `alreadySeen` handling out of for-loop.

Closes gh-30839
2023-07-09 15:22:35 +02:00
Sébastien Deleuze b3de1b8e95 Use consistently *KotlinTests naming for Kotlin tests
Closes gh-30837
2023-07-08 11:02:20 +02:00
Sébastien Deleuze fb17e283d1 Replace @link by proper KDoc class reference in tests
Closes gh-30836
2023-07-08 10:44:40 +02:00
Juergen Hoeller 0b7a24fc14 Polishing 2023-07-08 00:58:20 +02:00
Sam Brannen 75b540f25c Update copyright headers 2023-07-07 15:03:09 +02:00
Sam Brannen 8bf79cc9c4 Polish contribution
Closes gh-30593
2023-07-07 15:02:38 +02:00
Heo YounHaeng 7ff80bc09d Fix example in Javadoc for MultipartBodyBuilder
See gh-30593
2023-07-07 15:00:47 +02:00
Valery Yatsynovich 8d6b0eb191 Fix typo in UriUtils Javadoc
Closes gh-30598
2023-07-07 14:50:46 +02:00
Juergen Hoeller 35c7e3960e Polishing 2023-07-07 13:46:57 +02:00
Juergen Hoeller 8e8c3f5a7c Polishing 2023-07-07 13:14:40 +02:00
Olga MaciaszekSharma 268f3c853e Add RestTemplate support for HTTP interface client
See gh-30117
2023-07-06 19:07:40 +02:00
Sam Brannen f50b230fb3 Emphasize that a ContextCustomizer must implement equals() and hashCode() 2023-07-06 17:28:24 +02:00
Sam Brannen 02ba06953f Polish grammar and formatting 2023-07-06 17:21:30 +02:00
Brian Clozel df22ba39f8 Warn against direct usage of Servlet API in WebFlux apps
Closes gh-28872
2023-07-06 17:11:24 +02:00
Sam Brannen 826776f321 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 14:01:26 +02:00
Sam Brannen 29f92c8a2b Polish observability docs 2023-07-06 13:27:20 +02:00
Brian Clozel 64e04b7bc2 Document limitations of Servlet Filter observations
This commit documents the fact that the Servlet Filter based
observations for MVC applications is limited by the Servlet Filter
contract in the first place. All processing and logging that happens
outside of the scope of the filter is not observed.
Log statements from the catalina engine (in the case of Tomcat), or any
container-specific infrastructure, is not covered by the
instrumentation.

Closes gh-29398
2023-07-06 13:09:41 +02:00
Sam Brannen ad05b02ff5 Update Javadoc for ObjectUtils.nullSafeConciseToString()
See gh-30810
2023-07-06 12:26:47 +02:00
Brian Clozel 430a24e6bc Further document ShallowEtagHeaderFilter limitations
This commit improves the documentation for the
`ShallowEtagHeaderFilter`, stating that it is only meant to support a
subset of conditional HTTP requests: GET requests with "If-None-Match"
headers. Other headers and state changing HTTP methods are not supported
here, as the filter only operates on the content of the response and has
no knowledge of the resource being served.

Closes gh-30517
2023-07-06 09:39:57 +02:00
Juergen Hoeller b7b9f2cb6b Expand tests for array to Collection/Set/List interface
See gh-28048
2023-07-05 20:15:10 +02:00
Sam Brannen b76664e757 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-30810
2023-07-05 17:01:01 +02:00
Sam Brannen ae13823851 Polishing 2023-07-05 15:33:15 +02:00
Sam Brannen 58b4286216 Polish MockHttpServletRequest 2023-07-05 13:59:47 +02:00
Sam Brannen df079feea9 Update copyright header 2023-07-05 13:48:13 +02:00
Patrick Strawderman 372282457f Use Collections.emptyEnumeration() where appropriate
Closes gh-30803
2023-07-05 13:47:11 +02:00
Juergen Hoeller 79df1da792 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:51:45 +02:00
Juergen Hoeller c5771bc7c8 Discuss JdbcTransactionManager vs DataSourceTransactionManager
Includes doc update for 6.0 default exception translation etc.

Closes gh-30802
2023-07-05 12:51:10 +02:00
Juergen Hoeller 2365581265 Upgrade to HSQLDB 2.7.2 and WebJars Locator 0.53 2023-07-04 21:35:37 +02:00
Juergen Hoeller c1a8b9a14d Polishing 2023-07-04 21:24:35 +02:00
rstoyanchev e945e7426e Update AspectJ Javadoc link after permanent redirect 2023-07-04 18:09:55 +01:00
Juergen Hoeller f07b9fd217 Polishing 2023-07-04 16:52:44 +02:00
Juergen Hoeller 80a20488fd Make File/Path tests pass on Windows
See gh-30806
2023-07-04 16:52:39 +02:00
Juergen Hoeller 1dc9dffc70 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
2023-07-04 15:58:46 +02:00
Juergen Hoeller 0226580773 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
2023-07-04 15:58:30 +02:00
Sam Brannen 3ef1b7d83c 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-30805
2023-07-04 13:27:47 +02:00
Sam Brannen 08bce69d3d Add tests for status quo in ObjectUtils.nullSafeConciseToString() 2023-07-04 13:15:56 +02:00
Yanming Zhou 56b60120fe Stop using deprecated AbstractArchiveTask.archivePath in Gradle build
This commit addresses the following warning in the build.

The AbstractArchiveTask.archivePath property has been deprecated. This
is scheduled to be removed in Gradle 9.0. Please use the archiveFile
property instead. See
https://docs.gradle.org/8.1.1/dsl/org.gradle.api.tasks.bundling.AbstractArchiveTask.html#org.gradle.api.tasks.bundling.AbstractArchiveTask:archivePath
for more details.

Closes gh-30697
2023-07-03 17:09:48 +02:00
Sam Brannen 1364a179a9 Upgrade to Gradle 8.2
Closes gh-30791
2023-07-03 16:24:34 +02:00
Sam Brannen 2161e865d7 Update copyright header 2023-07-03 15:53:43 +02:00
Vladyslav Baidak 0b2c2d04b2 Fix typo in Javadoc for BeanDefinitionDsl.kt
Closes gh-30798
2023-07-03 15:49:28 +02:00
Sam Brannen 07fe8eea83 Improve error message for wrong version of micrometer-observation
This commit also reverts to using ReflectionUtils.findMethod in order
to make the check more robust in case the Micrometer team refactors the
code base and declares the `getObservationRegistry()` method in a super
type.
2023-07-03 14:48:53 +02:00
Sam Brannen 5aac35b99e Check deps only once in MicrometerObservationRegistryTestExecutionListener
Prior to this commit, the required runtime dependencies were checked
via reflection each time an attempt was made to instantiate
MicrometerObservationRegistryTestExecutionListener.

Since it's sufficient to check for the presence of required runtime
dependencies only once, this commit caches the results of the
dependency checks in a static field.

This commit also introduces automated tests for the runtime dependency
checks in MicrometerObservationRegistryTestExecutionListener.

See gh-30747
2023-07-02 16:40:41 +02:00
Sam Brannen 040ea0a97c Remove @Aspect for classes containing only @Pointcut declarations in ref docs
Closes gh-30790
2023-07-01 17:41:55 +02:00
Sam Brannen 3c05679a97 Polishing
See gh-30762
2023-06-30 14:04:37 +02:00
Yanming Zhou d8729a7c67 Polish variable name in ReschedulingRunnable
As a variable name, `initDelay` is applicable for `scheduleAtFixedRate`
and `scheduleWithFixedDelay` but not for `schedule`.

Closes gh-30762
2023-06-30 13:57:46 +02:00
Sam Brannen c95426a616 Polishing 2023-06-30 13:55:34 +02:00
Juergen Hoeller 1e403d1606 Upgrade to Groovy 4.0.13 and Checkstyle 10.12.1 2023-06-30 12:58:28 +02:00
Juergen Hoeller f1567fb21a Raise beforeCompletion/afterCompletion exception log level to error
Closes gh-30776
2023-06-30 12:47:30 +02:00
Juergen Hoeller 60865eae4b Align ConcurrentMapCacheManager locking behavior with CaffeineCacheManager
Closes gh-30780
2023-06-30 10:39:53 +02:00
Juergen Hoeller 0c39fff831 Polishing 2023-06-29 18:04:08 +02:00
Juergen Hoeller e902f9551a Improve condition assertions 2023-06-29 12:05:07 +02:00
Juergen Hoeller 0a20c8a44a Restore defensive access to volatile field in getBeanClassName()
Closes gh-30773
2023-06-29 12:04:53 +02:00
Juergen Hoeller 3cb746c358 Consistently handle invocation exceptions in TypeProxyInvocationHandler
Closes gh-30764
2023-06-28 15:45:40 +02:00
Juergen Hoeller 6526e79eea Polishing 2023-06-26 19:28:38 +02:00
Juergen Hoeller b77d4d01c5 Adapt no-arg value from interface-based InvocationHandler callback
Closes gh-30756
2023-06-26 19:28:19 +02:00
Juergen Hoeller 599ac58baa Avoid arithmetic overflow for large delay/period values
Closes gh-30754
2023-06-26 19:28:08 +02:00
Juergen Hoeller 449174c7d4 Polishing 2023-06-26 12:35:09 +02:00
Juergen Hoeller 9266e6d29e Remove outdated javadoc notes on getMessage and printStackTrace
Closes gh-30748
2023-06-26 12:34:59 +02:00
Juergen Hoeller 062d701ae1 Consistently use mutable ArrayList for modulesToInstall vs modules
Closes gh-30751
2023-06-26 12:34:54 +02:00
Sébastien Deleuze 7137b22e6b Fix test compilation warnings
Closes gh-30753
2023-06-26 12:03:27 +02:00
Sam Brannen acb786d359 Improve logging in MicrometerObservationRegistryTestExecutionListener
Prior to this commit, dependency checks in the static initialization
block for MicrometerObservationRegistryTestExecutionListener resulted
in an ExceptionInInitializerError which led to verbose logging in
TestContextFailureHandler.

This commit improves the logging for missing dependencies in
MicrometerObservationRegistryTestExecutionListener by moving the
dependency checks to the constructor and by throwing a
NoClassDefFoundError instead of an IllegalStateException. This allows
TestContextFailureHandler to log a concise DEBUG message denoting that
the listener is being skipped due to missing dependencies.

This commit also now checks for the presence of
io.micrometer.context.ThreadLocalAccessor in addition to
io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor.

Furthermore, this commit now explicitly mentions the need for
io.micrometer:context-propagation in the error message.

The following demonstrate the generated DEBUB message when
ObservationThreadLocalAccessor and ThreadLocalAccessor are missing,
respectively.

Skipping candidate TestExecutionListener [org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener] due to a missing dependency. Specify custom TestExecutionListener classes or make the default TestExecutionListener classes and their required dependencies available. Offending class: io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor. MicrometerObservationRegistryTestExecutionListener requires io.micrometer:micrometer-observation:1.10.8 or higher and io.micrometer:context-propagation:1.0.3 or higher.

Skipping candidate TestExecutionListener [org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener] due to a missing dependency. Specify custom TestExecutionListener classes or make the default TestExecutionListener classes and their required dependencies available. Offending class: io.micrometer.context.ThreadLocalAccessor. MicrometerObservationRegistryTestExecutionListener requires io.micrometer:micrometer-observation:1.10.8 or higher and io.micrometer:context-propagation:1.0.3 or higher.

Closes gh-30747
2023-06-25 18:49:57 +02:00
Sam Brannen fa7300c1de Remove unused test code and polish 2023-06-25 15:31:15 +02:00
Sam Brannen db17a97ce8 Polishing 2023-06-25 15:18:59 +02:00
Johnny Lim 55f946c5a0 Fix incomplete AssertJ assertions
Closes gh-30743
2023-06-25 15:18:52 +02:00
Sam Brannen 3181dca5ef Support [package-]private init/destroy methods in AOT mode
Prior to this commit, private (and non-visible package-private)
init/destroy methods were not supported in AOT mode. The reason is that
such methods are tracked using their fully-qualified method names, and
the AOT support for init/destroy methods previously did not take
fully-qualified method names into account. In addition, the invocation
order of init/destroy methods differed vastly between standard JVM mode
and AOT mode.

This commit addresses these issues in the following ways.

- AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(),
  DisposableBeanAdapter.determineDestroyMethod(), and
  BeanDefinitionPropertiesCodeGenerator.addInitDestroyHint() now parse
  fully-qualified method names to locate the correct init/destroy
  methods.

- AbstractAutowireCapableBeanFactory and DisposableBeanAdapter delegate
  to a new MethodDescriptor record which encapsulates the parsing of
  fully-qualified method names; however,
  BeanDefinitionPropertiesCodeGenerator duplicates this logic since it
  resides in a different package, and we do not currently want to make
  MethodDescriptor public.

- Init/destroy methods detected via annotations (such as @PostConstruct
  and @PreDestroy) are now invoked prior to init/destroy methods that
  are explicitly configured by name or convention. This aligns with the
  invocation order in standard JVM mode; however,
  InitializingBean#afterPropertiesSet() and DisposableBean#destroy()
  are still invoked before annotated init/destroy methods in AOT mode
  which differs from standard JVM mode.

- Unit and integration tests have been updated to test the revised
  behavior.

Closes gh-30692
2023-06-24 14:22:17 +02:00
Sam Brannen f86a69ebfb Update copyright headers and polish 2023-06-24 14:14:02 +02:00
Sam Brannen 6d63890c56 Use Assumptions.abort() where appropriate 2023-06-24 14:13:22 +02:00
Sam Brannen 489c89b912 Remove unused test code 2023-06-24 14:12:58 +02:00
Sam Brannen 39bc7566df Stop printing to System.out in tests 2023-06-24 14:10:12 +02:00
Sébastien Deleuze d3a249e34d Reduce the delay used for Coroutines in tests
Closes gh-30731
2023-06-23 14:17:56 +02:00
Sébastien Deleuze 81f1edbaf2 Change InvocableHandlerMethod#invokeSuspendingFunction return type
This commits changes the return type from Publisher<?> to
Object in order to avoid potential compatibility issues when
the Reactive Streams dependency is not in the classpath.

Closes gh-30716
2023-06-23 14:17:56 +02:00
Sébastien Deleuze 23ecb50137 Optimize KotlinReflectionParameterNameDiscoverer
This commit removes the intermediate list allocation.

Closes gh-30725
2023-06-23 14:17:56 +02:00
Sam Brannen 3d33d2baa9 Polish contribution 2023-06-23 13:35:16 +02:00
Xiu Hong Kooi 3745224646 Remove redundant assertion in ReactorServerHttpResponse constructor
See gh-30686
Closes gh-30696
2023-06-23 13:34:31 +02:00
Rossen Stoyanchev bf82ed7186 Add HttpExchangeAdapter
See gh-30117
2023-06-23 11:49:29 +01:00
Eric Haag 1b27a7baab Remove explicit cross project task dependency
Previously, the runtimeHintsTest task configuration made a cross
project task reference to obtain the jar path of spring-core-test
to use in the -javaagent argument.

With this change, a dedicated configuration exists to resolve the
project artifact without the need to reference the jar task of
spring-core-test.

Closes gh-30838
2023-07-10 22:42:37 +02:00
Eric Haag d40c10e00f Evaluate runtime hints agent parameter lazily
Previously, an afterEvaluate call was used to read the values of the
runtimeHintsAgent extension and the -javaagent parameter supplied to
the runtimeHintsTest task was evaluated eagerly.

With this change the construction of the -javaagent parameter is
deferred until task execution and the extension properties are
evaluated lazily.

See gh-30838
2023-07-10 22:42:37 +02:00
Eric Haag 5d022d2a24 Fix build cache miss in runtimeHintsTest task
Prior to this change, a build cache miss would occur in
runtimeHintsTest tasks when executing the build from two different
locations, causing the tasks to re-execute. This was due to an
absolute path to the agent jar being included in the -javaagent
argument supplied to the test JVM process.

This change introduces a RuntimeHintsAgentArgumentProvider allowing
finer grained control over the way Gradle computes the build cache
key. With this change, the contents of the agent jar file are
considered, rather than the absolute file location.

See gh-30838
2023-07-10 22:42:37 +02:00
Johnny Lim 433b72d493 Polish gh-29883 2023-07-10 22:13:12 +02:00
Sam Brannen 7bc731dfa6 Merge branch '6.0.x' 2023-07-10 19:07:09 +02:00
Brian Clozel 5cb6454824 Switch to Reactor 2023.0.0-SNAPSHOT
See gh-30856
2023-07-10 18:13:40 +02:00
Juergen Hoeller 9a68b3e910 Merge branch '6.0.x' 2023-07-10 17:18:16 +02:00
Sébastien Deleuze 38f9cbe3de Use latest version of sockjs-client in AbstractSockJsService
Closes gh-30848
2023-07-10 15:27:53 +02:00
Sébastien Deleuze 76f94e998e Merge branch '6.0.x' 2023-07-09 18:41:58 +02:00
Juergen Hoeller 71bb45c87b Merge branch '6.0.x' 2023-07-09 16:56:45 +02:00
Sam Brannen 0521cdda88 Merge branch '6.0.x' 2023-07-09 15:38:55 +02:00
Juergen Hoeller 6b1fbc9fe1 Revise ResolvableType equality
ResolvableTypes are only considered equal if of the very same class now.
As a consequence, a forRawClass result is not equal to forClass anymore.
The new equalsType method is available for plain type equality checks.

Closes gh-28608
Closes gh-27748
2023-07-09 12:35:37 +02:00
Juergen Hoeller 5243c2262a Support scheduler qualifier for reactive SubscribingRunnable as well
See gh-20818
2023-07-08 17:18:17 +02:00
Juergen Hoeller a0c80ffc06 Destroy local TaskSchedulerRouter which may contain local executor
See gh-20818
2023-07-08 15:55:25 +02:00
Juergen Hoeller a8614531ab Support for determining a target scheduler for a specific task
Introduces "scheduler" attribute on @Scheduled annotation.
TaskSchedulerRouter delegates to qualified/default scheduler.
ScheduledMethodRunnable exposes qualifier through SchedulingAwareRunnable.

Closes gh-20818
2023-07-08 15:37:04 +02:00
Juergen Hoeller f0fe58f0ec Move observation support classes to scheduling.support package
Avoids a package cycle between config and support (only config->support allowed).

See gh-29883
2023-07-08 14:57:02 +02:00
Sébastien Deleuze 8fb412ea74 Merge branch '6.0.x' 2023-07-08 11:11:37 +02:00
Juergen Hoeller bf99361abb Merge branch '6.0.x' 2023-07-08 00:58:58 +02:00
Juergen Hoeller 464b676ec5 Expose shutdown state in TaskRejectedException message
See gh-27090
2023-07-07 23:59:10 +02:00
rstoyanchev ac11b03cd3 Document customization of method validation errors
Closes gh-30653
2023-07-07 21:31:58 +01:00
rstoyanchev df2617d575 Document method validation improvements
Closes gh-30643
2023-07-05 17:07:30 +01:00
Sébastien Deleuze a03a14797f Add AOT support for Kotlin constructors with optional parameters
This commit leverages Kotlin reflection to instantiate classes
with constructors using optional parameters in the code
generated AOT.

Closes gh-29820
2023-07-07 17:40:31 +02:00
Arjen Poutsma 20dd66cd5a Introduce ReactorNettyClientRequestFactory
This commit introduces an implementation of ClientHttpRequestFactory
based on Reactor Netty's HttpClient.

Closes gh-30835
2023-07-07 15:30:53 +02:00
Sam Brannen d720d6be6b Merge branch '6.0.x' 2023-07-07 15:05:01 +02:00
Arjen Poutsma cb0c5f5a7b Allow RestClient::exchange to keep connection open
This commit introduces an overloaded version of RestClient::exchange,
adding a boolean parameter that indicates whether the connection is
closed after the exchange function is executed.

See gh-29552
2023-07-07 14:24:44 +02:00
Arjen Poutsma 8691173fd8 Create RestClient documentation placeholder
This commit creates a placeholder for future RestClient reference
documentation. It also creats a link to RestClient from the RestTemplate
javadoc.

See gh-30826
2023-07-07 14:14:59 +02:00
Juergen Hoeller ddc3cf301a Merge branch '6.0.x'
# Conflicts:
#	spring-context/src/main/java/org/springframework/scheduling/concurrent/ExecutorConfigurationSupport.java
2023-07-07 13:51:08 +02:00
Juergen Hoeller b12115b61f Sophisticated lifecycle support for ThreadPoolTaskExecutor/Scheduler
Pause/resume capability through SmartLifecycle implementation.
ContextClosedEvent triggers early executor/scheduler shutdown.
Programmatic initiateShutdown() option for custom early shutdown.

Closes gh-30831
Closes gh-27090
Closes gh-24497
2023-07-07 13:04:52 +02:00
Sébastien Deleuze 029a69f5c1 Upgrade to Kotlin Coroutines 1.7.2
Closes gh-30833
2023-07-07 11:44:03 +02:00
Sébastien Deleuze 80d1f12324 Upgrade to Kotlin 1.9.0
Closes gh-30719
2023-07-07 11:43:02 +02:00
Sam Brannen e906eac049 Update regarding Antora, etc. 2023-07-07 11:18:43 +02:00
Sam Brannen 32aa9e4b63 Update links 2023-07-07 11:00:53 +02:00
Sam Brannen 7162faaa4d Merge branch '6.0.x' 2023-07-06 17:30:02 +02:00
Sam Brannen 1901b708b2 Merge branch '6.0.x' 2023-07-06 17:21:49 +02:00
Sam Brannen d86750372a Improve Javadoc for @Configuration 2023-07-06 17:13:37 +02:00
Brian Clozel 3a0e5c8894 Merge branch '6.0.x' 2023-07-06 17:12:05 +02:00
Arjen Poutsma cf008eb9b1 Revert "Follow redirects in JdkClientHttpRequestFactory"
This reverts commit 7c37f4bc51.
2023-07-06 15:53:35 +02:00
Sam Brannen 0bf85af8e9 Merge branch '6.0.x'
# Conflicts:
#	framework-docs/modules/ROOT/pages/integration/observability.adoc
#	spring-core/src/test/java/org/springframework/core/convert/converter/DefaultConversionServiceTests.java
2023-07-06 14:11:24 +02:00
Arjen Poutsma 78bb66b0f2 Reduce flushes in FormHttpMessageConverter
Before this commit, each part written by the FormHttpMessageConverter
would typically end with a flush, which reduced performance.
2023-07-06 13:49:57 +02:00
Brian Clozel 246135364c Merge branch '6.0.x' 2023-07-06 13:09:58 +02:00
Sam Brannen 468ef7a618 Merge branch '6.0.x' 2023-07-06 12:27:47 +02:00
Arjen Poutsma 68b5eedde1 Change OutputStreamPublisher default chunk size
This commit set the default chunk size to 1024 (from 8192).
2023-07-06 12:01:24 +02:00
Arjen Poutsma 3d2befc84a Rearrange HttpHeaders adapters
This commit moves HttpHeaders that are used in multiple places (client
and server, reactive and non-reactive) to a new, separate http.support
package.

Closes gh-30823
2023-07-06 11:00:26 +02:00
Brian Clozel 8e9528de13 Merge branch '6.0.x' 2023-07-06 09:40:13 +02:00
Juergen Hoeller 0c8d3e70cf Prefer ArrayList for Collection when source is an array
Closes gh-28048
2023-07-05 20:23:17 +02:00
Juergen Hoeller 47e631d5ff Merge branch '6.0.x' 2023-07-05 20:15:53 +02:00
Sam Brannen e86003b692 Merge branch '6.0.x' 2023-07-05 17:02:35 +02:00
Sam Brannen f6218cadd7 Merge branch '6.0.x' 2023-07-05 15:33:26 +02:00
Sam Brannen 368a917466 Polish RestClient, etc. 2023-07-05 15:22:27 +02:00
Arjen Poutsma a6c5692586 Make OutputStreamPublisher more generic
This commit improves the OutputStreamPublisher so that it is capable
of publishing other types that ByteBuffers.
2023-07-05 15:20:43 +02:00
Sam Brannen d0a2820af4 Polish AnnotatedMethod 2023-07-05 14:46:19 +02:00
Sam Brannen 299b86bae3 Merge branch '6.0.x' 2023-07-05 14:02:49 +02:00
Juergen Hoeller 1218e65ca1 Merge branch '6.0.x' 2023-07-05 12:53:07 +02:00
Arjen Poutsma 496155525c Allow built ServerResponse to throw exception
This commit ensures that ServerResponse.HeadersBuilder::build can throw
an exception, by introducing a separate functional interface that does
allow for exceptions to be thrown.

Closes gh-30818
2023-07-05 12:01:55 +02:00
Arjen Poutsma 7c37f4bc51 Follow redirects in JdkClientHttpRequestFactory
Make sure we follow redirects in the default HttpClient created by
JdkClientHttpRequestFactory, similar toSimpleClientHttpRequestFactory.
2023-07-05 11:08:41 +02:00
Arjen Poutsma 6793edc349 Increase Jetty read timeout to 10 seconds 2023-07-05 10:34:20 +02:00
Juergen Hoeller 1777e7f3b7 Merge branch '6.0.x'
# Conflicts:
#	spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java
#	spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java
2023-07-04 21:40:11 +02:00
Juergen Hoeller 6fa09e1783 Extract AnnotatedMethod base class for consistent annotation exposure
As a consequence, the spring-messaging HandlerMethod detects interface parameter annotations as well, and the same is available for other HandlerMethod variants.

Closes gh-30801
2023-07-04 20:42:30 +02:00
rstoyanchev ae23f5a594 Merge branch '6.0.x' 2023-07-04 18:10:19 +01:00
rstoyanchev deaa493644 Add Visitor to HandlerMethodValidationException
Closes gh-30813
2023-07-04 17:19:58 +01:00
Sébastien Deleuze 2a126faae7 Upgrade to Project CRaC 1.3.0
Closes gh-30812
2023-07-04 17:49:00 +02:00
Sébastien Deleuze 35304435d0 Add RestClient Kotlin extensions
Closes gh-30807
2023-07-04 17:33:39 +02:00
Juergen Hoeller 420255373d Merge branch '6.0.x' 2023-07-04 16:53:17 +02:00
Juergen Hoeller 834d22f866 Polishing 2023-07-04 16:08:24 +02:00
Juergen Hoeller 2a77665be7 Merge branch '6.0.x' 2023-07-04 15:59:38 +02:00
Brian Clozel 14857ae0da Upgrade to JDK 21ea29 in CI build 2023-07-04 15:23:51 +02:00
Sam Brannen 7156ea016e Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/util/ObjectUtils.java
2023-07-04 13:44:19 +02:00
Arjen Poutsma 0820210c7c Introduce RestClient
This commit introduces the RestClient, a synchronous HTTP client that
offers an API similar to WebClient, using the same infrastructure (i.e.
request factory, error handler, interceptors, etc) as RestTemplate.

Closes gh-29552
2023-07-04 10:27:58 +02:00
Sam Brannen 9eb1fbd5c3 Merge branch '6.0.x' 2023-07-03 17:18:27 +02:00
Sam Brannen ea9c217827 Merge branch '6.0.x' 2023-07-03 16:37:35 +02:00
rstoyanchev 1fc020cf92 Fix checkstyle violations 2023-07-03 15:31:35 +01:00
rstoyanchev 592ab0f350 Add ~.validation.method package
Extract classes from ~.validation.beanvalidation without a direct
dependency on beanvalidation.

See gh-30644
2023-07-03 15:05:51 +01:00
Sam Brannen 0da2241367 Merge branch '6.0.x' 2023-07-03 15:54:13 +02:00
Sam Brannen 37e8ef1542 Merge branch '6.0.x' 2023-07-03 15:50:17 +02:00
Sam Brannen e995033811 Polishing 2023-07-03 15:00:02 +02:00
Sam Brannen 4c0329014f Merge branch '6.0.x' 2023-07-03 14:49:23 +02:00
Arjen Poutsma 72301dc861 Add Duration variants for ClientHttpRequestFactory timeouts
This commit adds overloaded variants of timeout setters that take a
Duration instead of a number.
2023-07-03 13:35:26 +02:00
rstoyanchev 84e863f803 Refactoring in MethodValidationAdapter
Extract the default logic for resolving the name of an @Valid
parameter into an ObjectNameResolver, and use it when there isn't
one configured.

See gh-30644
2023-07-03 12:08:11 +01:00
rstoyanchev 7a79da589a Add default web handling of method validation errors
Closes gh-30644
2023-07-03 12:08:11 +01:00
rstoyanchev a481c7649f Refactor to prepare for method validation handling
To handle method validation errors in ResponseEntityExceptionHandler,
MethodValidationException and associated types should not depend on
Bean Validation. To that effect:

1. MethodValidationResult and ParameterValidationResult no longer make
the underlying ConstraintViolation set available, and instead expose
only the adapted validation errors (MessageSourceResolvable, Errors),
analogous to what SpringValidatorAdapter does. And likewise
MethodValidationException no longer extends ConstraintViolationException.

2. MethodValidationPostProcessor has a new property
adaptConstraintViolations to decide whether to simply raise
ConstraintViolationException, or otherwise to adapt the ConstraintViolations
and raise MethodValidationException instead, with the former is the default
for compatibility.

3. As a result, the MethodValidator contract can now expose methods that
return MethodValidationResult, which provided more flexibility for handling,
and it allows MethodValidationAdapter to implement MethodValidator directly.

4. Update Javadoc in method validation classes to reflect this shift, and
use terminology consistent with Spring validation in classes without an
explicit dependency on Bean Validation.

See gh-30644
2023-07-03 12:08:11 +01:00
Rossen Stoyanchev ba4d9a5230 Add BindErrorUtils
This deprecates static methods in MethodArgumentNotValidException
which is not a great vehicle for such methods.

See gh-30644
2023-07-03 12:08:11 +01:00
rstoyanchev e83594a2a3 Polishing in Web validation exceptions
- Update method order
- Do not automatically create MessageSource arguments in
WebExchangeBindException constructor as they're more likely to be
created via getDetailMessageArguments with MessageSource passed in.

See gh-30644
2023-07-03 12:08:11 +01:00
rstoyanchev a8ea472121 Refactoring in MethodValidationResult
Remove throwIfViolationsPresent and replace with static factory
methods on MethodValidationException taking MethodValidationResult,
which makes handling more explicit and allows choice of what
exception to raise.

Update MethodValidationResult to expose the target, the method, and
forReturnValue flag, so the code handling an exception will have
access to all details.

See gh-30644
2023-07-03 12:08:11 +01:00
Arjen Poutsma 1393fac402 Merge pull request #30788 from spencergibb:customize-disallowed-headers
* gh-30788:
  Polishing external contribution
  Allow customization of disallowed JdkClientHttpRequest headers
2023-07-03 12:42:47 +02:00
Arjen Poutsma 46f1849c2f Polishing external contribution
See gh-30787
Closes gh-30788
2023-07-03 12:36:25 +02:00
spencergibb 9900575f9c Allow customization of disallowed JdkClientHttpRequest headers
By default, the JDK HttpClient's HttpRequest does not allow Connection,
Content-Length, Expect, Host, or Upgrade headers to be set, but this can
be overriden with the `jdk.httpclient.allowRestrictedHeaders` system
property.

See https://bugs.openjdk.org/browse/JDK-8213696

Closes gh-30787
2023-07-03 12:35:44 +02:00
Sam Brannen 2ed10f13e9 Merge branch '6.0.x' 2023-07-02 16:47:25 +02:00
Sam Brannen a23c9cd53d Merge branch '6.0.x' 2023-07-01 17:42:28 +02:00
Sam Brannen 9ac2443b78 Polish ModuleResource[Tests] 2023-07-01 16:49:32 +02:00
Sébastien Deleuze f075120675 Support WildcardType resolution in GenericTypeResolver
This commit adds support for WildcardType bounds resolution,
commonly seen in Kotlin due to declaration-site variance,
but also possible in Java even if less common.

Closes gh-22313
2023-06-30 15:26:32 +02:00
Sam Brannen b8f091e2f6 Merge branch '6.0.x' 2023-06-30 14:17:49 +02:00
Johnny Lim 41f8b6926f Polish gh-30013
See gh-30013
2023-06-30 14:02:15 +02:00
Juergen Hoeller b4ed3fbcd0 Upgrade to Checkstyle 10.12.1 2023-06-30 13:02:38 +02:00
Juergen Hoeller 83ec9f4fe7 Merge branch '6.0.x'
# Conflicts:
#	build.gradle
2023-06-30 13:00:04 +02:00
Seonghoon Kim 3f65b8506b Increase log level to error 2023-06-30 12:38:28 +02:00
Juergen Hoeller 50074f0e96 Merge branch '6.0.x' 2023-06-30 10:40:37 +02:00
Juergen Hoeller 31a51cca4f Support for getFilename() in ModuleResource
See gh-28507
2023-06-30 00:35:14 +02:00
Juergen Hoeller 654dee8cd6 Additional notes on module access via ClassPathResource
See gh-28507
2023-06-29 18:15:38 +02:00
Juergen Hoeller 7028de9dbd Merge branch '6.0.x' 2023-06-29 18:04:40 +02:00
Juergen Hoeller e4751513a4 Additional notes on module access via ClassPathResource
See gh-28507
2023-06-29 17:54:53 +02:00
Sébastien Deleuze bd7e2d2875 Change restore logging to info level
Closes gh-30775
2023-06-29 17:20:51 +02:00
Juergen Hoeller 6061fdf231 Introduce ModuleResource for resources loaded from a given Module
Closes gh-28507
2023-06-29 17:18:46 +02:00
Arjen Poutsma 9b662e8244 Typo 2023-06-29 15:36:31 +02:00
Arjen Poutsma f51a640309 Polishing JdkClientHttpRequestFactory 2023-06-29 14:40:25 +02:00
Arjen Poutsma 48906afaf4 Polishing JettyClientHttpRequestFactory 2023-06-29 12:32:20 +02:00
Juergen Hoeller ef4d93507d Merge branch '6.0.x' 2023-06-29 12:05:57 +02:00
Arjen Poutsma d1d79babe7 Polishing JettyClientHttpRequestFactory 2023-06-28 16:19:13 +02:00
Juergen Hoeller 2eb8efe83b Merge branch '6.0.x' 2023-06-28 15:46:29 +02:00
Arjen Poutsma dd57ec9fa0 Merge pull request #30478 from mdeinum:http-client
* gh-30478:
  Polishing external contribution
  HttpClient based ClientHttpRequestFactory
2023-06-28 12:28:24 +02:00
Arjen Poutsma 0033eb4ed6 Polishing external contribution
- Removed duplicate Client in types names.
- Removed buffering in favor of OutputStream to
  Flow.Publisher<ByteBuffer> bridge.
- Made request and types package private.
- Various other small improvements.

Closes gh-30478
2023-06-28 12:23:29 +02:00
Marten Deinum 2ca8dd2faa HttpClient based ClientHttpRequestFactory
As JDK17 is now the baseline it is possible to use the
HttpClient provided by Java.
2023-06-28 10:43:44 +02:00
Brian Clozel c2e3fed8dc Align observations of @Scheduled with OTel conventions
This commit updates the `ScheduledTaskObservationDocumentation` to
better align the contributed KeyValues with OpenTelemetry conventions
for observations of code executions.

Instead of a "target.type" key with the bean class simple name, this
is now contributing the canonical class name of the bean under the
"code.namespace" key.
The "method.name" key is renamed to "code.function" and its values
remain unchanged.

Closes gh-30721
2023-06-27 22:20:06 +02:00
rstoyanchev 91eb2be44c Remove no longer supported protected methods
Closes gh-26721
2023-06-27 16:34:52 +01:00
rstoyanchev d4ac90dae0 Support nested constructors in DataBinder
Closes gh-20806
2023-06-26 17:01:44 +01:00
rstoyanchev 11a416156b Use ResolvableType to create WebDataBinder
This provides more flexibility to pass a targetType even if
a MethodParameter is not available.

See gh-26721
2023-06-26 13:11:05 +01:00
Sam Brannen 3bf78d6f8c Fix AbstractMessageListenerContainer Javadoc regarding error log level
This commit updates AbstractMessageListenerContainer's Javadoc
regarding the log level used in invokeErrorHandler() so that the
documentation aligns with the implementation, namely that errors will
logged at WARN level if no ErrorHandler has been registered.

Closes gh-30730
2023-06-23 12:45:52 +02:00
Sam Brannen 563b2a8505 Polish AbstractMessageListenerContainer Javadoc 2023-06-23 12:44:57 +02:00
rstoyanchev d37d6688d8 WebFlux constructs model attribute via DataBinder
See gh-26721
2023-06-23 11:15:00 +01:00
Sam Brannen 9ccbeec947 Ignore null message when introspecting resource cleanup failure
This commit fixes a regression introduced in conjunction with gh-27572.

See gh-30597
Closes gh-30729
2023-06-23 12:01:16 +02:00
rstoyanchev 801f01e23f Polishing in ModelAttributeMethodArgumentResolver
See gh-26721
2023-06-22 20:59:05 +01:00
rstoyanchev ea398d7b7e Support constructing target object in DataBinder
See gh-26721
2023-06-22 20:36:28 +01:00
rstoyanchev 40bf923d7d Polishing in MultipartFileArgumentResolver
Closes gh-30728
2023-06-27 10:51:42 +01:00
Olga Maciaszek-Sharma e69a1d22f9 Add MultipartFile support to HTTP interface client
See gh-30728
2023-06-27 09:55:24 +01:00
Juergen Hoeller 3f40452511 Merge branch '6.0.x' 2023-06-26 19:36:20 +02:00
Juergen Hoeller 2ccf4cab8b Polishing 2023-06-26 12:37:33 +02:00
Juergen Hoeller feac983869 Merge branch '6.0.x' 2023-06-26 12:35:56 +02:00
Sébastien Deleuze 66b27e6dc8 Merge branch '6.0.x' 2023-06-26 12:03:40 +02:00
Sam Brannen 6072a537d9 Polish formatting 2023-06-25 19:13:27 +02:00
Sam Brannen aecebf7981 Ensure MethodValidationAdapterTests pass with default Locale other than English
Closes gh-30734
2023-06-25 19:12:41 +02:00
Sam Brannen 4cbf47834d Merge branch '6.0.x' 2023-06-25 18:50:23 +02:00
Sam Brannen 854715d9a7 Update copyright headers 2023-06-25 15:39:16 +02:00
Sam Brannen 9127777c32 Merge branch '6.0.x'
# Conflicts:
#	spring-context/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java
2023-06-25 15:34:10 +02:00
Johnny Lim 6c816c55d1 Fix incomplete AssertJ assertions
Closes gh-30743
2023-06-25 15:10:11 +02:00
Sam Brannen 209e02cf29 Merge branch '6.0.x' 2023-06-24 14:27:13 +02:00
Sam Brannen 19686adc01 Merge branch '6.0.x' 2023-06-24 14:15:05 +02:00
Sébastien Deleuze 35667e81ea Merge branch '6.0.x' 2023-06-23 14:20:13 +02:00
Juergen Hoeller d881cd3346 Accept REQUIRES_NEW on non-async transactional event listeners
See gh-30679
2023-06-23 14:03:11 +02:00
Sam Brannen ca51b1422a Merge branch '6.0.x' 2023-06-23 13:53:01 +02:00
Sam Brannen da00bbebbf Merge branch '6.0.x' 2023-06-23 12:46:30 +02:00
Sam Brannen 171535f680 Merge branch '6.0.x' 2023-06-23 12:07:37 +02:00
Sébastien Deleuze f06cf21341 Support Kotlin parameter default values in handler methods
This commit adds support for Kotlin parameter default values
in handler methods. It allows to write:
@RequestParam value: String = "default"
as an alternative to:
@RequestParam(defaultValue = "default") value: String

Both Spring MVC and WebFlux are supported, including on
suspending functions.

Closes gh-21139
2023-06-22 16:08:48 +02:00
Sam Brannen 254fb39567 Merge branch '6.0.x' 2023-06-22 16:01:22 +02:00
Sam Brannen 29248dff15 Use correct ClassLoader in MicrometerObservationRegistryTestExecutionListener
In the original implementation of
MicrometerObservationRegistryTestExecutionListener I accidentally
imported JUnit 5's org.junit.platform.launcher.TestExecutionListener
instead Spring's
org.springframework.test.context.TestExecutionListener. The code
therefore attempts to use the ClassLoader for the JUnit Platform's
TestExecutionListener which may fail to see the required types. In
addition, if the JUnit Platform's TestExecutionListener is not on the
classpath, the attempt to access its ClassLoader will fail.

This commit addresses this by properly using the ClassLoader for
Spring's TestExecutionListener to detect dependencies of the
MicrometerObservationRegistryTestExecutionListener.

Closes gh-30726
2023-06-22 15:55:46 +02:00
Sam Brannen 40596433f1 Merge branch '6.0.x' 2023-06-22 15:28:34 +02:00
Sam Brannen 65d450ab6d Document that RowCallbackHandler can be used w/ NamedParameterJdbcTemplate
Closes gh-30705
2023-06-22 15:27:41 +02:00
Johnny Lim 3be1216897 Polish
This commit polishes a bit.

Closes gh-30691
2023-06-22 15:12:58 +02:00
Sam Brannen b8a713fde3 Merge branch '6.0.x' 2023-06-22 15:12:25 +02:00
Johnny Lim 271f2dc665 Polish
This commit polishes a bit.

Closes gh-30691
2023-06-22 15:06:05 +02:00
Sam Brannen 06b6c4bcf9 Update copyright headers 2023-06-22 14:56:09 +02:00
Sam Brannen cd4ab23fa9 Merge branch '6.0.x' 2023-06-22 14:55:43 +02:00
Sam Brannen da323d3335 Update copyright headers 2023-06-22 14:55:23 +02:00
Sam Brannen 5598dd2c34 Merge branch '6.0.x' 2023-06-22 13:54:04 +02:00
Sam Brannen 32f061a3e0 Polishing 2023-06-22 13:48:07 +02:00
Sam Brannen f12d81f791 Merge branch '6.0.x' 2023-06-22 11:36:10 +02:00
Anton Gubenko 9b5cbc1334 Fix link text from "null" to "Component Classes" in Testing chapter
Closes gh-30714
2023-06-22 11:35:23 +02:00
Sam Brannen 49547fc710 Merge branch '6.0.x'
# Conflicts:
#	build.gradle
2023-06-22 11:32:39 +02:00
Johnny Lim 40e378a5a6 Upgrade to me.champeau.jmh 0.7.1
Closes gh-30690
2023-06-22 11:31:32 +02:00
Brian Clozel ea8fdd17c8 Upgrade to JDK21 EA build 27 2023-06-22 08:43:03 +02:00
Juergen Hoeller a6566bfd5f Merge branch '6.0.x' 2023-06-21 18:53:15 +02:00
Juergen Hoeller 8eb0a0b94e Upgrade to Tomcat 10.1.10, Netty 4.1.94, Mockito 5.4 2023-06-21 18:52:02 +02:00
Juergen Hoeller 09cf489c6b Test for supportsEventType mismatch with unrelated event type
See gh-30712
2023-06-21 18:24:38 +02:00
Sam Brannen abefc0aba0 Merge branch '6.0.x' 2023-06-21 17:54:16 +02:00
Sam Brannen 9a5290ea27 Apply project conventions to formatting 2023-06-21 17:50:42 +02:00
Sam Brannen 03b304f05c Merge branch '6.0.x' 2023-06-21 17:37:04 +02:00
Sam Brannen b3176208e2 Remove invalid Javadoc link 2023-06-21 17:36:36 +02:00
Juergen Hoeller 54e25e2fa6 Merge branch '6.0.x' 2023-06-21 17:18:55 +02:00
Juergen Hoeller 1dfe737d0e Avoid ResolvableType creation for interface/superclass check
See gh-30713
2023-06-21 17:17:58 +02:00
Juergen Hoeller dc2f513619 Correct supportsEventType checks for payload events
See gh-30712
2023-06-21 17:17:03 +02:00
Sam Brannen 83447663b4 Merge branch '6.0.x' 2023-06-21 16:21:34 +02:00
Sam Brannen 0eb33d09ac Ensure package-private init/destroy methods are always invoked
Prior to this commit, if an init/destroy method was package-private and
declared in a superclass in a package different from the package in
which the registered bean resided, a local init/destroy method with the
same name would effectively "shadow" the method from the different
package, resulting in only the local init/destroy method being invoked.

This commit addresses this issue by tracking package-private init
methods from different packages using their fully-qualified method
names, analogous to the existing support for private init/destroy
methods.

Closes gh-30718
2023-06-21 16:18:19 +02:00
Sam Brannen f67f98a1a7 Polishing 2023-06-21 15:56:50 +02:00
Stephane Nicoll b581a79eed Merge branch '6.0.x' 2023-06-21 14:51:00 +02:00
Stephane Nicoll 6c42f374c8 Consistently set target type in generated code
Previously, a bean definition that is optimized AOT could have
different metadata based on whether its resolved type had a generic or
not. This is due to RootBeanDefinition taking either a Class or a
ResolvableType doing fundamentally different things. While the former
sets the bean class which is to little use with an instance supplier,
the latter specifies the target type of the bean.

This commit sets the target type of the bean, using the existing
setter methods that take either a class or a ResolvableType and set the
same attribute consistently.

Closes gh-30689
2023-06-21 14:45:19 +02:00
Sam Brannen 6535614d78 Merge branch '6.0.x' 2023-06-21 14:22:11 +02:00
Sam Brannen 4879b56bb9 Test status quo for private init/destroy methods in AOT mode
This commit only tests which init/destroy methods are "registered" in
AOT mode.

This commit does NOT test that the registered methods can actually be
invoked in AOT mode: that will be addressed in a separate commit.

See gh-30692
2023-06-21 14:19:13 +02:00
Sam Brannen 2fd83aa764 Polish InitDestroyAnnotationBeanPostProcessor internals, etc. 2023-06-21 14:19:00 +02:00
Juergen Hoeller fa82683ce2 Merge branch '6.0.x' 2023-06-21 13:16:47 +02:00
Juergen Hoeller 93218a06ba Cache hasUnresolvableGenerics result for repeated checks
Closes gh-30713
2023-06-21 13:16:04 +02:00
Juergen Hoeller 714c3c59eb Accept unresolvable generics as long as raw event class matches
Closes gh-30712
2023-06-21 13:15:35 +02:00
Juergen Hoeller 1a201cd180 Merge branch '6.0.x'
# Conflicts:
#	spring-jcl/src/main/java/org/apache/commons/logging/LogFactory.java
2023-06-21 09:51:11 +02:00
Juergen Hoeller adcdefce43 Upgrade to Jetty 12.0.0.beta2 2023-06-21 09:49:26 +02:00
Juergen Hoeller 049a024dea Deprecate RootBeanDefinition(ResolvableType) constructor
Closes gh-30704
2023-06-21 09:48:00 +02:00
Juergen Hoeller 20bbebb299 Ensure Spring LogFactory contains all public methods from Apache LogFactory
Closes gh-30668
2023-06-21 09:47:16 +02:00
Maarten Coene 24457660e3 Ensure Spring LogFactory contains all public methods from Apache LogFactory (#30668) 2023-06-21 09:29:58 +02:00
Juergen Hoeller f1fb8cf03e Polishing 2023-06-20 22:53:12 +02:00
Juergen Hoeller 18c6aceee7 Consistent guard for Reactive Streams presence
Closes gh-30707
2023-06-20 22:51:23 +02:00
Sébastien Deleuze 24ddceea47 Merge branch '6.0.x' 2023-06-20 20:57:33 +02:00
Sébastien Deleuze 26f006509f Polish CoWebFilter javadoc 2023-06-20 20:56:47 +02:00
Sébastien Deleuze 82ec28b369 Add a CoExchangeFilterFunction for WebClient
This commit introduces a Kotlin-specific implementation
of the ExchangeFilterFunction interface that allows for
using coroutines, similar to what CoWebFilter does on
server-side.

Closes gh-30650
2023-06-20 20:54:38 +02:00
rstoyanchev db19f6395d Polishing
Closes gh-29768
2023-06-20 17:18:40 +01:00
Atsushi Yoshikawa b677ff20fe AbstractMessageConverter delegates null headers
See gh-29768
2023-06-20 17:18:40 +01:00
rstoyanchev b98c1ec36a Apply default value in case of null after conversion
Closes gh-29550
2023-06-20 17:18:40 +01:00
Stephane Nicoll 37ff9792be Merge branch '6.0.x' 2023-06-20 17:42:40 +02:00
Stephane Nicoll 089503aab7 Fix typo 2023-06-20 17:32:24 +02:00
Stephane Nicoll 74155e3d88 Do not invoke AspectJ hints generation if AspectJ is not present
See gh-28711
2023-06-20 17:26:08 +02:00
Sam Brannen 3344ab909b Merge branch '6.0.x' 2023-06-20 15:49:13 +02:00
Sam Brannen 564f33d5ef Polishing 2023-06-20 15:47:41 +02:00
Stephane Nicoll 828b39587f Merge branch '6.0.x' 2023-06-20 15:21:37 +02:00
Stephane Nicoll 83acd5b050 Document JPA configuration best practices with AOT
Closes gh-30498
2023-06-20 15:21:12 +02:00
Sam Brannen 0605172d4d Merge branch '6.0.x'
# Conflicts:
#	spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java
2023-06-20 13:29:06 +02:00
Sam Brannen 67798a7b52 Fix CSS classes in Javadoc HTML tables due to upgrade to Java 17
Closes gh-30701
2023-06-20 13:24:03 +02:00
rstoyanchev 089d938e15 Set throwExceptionIfNoHandlerFound=true and deprecate
Closes gh-29491
2023-06-19 17:18:09 +01:00
rstoyanchev c00508d6cf Raise and handle NoResourceFoundException
See gh-29491
2023-06-19 17:18:08 +01:00
Stephane Nicoll 83b0f4f394 Merge branch '6.0.x' 2023-06-19 15:47:26 +02:00
Stephane Nicoll 2b981651e1 Merge pull request #30601 from cwatzl
* pr/30601:
  Update copyright year of changed file
  Flag PathResourceResolver#resolve*Internal as @Nullable

Closes gh-30601
2023-06-19 15:47:12 +02:00
Stephane Nicoll 294cdba80c Update copyright year of changed file
See gh-30601
2023-06-19 15:44:04 +02:00
cwatzl 072a86149d Flag PathResourceResolver#resolve*Internal as @Nullable
See gh-30601
2023-06-19 15:37:16 +02:00
Brian Clozel 09cb844421 Instrument Scheduled methods for observability
This commit enhances the `ScheduledAnnotationBeanPostProcessor` to
instrument `@Scheduled` methods declared on beans. This will create
`"tasks.scheduled.execution"` observations for each execution of a
scheduled method. This supports both blocking and reactive variants.

By default, observations are no-ops; developers must configure the
current `ObservationRegistry` on the `ScheduledTaskRegistrar` by using a
`SchedulingConfigurer`.

Closes gh-29883
2023-06-19 08:55:08 +02:00
Juergen Hoeller 842569c9e5 Detect invalid transaction configuration for transactional event listeners
Closes gh-30679
2023-06-17 16:13:59 +02:00
Sam Brannen 3568f6c61a Merge branch '6.0.x' 2023-06-17 13:36:57 +02:00
Sam Brannen 8bb4c167e4 Polishing
See gh-30280
2023-06-17 13:36:37 +02:00
Juergen Hoeller 5bf213948c Merge branch '6.0.x'
# Conflicts:
#	spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java
2023-06-17 11:41:07 +02:00
Juergen Hoeller dff7aa4d4b Fall back to type-based creation if no bean of the given name exists
Closes gh-30683
2023-06-17 11:38:57 +02:00
Juergen Hoeller c634acd9ff Recognize error code 2628 as data integrity violation (MSSQL 2019)
Closes gh-30681
2023-06-17 11:38:41 +02:00
Sam Brannen 92c2fb45c7 Merge branch '6.0.x' 2023-06-16 13:40:18 +02:00
Sam Brannen ed5c19f53e Document that @Sql requires spring-jdbc & spring-tx on the classpath
Closes gh-30280
2023-06-16 13:39:35 +02:00
Sébastien Deleuze cd9c0e03e7 Merge branch '6.0.x' 2023-06-16 11:35:31 +02:00
Sébastien Deleuze 03420f811b Add reflection hints for AspectJ advice methods
Closes gh-28711
2023-06-16 11:33:57 +02:00
Sam Brannen 2dd34cf967 Clean up warnings in tests 2023-06-15 16:26:34 +02:00
Sam Brannen a2072de391 Update copyright headers 2023-06-15 16:21:13 +02:00
Sam Brannen 526d9eae7f Merge branch '6.0.x' 2023-06-15 16:20:19 +02:00
Sam Brannen 4565bcd757 Update copyright headers 2023-06-15 16:19:58 +02:00
Sam Brannen f22f439a68 Suppress deprecation warning due to upgrade to context-propagation 1.0.3
See gh-30657
2023-06-15 16:18:38 +02:00
Sam Brannen 7681d12eb0 Merge branch '6.0.x'
# Conflicts:
#	gradle.properties
2023-06-15 16:15:17 +02:00
Sam Brannen 5672284f53 Remove code duplication in RootBeanDefinition 2023-06-15 16:11:40 +02:00
Brian Clozel b077ae9259 Configure local JDK toolchains in CI staging job 2023-06-15 14:01:06 +02:00
Spring Builds 367f381fea Next development version (v6.0.11-SNAPSHOT) 2023-06-15 08:31:33 +00:00
Juergen Hoeller 362e189aa5 Adapt UserController example to current ServerRequestObservationContext
See gh-30013
2023-06-14 22:48:40 +02:00
Juergen Hoeller 96ae03b48f Merge branch '6.0.x' 2023-06-14 22:27:55 +02:00
Juergen Hoeller b9221656cc Declare ClassLoader for DeserializingConverter constructor as nullable
Closes gh-30670
2023-06-14 22:27:07 +02:00
Juergen Hoeller c30f6aa427 Polishing 2023-06-14 22:17:39 +02:00
Juergen Hoeller c276e5b679 Consistent use of 6.1 as generational version number 2023-06-14 21:58:45 +02:00
Juergen Hoeller f00a8cb3a3 Remove ServerWebExchange dependency in ServerRequestObservationContext
Avoiding cycle between http.server and web.server packages.

See gh-30013
2023-06-14 21:57:27 +02:00
Juergen Hoeller 220995b830 Move HandlerMethodValidator to web.method.annotation package
Avoiding cycle between web.method.support and web.method.annotation packages.

See gh-29825
2023-06-14 21:52:55 +02:00
Juergen Hoeller e344f3f869 Consistent treatment of new Spring system properties
See gh-30606
See gh-30571
2023-06-14 18:27:06 +02:00
Sébastien Deleuze 517a073f33 Use spring.native.precompute.log system property
This commit changes the Java system property used to
control PreComputeFieldFeature verbose logging from
spring.aot.precompute to spring.native.precompute.log
in order to clarify its purpose and avoid confusion
with AOT processing of JVM bytecode or Java sources.

See gh-30571
2023-06-14 17:58:08 +02:00
rstoyanchev dcba9475ba Allow custom ProblemDetail in ErrorResponse.Builder
Closes gh-30568
2023-06-14 16:48:35 +01:00
rstoyanchev 2e43412a82 Polishing in DefaultErrorResponseBuilder
Closes gh-30566
2023-06-14 16:48:35 +01:00
rstoyanchev 48861b67dd Add "title" message code to ErrorResponse.Builder
See gh-30566
2023-06-14 16:30:15 +01:00
rstoyanchev 61eaa9333b Polishing in ErrorResponse
See gh-30566
2023-06-14 16:30:15 +01:00
rstoyanchev 9c7b5cb3f5 Add ProblemDetail "type" message code
See gh-30566
2023-06-14 16:30:15 +01:00
Sam Brannen 53828cbfad Merge branch '6.0.x' 2023-06-14 14:39:06 +02:00
Sam Brannen aa2028127f Overhaul TestExecutionListener for Micrometer ObservationRegistry
This commit overhauls the TestExecutionListener for Micrometer's
ObservationRegistry that was introduced in the previous commit.

Specifically, this commit:

- Renames the listener to MicrometerObservationRegistryTestExecutionListener
  since the use of a ThreadLocal is an implementation detail that may
  change over time.

- Makes the listener package-private instead of public in order to
  allow the team greater flexibility in evolving this feature.

- Eagerly loads the ObservationThreadLocalAccessor class and verifies
  that it has a getObservationRegistry() method to ensure that the
  listener is properly skipped when SpringFactoriesLoader attempts to
  load it, if Micrometer 1.10.8+ is not on the classpath.

- Switches the listener's automatic registration order to 2500 in order
  to register it after the DependencyInjectionTestExecutionListener.

- Only tracks the previous ObservationRegistry in beforeTestMethod() if
  the test's ApplicationContext contains an ObservationRegistry bean.

- Properly removes the TestContext attribute for the previous
  ObservationRegistry in afterTestMethod().

- Introduces DEBUG logging for diagnostics.

- Adds an entry in the Javadoc for TestExecutionListener as well as in
  the Testing chapter in the reference manual.

Closes gh-30658
2023-06-14 14:36:05 +02:00
Marcin Grzejszczak a82659c837 Introduce TestExecutionListener for Micrometer ObservationRegistry
Prior to this commit, there was no way to specify the
ObservationRegistry that is registered in the given test's
ApplicationContext as the one that should be used by Micrometer's
ObservationThreadLocalAccessor for context propagation.

This commit introduces a TestExecutionListener for Micrometer's
ObservationRegistry in the Spring TestContext Framework. Specifically,
this listener obtains the ObservationRegistry registered in the test's
ApplicationContext, stores it in ObservationThreadLocalAccessor for the
duration of each test method execution, and restores the original
ObservationRegistry in ObservationThreadLocalAccessor after each test.

Co-authored-by: Sam Brannen <sam@sambrannen.com>
See gh-30658
2023-06-14 14:35:53 +02:00
Arjen Poutsma e3c602c43a Polishing
Restore thread interrupted status in JettyClientHttpRequest
2023-06-14 14:09:25 +02:00
Arjen Poutsma 02e9209e5c Merge pull request #30433 from srivatsa-cfp:main
* gh-30433:
  Polishing external contribution
  Add non-null assertions in DefaultEntityResponseBuilder
2023-06-14 13:49:20 +02:00
Arjen Poutsma 8a29bfba3f Polishing external contribution 2023-06-14 13:44:50 +02:00
Vatsa 0c817f0441 Add non-null assertions in DefaultEntityResponseBuilder
This commit adds various non-null assertions to
DefaultEntityResponseBuilder, in Spring MVC.

Closes gh-30433
2023-06-14 13:44:50 +02:00
Juergen Hoeller 326e27eab2 Merge branch '6.0.x' 2023-06-14 12:57:59 +02:00
Juergen Hoeller 3415b04c73 Use nanosecond precision for scheduling (aligned with calculations)
Closes gh-30666
2023-06-14 12:57:17 +02:00
Arjen Poutsma 5547361d18 Polishing
Store status code as HttpStatusCode instead of Object.
2023-06-14 12:05:49 +02:00
Arjen Poutsma 805d643347 Merge branch '6.0.x' 2023-06-14 11:45:04 +02:00
Arjen Poutsma a73ad52a8a Clarify removal of ResponseEntity::getStatusCodeValue 2023-06-14 11:29:21 +02:00
Juergen Hoeller b20a71a0d3 Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/util/ObjectUtils.java
2023-06-14 11:19:56 +02:00
Juergen Hoeller 13c32d80ba Upgrade to Undertow 2.3.7 and JRuby 9.4.3 2023-06-14 11:18:37 +02:00
Juergen Hoeller 3171a8b0e2 Align with 5.3.28 javadoc for isSimpleValueType
See gh-30661
2023-06-14 11:18:18 +02:00
Juergen Hoeller 3de4e931c7 Javadoc notes on isSimpleValueType in BeanUtils vs ClassUtils
See gh-30664
2023-06-14 10:40:14 +02:00
Juergen Hoeller 93345de687 Consistent Locale exposure for Bean Validation message assertions
See gh-29825
See gh-30198
2023-06-14 10:39:19 +02:00
Juergen Hoeller bbf3c6ecac Upgrade to Jackson 2.15
Closes gh-30665
2023-06-14 10:39:11 +02:00
Juergen Hoeller ca4de8f191 Consistent simple value type check
Includes UUID treatment for data binding and bean dependency checks.

Closes gh-30664
2023-06-14 09:37:39 +02:00
Juergen Hoeller 858ea1a8c5 Merge branch '6.0.x' 2023-06-14 09:32:30 +02:00
Juergen Hoeller 927d27b121 Consider UUID as simple value type with concise toString output
Closes gh-30661
2023-06-14 09:31:35 +02:00
Juergen Hoeller 1df5e9f30c Upgrade to Reactor 2022.0.8
Closes gh-30655
2023-06-14 09:31:02 +02:00
Sébastien Deleuze dd50da314d Update reference documentation index
Add "JVM Checkpoint Restore" to the Integration section.

See gh-30647
2023-06-14 08:49:52 +02:00
Juergen Hoeller 1f068fcdb8 Rename checkpoint property to "spring.context.checkpoint"
See gh-30606
2023-06-13 19:06:46 +02:00
rstoyanchev 85d81024a4 Add MethodParameter[] input to MethodValidationAdapter
This allows re-use of existing MethodParameter instances from controller
methods with cached metadata, and also ensures additional capabilities
such as looking up parameter annotations on interfaces.

See gh-29825
2023-06-13 17:40:57 +01:00
Sam Brannen e7c3e1c516 Merge branch '6.0.x' 2023-06-13 17:14:03 +02:00
Sam Brannen ed74b04520 Move web-related test for BeanUtilsRuntimeHints to spring-web
The dependency on spring-web from spring-beans makes it impossible to
import the projects in Eclipse IDE due to cycles between projects.

This commit therefore moves the web-related test for
BeanUtilsRuntimeHints to spring-web.

See gh-30491
2023-06-13 17:12:38 +02:00
Sam Brannen a268203832 Merge branch '6.0.x' 2023-06-13 16:27:20 +02:00
Sam Brannen 6cfb11a360 Upgrade to Micrometer BOM 1.10.8 and context-propagation 1.0.3
Cloes gh-30657
2023-06-13 16:21:26 +02:00
Sébastien Deleuze 9536dd14ef Polish PreComputeFieldFeature 2023-06-13 14:25:56 +02:00
Sébastien Deleuze c565df96f5 Remove System.out calls in PreComputeFieldFeature
Closes gh-30571
2023-06-13 14:25:32 +02:00
Juergen Hoeller 4b4a8af893 Merge branch '6.0.x' 2023-06-13 12:41:35 +02:00
Juergen Hoeller 3b263c5c3d Synchronize transaction begin for non-lazy default transactions as well
Lazy and read-only database transactions remain exposed to potential isolation level mismatches in case of concurrent transactions with custom isolation levels.

Closes gh-29997
2023-06-13 12:40:57 +02:00
rstoyanchev 1e3161b161 Expose MethodParameter in MissingServletRequestParameterException
See gh-26219
2023-06-13 11:29:35 +01:00
rstoyanchev 6b50b7b72a Initialize propertyName in TypeMismatchException
See gh-26219
2023-06-13 11:29:35 +01:00
rstoyanchev 96895c7759 Polishing in MethodArgumentNotValidException
See gh-30198
2023-06-13 11:29:35 +01:00
rstoyanchev 96c494c6ad Update error format in MethodArgumentNotValidException
1. Remove list markers (those can be provided in message).
2. Use ", and " between errors for readability.
3. Remove single quotes around errors.
4. If MessageSource is provided, use resolved message as is since in
that case applications have full control over each message.

Closes gh-30198
2023-06-13 11:29:35 +01:00
Sam Brannen 48548b29d6 Merge branch '6.0.x' 2023-06-13 11:58:37 +02:00
Sam Brannen f18a85e193 Polish null-safety documentation 2023-06-13 11:57:41 +02:00
Sébastien Deleuze 55b3b28aec Introduce JVM checkpoint/restore support documentation
Closes gh-30647
2023-06-13 10:52:12 +02:00
Sébastien Deleuze 6a26db80b6 Refine RouterFunctionMapping ordering consistency
This commit changes the order of RouterFunctionMapping defined
in WebMvcConfigurationSupport from 3 to -1 in order to achieve
better consistency between WebMVC and WebFlux. It also reduces
the surprise factor. That way, functional routes are always
before annotation-based ones.

Closes gh-30278
2023-06-13 08:17:54 +02:00
rstoyanchev ccf68878c7 Merge branch '6.0.x' 2023-06-12 16:12:03 +01:00
rstoyanchev f7d195782f Revert "Temporarily re-enable ReactorNetty2StompBrokerRelayIntegrationTests"
This reverts commit 7e52b803be.
2023-06-12 16:11:42 +01:00
rstoyanchev bbab4faf7a Method level only, empty RequestMapping matches "" and "/"
Closes gh-30293
2023-06-12 16:11:42 +01:00
Sam Brannen f7367ceae5 Merge branch '6.0.x' 2023-06-12 16:44:48 +02:00
Sam Brannen 3fb98b6a97 Polishing 2023-06-12 16:43:56 +02:00
Roland Weisleder dc4f46df9f Fix markup issue in Javadoc of QuartzCronField
Closes gh-30646
2023-06-12 16:40:11 +02:00
Stephane Nicoll 61c9cbc3f5 Retain active profiles used during AOT processing
This commit makes sure that profiles that have been explicitly enabled
during AOT optimizations are automatically enabled when using those
optimizations.

If other profiles are set at runtime, they take precedence over the ones
defined during AOT processing.

Closes gh-30421
2023-06-12 16:33:35 +02:00
Sébastien Deleuze 446b90172b Merge branch '6.0.x' 2023-06-12 16:01:35 +02:00
Sébastien Deleuze 80af7bedef Polish null-safety reference documentation 2023-06-12 16:00:13 +02:00
Juergen Hoeller 6501176081 Merge branch '6.0.x' 2023-06-12 12:59:55 +02:00
Juergen Hoeller f8c8873c99 Document which @Scheduled attributes support SpEL expressions
Closes gh-29290
2023-06-12 12:57:10 +02:00
Juergen Hoeller cc8c852c2b Specific check for parent of MethodInvocationInfo ClassLoader
See gh-30389
2023-06-12 12:57:10 +02:00
Sébastien Deleuze ac35ffef9e Merge branch '6.0.x' 2023-06-12 12:48:42 +02:00
Sébastien Deleuze fe7f8e2de5 Polish CoWebFilter 2023-06-12 12:48:01 +02:00
Rossen Stoyanchev 6b89cf94a3 Add method validation to WebFlux
See gh-29825
2023-06-12 11:37:55 +01:00
Rossen Stoyanchev bd054a4918 Add method validation to Spring MVC
See gh-29825
2023-06-12 11:37:55 +01:00
rstoyanchev cb04c3b335 Expose isReturnValue from MethodValidationException
See gh-29825
2023-06-12 11:37:55 +01:00
rstoyanchev 5c5d8e61ae Add BindingResultNameResolver option
See gh-29825
2023-06-12 11:37:55 +01:00
rstoyanchev 0fef380202 Add MethodValidator
See gh-29825
2023-06-12 11:37:55 +01:00
Rossen Stoyanchev cc8361cd93 Add MethodValidationResult
See gh-29825
2023-06-12 11:37:55 +01:00
rstoyanchev 8b53fecc06 Use List for violations in ParameterErrors
See gh-29825
2023-06-12 11:37:55 +01:00
Rossen Stoyanchev 425d5a94cb Adapt ConstraintViolation's from method validation
See gh-29825
2023-06-12 11:37:55 +01:00
rstoyanchev 38abee00e2 Rename MethodValidationTests and polishing
See gh-29825
2023-06-12 11:37:55 +01:00
rstoyanchev 082784e023 Extract delegate from MethodValidationInterceptor
See gh-29825
2023-06-12 11:37:55 +01:00
Juergen Hoeller 155a37d3a6 Merge branch '6.0.x' 2023-06-12 10:50:40 +02:00
Juergen Hoeller 0a5aff1b60 Specific check for parent of spring-aop ClassLoader
Also applied to getProxyClass now.

Closes gh-30389
2023-06-12 10:48:57 +02:00
Vedran Pavic 3d61d9e0d8 Handle custom JMS acknowledgment modes as client acknowledge (#30619)
This commit updates JmsAccessor to handle custom JMS acknowledgment
modes as client acknowledge, which is useful when working with JMS
providers that provide non-standard variations of CLIENT_ACKNOWLEDGE,
such as AWS SQS and its UNORDERED_ACKNOWLEDGE mode.
2023-06-12 10:46:22 +02:00
Sam Brannen f8a3253d12 Polishing 2023-06-11 16:32:16 +02:00
Sam Brannen b4ba80b09e Merge branch '6.0.x'
# Conflicts:
#	spring-test/src/main/java/org/springframework/test/context/cache/DefaultCacheAwareContextLoaderDelegate.java
2023-06-11 15:56:23 +02:00
Sam Brannen 1a26e17f41 Ensure context cache stats are logged when ApplicationContext fails to load
Closes gh-30635
2023-06-11 15:46:28 +02:00
Sam Brannen f6045e8e11 Move context failure tracking to the ContextCache
In the previous commit which introduced the new context failure threshold
support in the TestContext framework, the context failure tracking was
tied to an instance of DefaultCacheAwareContextLoaderDelegate.
Consequently, the feature was only supported within a given test class.

This commit therefore moves context failure tracking to the ContextCache
SPI (and DefaultContextCache) so that the feature applies to all test
classes within the current test suite (i.e., JVM).

This commit also includes the total failure count in the statistics
logged by the DefaultContextCache.

See gh-14182
2023-06-11 15:35:10 +02:00
Sam Brannen f0a3f776c2 Avoid duplication of constant in Javadoc 2023-06-11 15:20:23 +02:00
Sam Brannen 74dc07e736 Improve ContextCacheTestUtils 2023-06-11 15:15:35 +02:00
Sam Brannen c5eb4ed978 Introduce context failure threshold support in the TestContext framework
This set of commits introduces ApplicationContext "failure threshold"
support in the Spring TestContext Framework (TCF).

Specifically, this new feature avoids repeated attempts to load a
failing ApplicationContext in the TCF, based on a failure threshold
which defaults to 1 but can be configured via a system property.

See individual commits for details.

Closes gh-14182
2023-06-09 17:50:48 +02:00
Sam Brannen bff81d3056 Document test context failure threshold support in reference manual
See gh-14182
2023-06-09 17:45:12 +02:00
Sam Brannen c8bb7ded5d Improve Javadoc for DefaultCacheAwareContextLoaderDelegate
See gh-14182
2023-06-09 17:45:06 +02:00
Sam Brannen 56f3bd86cf Add integration tests for context failure threshold support
See gh-14182
2023-06-09 17:44:44 +02:00
Sam Brannen 52ae97cffc Make test context failure threshold configurable
This commit makes the failure threshold value configurable via a JVM
system property or Spring property named
"spring.test.context.failure.threshold".

See gh-14182
2023-06-09 17:43:29 +02:00
Sam Brannen c7ca5c81c3 Avoid repeated attempts to load failing ApplicationContext in the TCF
This commit introduces initial support for a new "context failure
threshold" feature in the Spring TestContext Framework (TCF).

Specifically, DefaultCacheAwareContextLoaderDelegate now tracks how
many times a failure occurs when attempting to load an
ApplicationContext and preemptively throws an IllegalStateException for
subsequent attempts to load the same context if the configured failure
threshold has been exceeded.

See gh-14182
2023-06-09 17:40:28 +02:00
Sébastien Deleuze ccb8db41f0 Merge branch '6.0.x' 2023-06-09 15:21:54 +02:00
Sébastien Deleuze 439bcd6715 Polishing 2023-06-09 15:19:42 +02:00
Sébastien Deleuze 4e33d0c293 Add missing hint for ResourceEditor
Closes gh-30628
2023-06-09 15:19:18 +02:00
Sébastien Deleuze 46fe7f5bea Merge branch '6.0.x' 2023-06-09 14:17:45 +02:00
Sébastien Deleuze 9b4e0e9837 Add missing hint for converting String to URI
Closes gh-30627
2023-06-09 14:14:54 +02:00
Sébastien Deleuze 071d6a2a5a Introduce hints for finding hints by conventions
Closes gh-30491
2023-06-09 14:14:54 +02:00
Sam Brannen 54904de77d Merge branch '6.0.x' 2023-06-09 11:52:20 +02:00
Sam Brannen d7d0292654 Document @DirtiesContext semantics when declared at class & method level
Closes gh-30623
2023-06-09 11:49:15 +02:00
Sam Brannen 2817dce78f Polish @DirtiesContext Javadoc 2023-06-09 11:40:31 +02:00
Sam Brannen 698acd32a7 Configure logger per concrete @DirtiesContext TestExecutionListener 2023-06-09 11:38:36 +02:00
Sam Brannen f36327b380 Exclude commons-logging dependency in spring-test 2023-06-09 11:37:08 +02:00
Sam Brannen dbd32f8f11 Merge branch '6.0.x' 2023-06-09 10:30:16 +02:00
Johnny Lim ea9c0ae6c0 Fix test fixture value in QualifierConfiguration
Closes gh-30624
2023-06-09 10:29:39 +02:00
Juergen Hoeller ef2b47e202 Merge branch '6.0.x' 2023-06-08 17:46:19 +02:00
Juergen Hoeller c16f582ed8 Consistent equals implementations in AOP support classes 2023-06-08 17:42:49 +02:00
Juergen Hoeller 6931106c5e Redesign inner Pointcut implementations as standalone classes
Avoids exposure of implicit Advisor instance state in Pointcut instance.

See gh-30621
2023-06-08 17:42:49 +02:00
Juergen Hoeller 045df81f14 Reduce ProxyCallbackFilter to key-only role after class generation
Avoids memory leaks from ProxyCallbackFilter-contained Advisors.
Includes consistent ProxyCallbackFilter#equals/hashCode methods.

Closes gh-26266
Closes gh-30615
2023-06-08 17:42:49 +02:00
Juergen Hoeller e210f08dce Declare Advisor#isPerInstance() as default method
Includes INSTANCE constants on default factory classes.

Closes gh-30614
2023-06-08 17:42:49 +02:00
Sam Brannen 60e8dbf11d Polishing 2023-06-08 17:41:22 +02:00
Sébastien Deleuze 01414d0b3d Merge branch '6.0.x' 2023-06-08 17:33:50 +02:00
Vedran Pavic 2317bef021 Add missing @Nullable in DefaultJmsListenerContainerFactory
Closes gh-30620
2023-06-08 17:32:59 +02:00
Arjen Poutsma ad5bf2fac8 Merge branch '6.0.x' 2023-06-08 16:40:44 +02:00
Arjen Poutsma ce5189a0a0 Default ServerWebExchange::cleanupMultipart implementation
This commit provided a default implementation for ServerWebExchange::cleanupMultipart.

See gh-30590
2023-06-08 16:31:53 +02:00
Sam Brannen a28ef22113 Merge branch '6.0.x' 2023-06-08 16:06:31 +02:00
Johnny Lim 7a4ed38cd4 This PR adds Javadoc for RegisteredBean.resolveAutowiredArgument()
See gh-30401
Closes gh-30609
2023-06-08 16:06:14 +02:00
Sam Brannen fe55b49c7d Consistently use mergedConfig as variable name for MergedContextConfiguration 2023-06-08 15:53:38 +02:00
Sam Brannen e32a92daa7 Polishing 2023-06-08 15:44:57 +02:00
Arjen Poutsma d7970e4ab8 Support JAXBElement in Jaxb2XmlEncoder
This commit introduces support for JAXBElements in the Jaxb2XmlEncoder.

Closes gh-30552
2023-06-08 15:30:41 +02:00
Sébastien Deleuze 2f78b42133 Refine Kotlin ParameterNameDiscoverer tests
Related to gh-30052, we should improve ParameterNameDiscoverer
Kotlin tests to make sure DefaultParameterNameDiscoverer behaves
as expected and is consistent with
KotlinReflectionParameterNameDiscoverer behavior.

Closes gh-30618
2023-06-08 15:27:06 +02:00
Arjen Poutsma f4ef057e9e Merge branch '6.0.x' 2023-06-08 14:42:24 +02:00
Arjen Poutsma c1fe57135e Clean multipart up only when data is read
This commit ensures that any storage used for multipart handling only
gets cleaned up if multipart data is actually retrieved via
ServerWebExchange::getMultipartData.

Closes gh-30590
2023-06-08 14:23:47 +02:00
Sébastien Deleuze 448786bfd0 Upgrade to Kotlin 1.8.22
See gh-29754
2023-06-08 09:29:06 +02:00
Sam Brannen 0093d6e34d Polish contribution
See gh-30587
2023-06-07 19:13:05 +02:00
luohongtu 324c6057fd Remove duplicate code in RequestResponseBodyMethodProcessor
Closes gh-30587
2023-06-07 19:13:05 +02:00
Juergen Hoeller 759ab23c45 Release shared JMS Connection on Single/CachingConnectionFactory.stop()
See gh-30612
2023-06-07 18:40:56 +02:00
Juergen Hoeller 1b62b6dd89 Merge branch '6.0.x' 2023-06-07 17:23:09 +02:00
Juergen Hoeller 2c8d1b7bff Polishing 2023-06-07 17:21:59 +02:00
Juergen Hoeller bd63c35b0b DefaultMessageListenerContainer tests for stop-and-restart
See gh-30612
2023-06-07 17:21:53 +02:00
Juergen Hoeller c052a02592 Ignore null message when introspecting resource cleanup failure
Closes gh-30597
2023-06-07 17:21:41 +02:00
Juergen Hoeller b3597f3d99 Polishing 2023-06-07 17:11:46 +02:00
Juergen Hoeller 06bb6dbcff Release shared JMS Connection before stop completion callback
Closes gh-30612
2023-06-07 17:11:35 +02:00
Sam Brannen 73e9de7b5f Simplify Javadoc 2023-06-07 17:08:11 +02:00
Sam Brannen e535ef37c7 Merge branch '6.0.x' 2023-06-07 16:02:04 +02:00
Johnny Lim dd926af5a8 This PR adds Javadoc for RegisteredBean.resolveAutowiredArgument()
See gh-30401
Closes gh-30609
2023-06-07 16:01:48 +02:00
Johnny Lim a726b5109a This PR adds Javadoc for RegisteredBean.resolveAutowiredArgument()
See gh-30401
Closes gh-30609
2023-06-07 16:00:30 +02:00
Johnny Lim 7c817dd34b Remove LocalVariableTableParameterNameDiscoverer reference in doc
See gh-29559
Closes gh-30611
2023-06-07 15:49:56 +02:00
Sam Brannen c9165470f2 Update test
See gh-30610
2023-06-07 15:04:28 +02:00
Sam Brannen 61816d0076 Merge branch '6.0.x' 2023-06-07 14:59:14 +02:00
Sam Brannen 5ad853ef5b Do not precede indexed access with a dot in SpEL AST representation
Prior to this commit, if a Spring Expression Language (SpEL) expression
contained indexed access to an object, the generated AST String
representation incorrectly included a dot ('.') before the index access.

For example, 'property[0]' had a generated AST string representation of
'property.[0]'.

This commit addresses this by reworking the logic in
CompoundExpression.toStringAST().

Closes gh-30610
2023-06-07 14:45:52 +02:00
Sam Brannen aa2a067489 Merge branch '6.0.x' 2023-06-07 13:36:05 +02:00
Sam Brannen dfbed616ba Update copyright headers 2023-06-07 13:17:14 +02:00
Sam Brannen 94214562d0 Polish contribution
See gh-30283
2023-06-07 13:15:12 +02:00
SW be94e1a2fb Replace switch statements with enhanced switch statements for consistency
Closes gh-30283
2023-06-07 13:02:08 +02:00
Sam Brannen 714d380ec0 Merge branch '6.0.x' 2023-06-07 12:01:54 +02:00
Sam Brannen f2ae106c32 Update deprecation Javadoc regarding "for removal in 6.2"
See gh-30608
2023-06-07 12:00:27 +02:00
Arjen Poutsma df7223f39c Remove APIs marked for removal
See gh-30604
2023-06-07 10:20:27 +02:00
Juergen Hoeller 7f6f47b97b Property-driven onRefresh checkpoint during application context bootstrap
Closes gh-30606
2023-06-06 19:18:34 +02:00
Sam Brannen b9e972c248 Polishing 2023-06-06 16:11:40 +02:00
Sébastien Deleuze 66a1be2d86 Enable KotlinScriptTemplateTests with Java 19
No support yet for Java 21.

Closes gh-29249
2023-06-06 15:49:04 +02:00
Sébastien Deleuze 717915e6ac Upgrade to Dokka 1.8.20
Closes gh-30605
2023-06-06 15:24:12 +02:00
Sam Brannen c8c8f5722b Support letters other than A-Z in identifiers in SpEL
Prior to this commit, only the letters 'A' - 'Z' (ignoring case) were
supported in identifiers (i.e., property, field, and variable names).

This known (yet undocumented) limitation prevented the use of characters
such as 'ü', 'ñ', 'é' as well as letters from other character sets such
as Chinese, Japanese, Cyrillic, etc.

This commit lifts that restriction by delegating to Character.isLetter()
to determine if a character in a SpEL expression is a letter.

Closes gh-30580
2023-06-06 14:14:15 +02:00
Sam Brannen cd610b3ed1 Merge branch '6.0.x' 2023-06-06 12:46:15 +02:00
Sam Brannen 7b20aefecf Improve error message for unsupported character in SpEL expression
Prior to this commit, when an unsupported character such as "ü" was
encountered in a SpEL expression, the error message was:

Cannot handle (252) 'ü'

With this commit, the error message is now similar to:

Unsupported character 'ü' (252) encountered at position 5 in expression.

See gh-30580
Closes gh-30602
2023-06-06 12:45:05 +02:00
Sam Brannen 93deb0a584 Polishing 2023-06-06 11:54:38 +02:00
Sam Brannen 05eab703cc Polishing 2023-06-06 11:29:25 +02:00
Brian Clozel c0cd55a8fa Clarify error handling for reactive scheduled methods
This commit adds a note in the reference documentation stating that
`ErrorHandler` infrastructure is not involved when reactive methods send
an error signal: the exception is sent as a message in the pipeline and
is not thrown from the task `Runnable`.

See gh-23533
2023-06-05 14:13:44 +02:00
Simon Baslé 35052f2113 Support @Scheduled fixedDelay/fixedRate on Publisher-returning methods
This commit adds support for `@Scheduled` annotation on reactive
methods and Kotlin suspending functions.

Reactive methods are methods that return a `Publisher` or a subclass
of `Publisher`. The `ReactiveAdapterRegistry` is used to support many
implementations, such as `Flux`, `Mono`, `Flow`, `Single`, etc.
Methods should not take any argument and published values will be
ignored, as they are already with synchronous support.

This is implemented in `ScheduledAnnotationReactiveSupport`, which
"converts" Publishers to `Runnable`. This strategy keeps track of
active Subscriptions in the `ScheduledAnnotationBeanPostProcessor`,
in order to cancel them all in case of shutdown.
The existing scheduling support for tasks is reused, aligning the
triggering behavior with the existing support: cron, fixedDelay and
fixedRate are all supported strategies.

If the `Publisher` errors, the exception is logged at warn level and
otherwise ignored. As a result new `Runnable` instances will be
created for each execution and scheduling will continue.
The only difference with synchronous support is that error signals
will not be thrown by those `Runnable` tasks and will not be made
available to the `org.springframework.util.ErrorHandler` contract.
This is due to the asynchronous and lazy nature of Publishers.

Closes gh-23533
Closes gh-28515
2023-06-05 14:13:44 +02:00
Juergen Hoeller 53f891226e Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/core/CollectionFactory.java
2023-06-05 13:59:37 +02:00
Juergen Hoeller cdc4497664 Restore creation of plain HashSet/HashMap for direct HashSet/HashMap type
Closes gh-30596
2023-06-05 13:57:59 +02:00
Juergen Hoeller 4fb4c95220 Merge branch '6.0.x' 2023-06-05 10:53:29 +02:00
Juergen Hoeller 6cc084dbde Consistent javadoc references to JdbcTransactionManager 2023-06-05 10:52:33 +02:00
Juergen Hoeller 974e10379a Add nested propagation support to R2dbcTransactionManager
Closes gh-30134
2023-06-05 10:45:47 +02:00
Juergen Hoeller 22ef48bec2 Shorten constant names to BUILD and RUN (for consistent spelling)
See gh-30511
2023-06-05 10:45:02 +02:00
Juergen Hoeller b8b88e638b Upgrade to Checkstyle 10.12 2023-06-04 18:54:30 +02:00
Juergen Hoeller 837327f530 Merge branch '6.0.x'
# Conflicts:
#	build.gradle
2023-06-04 18:43:46 +02:00
Juergen Hoeller 4be813bbee Upgrade to Groovy 4.0.12, Tomcat 10.1.9, Netty 4.1.93, Undertow 2.3.6, Protobuf 3.23.2, Picocli 4.7.4, Checkstyle 10.12 2023-06-04 18:42:21 +02:00
Juergen Hoeller 65617f1e75 Add isolation level test and restore null return value from beginTransaction
See gh-29997
2023-06-04 18:41:38 +02:00
Juergen Hoeller e224c71119 Merge branch '6.0.x' 2023-06-04 17:25:35 +02:00
Juergen Hoeller aaebf5749c 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 17:19:27 +02:00
Sam Brannen 5bc80fc094 Disable SpEL selector support in WebSocket messaging by default
This commit disables support for evaluating SpEL expressions from
untrusted sources by default. Specifically, this applies to the
SpEL-based 'selector' header support in WebSocket messaging, which
includes the DefaultSubscriptionRegistry and the classes used to
configure the 'selector' header name (SimpleBrokerMessageHandler and
SimpleBrokerRegistration).

The selector header support remains in place but will have to be
explicitly enabled beginning with Spring Framework 6.1.

For example, a custom implementation of WebSocketMessageBrokerConfigurer
can override the configureMessageBroker() method and configure the
selector header name as follows.

  registry.enableSimpleBroker().setSelectorHeaderName("selector");

Closes gh-30550
2023-06-04 17:02:02 +02:00
Sam Brannen 75466fee8d Merge branch '6.0.x' 2023-06-04 16:40:23 +02:00
Sam Brannen 24fa8793b1 Update copyright headers 2023-06-04 16:36:52 +02:00
Sam Brannen 4f10f559f7 Suppress warnings 2023-06-04 16:36:20 +02:00
Sam Brannen bedf5f26fe Merge branch '6.0.x' 2023-06-04 16:27:23 +02:00
Sam Brannen 2f35e7756b Integration test status quo for SpEL 'selector' support in messaging
See gh-30550
2023-06-04 16:25:21 +02:00
Sam Brannen cc50af08e4 Enhance unit tests for status quo for SpEL 'selector' support in messaging
See gh-30550
2023-06-04 16:23:42 +02:00
Sam Brannen d08e4081c2 Polishing 2023-06-04 15:59:12 +02:00
Juergen Hoeller 2689bab652 Merge branch '6.0.x' 2023-06-03 17:19:06 +02:00
Juergen Hoeller 9751987dc1 Avoid unnecessary auto-commit check for proper transaction begin
Closes gh-30508
2023-06-03 17:17:47 +02:00
Juergen Hoeller d2906253f1 Fall back to plain setObject call for non-supported SQL type
Closes gh-30556
2023-06-03 17:16:36 +02:00
Juergen Hoeller e82dd14f0f Merge branch '6.0.x'
# Conflicts:
#	spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java
2023-06-02 23:30:04 +02:00
Juergen Hoeller 4b8adf2dcc Polishing 2023-06-02 23:28:14 +02:00
Juergen Hoeller c68552556f Revise TargetSource implementations for proper nullability
Includes hashCode optimization in AbstractBeanFactoryBasedTargetSource.
Includes ThreadLocal naming fix in ThreadLocalTargetSource.

Closes gh-30576
Closes gh-30581
2023-06-02 23:26:58 +02:00
Juergen Hoeller b738a20233 Consistently publish events from CompletableFuture
Closes gh-30578
2023-06-02 23:25:35 +02:00
Juergen Hoeller cca8fbd3de Log warning in case of standard Commons Logging discovery
Closes gh-30575
2023-06-02 23:25:08 +02:00
Juergen Hoeller 1dba8f6add Polishing 2023-06-02 20:45:26 +02:00
Juergen Hoeller 25a1e8d414 Reset common caches before LifecycleProcessor-initiated checkpoint
See gh-29921
2023-06-02 20:42:37 +02:00
Juergen Hoeller 8c6287ef7b Expose parameter/field name for non-JavaBeans type conversion
Supports name-bound PropertyEditor registrations on data classes.
Includes consistent support for field-aware method parameters.

Closes gh-28284
2023-06-02 20:42:05 +02:00
Juergen Hoeller 322cbca0dc Support for async/reactive close methods (e.g. R2DBC)
Closes gh-26991
2023-06-02 20:40:55 +02:00
Sam Brannen 2685a35c3a Merge branch '6.0.x' 2023-06-01 15:02:42 +02:00
Sam Brannen 21397a67c6 Test status quo for SpEL 'selector' support in messaging
Prior to this commit, the tests we had in place for SpEL 'selector'
support did not assert what happens when a selector expression does not
match or when a selector header is not present.

See gh-30550
2023-06-01 14:57:50 +02:00
Sam Brannen e8ab53e76d Polishing 2023-06-01 14:57:50 +02:00
Stephane Nicoll 8606d9b581 Merge branch '6.0.x' 2023-05-31 12:27:02 +02:00
Stephane Nicoll 5b471a5349 Merge pull request #30570 from kihyuk-sung
* pr/30570:
  Polish "Fix invalid link in transaction resources"
  Fix invalid link in transaction resources

Closes gh-30570
2023-05-31 12:26:48 +02:00
Stephane Nicoll 08240bbcac Polish "Fix invalid link in transaction resources"
See gh-30570
2023-05-31 12:26:32 +02:00
K d719f3fc06 Fix invalid link in transaction resources
See gh-30570
2023-05-31 12:20:06 +02:00
Arjen Poutsma 3d63cbf076 Introduce JettyClientHttpRequestFactory
This commit introduces an implementation of ClientHttpRequestFactory
based on Jetty's HttpClient.

Closes gh-30564
2023-05-31 10:36:57 +02:00
rstoyanchev 67f88482e6 Merge branch '6.0.x' 2023-05-30 17:36:08 +01:00
rstoyanchev 938dff7bbe Remove (recently committed) erroneous character in test 2023-05-30 17:35:50 +01:00
rstoyanchev b3f5d20ad8 Merge branch '6.0.x' 2023-05-30 17:18:01 +01:00
rstoyanchev 162ccdd155 Consistent handling of parts in HttpRequestValues
Closes gh-30520
2023-05-30 17:17:31 +01:00
rstoyanchev f1594312cd Polishing in HttpRequestValues and tests
See gh-30520
2023-05-30 17:17:31 +01:00
rstoyanchev 7629ea5672 Update docs to mention Boot's HttpMessageConverters
Closes gh-30538
2023-05-30 17:17:31 +01:00
rstoyanchev 454a85978f Allow fallback on subclass of ProblemDetail
Closes gh-30533
2023-05-30 17:17:31 +01:00
Arjen Poutsma 49d688f99c Mark ClientHttpResponse::getRawStatusCode for removal 2023-05-30 15:37:58 +02:00
Arjen Poutsma 033bebf8cd Remove buffering from ClientHttpRequest implementations
This commit ensures that ClientHttpRequest implementations implement
StreamingHttpOutputMessage, so that they do not expose an OutputStream,
but store a handle capable of writing to a stream instead.

Closes gh-30557
2023-05-30 15:37:58 +02:00
Sébastien Deleuze 1ce22bdcc1 Remove MethodArgumentNotValidException(Executable, BindingResult)
Closes gh-30559
2023-05-30 12:45:01 +02:00
Sébastien Deleuze 4e678479b9 Merge branch '6.0.x' 2023-05-30 12:44:47 +02:00
Sébastien Deleuze 2cbc7eed73 Always use MethodArgumentNotValidException(MethodParameter, BindingResult) constructor
gh-23846 introduced a new
MethodArgumentNotValidException(Executable, BindingResult)
constructor that can be advantageously replaced by using
MethodArgumentNotValidException(MethodParameter, BindingResult)
in ModelAttributeMethodProcessor.

This commit updates ModelAttributeMethodProcessor accordingly,
and deprecates MethodArgumentNotValidException(Executable,
BindingResult) in favor of
MethodArgumentNotValidException(MethodParameter, BindingResult).

Closes gh-30558
2023-05-30 12:41:30 +02:00
Sébastien Deleuze 7a05f81844 Polish ModelAttributeMethodProcessor#constructAttribute Javadoc 2023-05-30 12:07:52 +02:00
Brian Clozel f69db61147 Fix JDK21 EA build URL 2023-05-30 11:51:39 +02:00
Brian Clozel 655f5eb1e2 Upgrade to JDK21 EA 24 in CI build 2023-05-30 10:49:42 +02:00
Brian Clozel e45edff4a4 Merge branch '6.0.x' 2023-05-30 10:37:50 +02:00
Brian Clozel 71b2154ec8 Remove libs-spring-framework-build repository
This commit removes the build configuration for the repository
"libs-spring-framework-build", as it is not needed anymore for the
dependencies it contains.
2023-05-30 10:36:53 +02:00
Stephane Nicoll fc309ee314 Merge branch '6.0.x' 2023-05-30 09:15:55 +02:00
Stephane Nicoll a716391aab Merge pull request #30554 from scordio
* pr/30554:
  Update copyright year of changed file
  Fix `FileSystemUtils::deleteRecursively` Javadoc

Closes gh-30554
2023-05-30 09:15:43 +02:00
Stephane Nicoll 09b2e5d0fb Update copyright year of changed file
See gh-30554
2023-05-30 09:13:29 +02:00
Stefano Cordio c6b2d2e1d9 Fix FileSystemUtils::deleteRecursively Javadoc
See gh-30554
2023-05-30 09:11:48 +02:00
Sébastien Deleuze 8a5f655a5c Merge branch '6.0.x' 2023-05-26 19:15:03 +02:00
Sébastien Deleuze 1cf6d1dd9d Refine GraalVM tracing agent detection
This commit refines how GraalVM tracing agent detection works
for both test and application executions.

It rolls back the introduction of TestAotDetector done in 111309605c
and instead updates AotDetector.useGeneratedArtifacts()
to only detect "buildtime" and "runtime" imagecode system
property values by leveraging a new method
NativeDetector.inNativeImage(NativeDetector.Context...).

This commit also adds a workaround for
https://github.com/oracle/graal/issues/6691.

Closes gh-30511
2023-05-26 19:10:21 +02:00
Simon Baslé 3f14ebc4cf Polish ReactiveTypeHandler when checking wildcard ndjson subtype
This commit polishes the previous change, ensuring that if the request
uses a wildcard subtype with an ndjson suffix then the wildcard isn't
present in the response's Content-Type.

Insteand, in that case we would fall back to `applicatin/x-ndjson` (the
base ndjson media type), assuming that the requester is only interested
in the ndjson nature of the underlying representation and not in the
specific semantics of any subtype.

See commit 9332b3f
See gh-26817
2023-05-26 15:23:09 +02:00
Remus Richard Dumitrache 4d8f6c1b41 Support parsing long millisecond timestamps in InstantFormatter
This commit adds support of parsing a simple long from a String and
turning it to an `Instant` by considering it represents a timestamp in
milliseconds (see `Instant.ofEpochMilli`). Failing to parse a long from
the String, the previous algorithm is used: first check for an RFC-1123
representation then an ISO_INSTANT representation.

See gh-30312
Closes gh-30546
2023-05-26 12:08:26 +02:00
Juergen Hoeller 7150c23e93 Merge branch '6.0.x' 2023-05-26 11:03:48 +02:00
Juergen Hoeller 8b8d147480 Avoid Autowired shortcut resolution for NullBean values
Includes getBean documentation against NullBean values.

Closes gh-30485
2023-05-26 11:03:10 +02:00
Brian Clozel 009179fed7 Merge branch '6.0.x' 2023-05-25 20:18:10 +02:00
Brian Clozel 8fe21b8ef9 Build Antora docs as part of CI check job
This commit adds the "antora" task to the check-project script in order
to check for documentation failures when pushing to the current branch.
The actual documentation is build is performed on the docs-build branch.

Closes gh-30528
2023-05-25 20:12:04 +02:00
Brian Clozel 7c9f5d05db Remove asciidoctor Gradle plugins
This part of the build has been replaced with Antora.
2023-05-25 20:07:50 +02:00
Brian Clozel 6dbd446fc8 Update CI pipeline 2023-05-25 19:17:29 +02:00
Brian Clozel 110b809b7d Update CI pipeline 2023-05-25 19:15:32 +02:00
Juergen Hoeller a45d438f05 Enforce JPA bootstrap failure for incomplete Hibernate Validator setup
Closes gh-30549
2023-05-25 18:50:57 +02:00
Juergen Hoeller cabc41bcd6 Merge branch '6.0.x' 2023-05-25 18:46:50 +02:00
Juergen Hoeller 5e625c8d2e Polishing 2023-05-25 18:45:32 +02:00
Juergen Hoeller 3f648f54c5 Set hibernate.cdi.extensions (for SpringBeanContainer on Hibernate 6.2)
Closes gh-30545
2023-05-25 18:45:27 +02:00
Simon Baslé 5977bb05ca Port BeanPropertyRowMapper and DataClassRowMapper for r2dbc
This commit ports and adapts spring-jdbc's `BeanPropertyRowMapper` and
`DataClassRowMapper` to spring-r2dbc, allowing to `map` rows or
outParameters to object instances, data classes or records.

See gh-26021
Closes gh-30530
2023-05-25 17:40:52 +02:00
Simon Baslé 9332b3f690 Have ReactiveTypeHandler consider +x-ndjson suffix as streaming
This commit adds `application/*+x-ndjson`, a wildcard media type which
covers all types that can be parsed as nd-json, to the list of media
types the ReactiveTypeHandler considers for a streaming response in
WebMVC.

As a result, a request which for example `Accept` the
`application/vnd.myapp.v1+x-ndjson` media type will generate a response
with the same `Content-Type`, with newline-delimited json objects being
streamed in the response body.

Closes gh-26817
2023-05-25 16:00:34 +02:00
Sam Brannen 5f13b2b35b Merge branch '6.0.x' 2023-05-25 14:03:01 +02:00
Sam Brannen d61074268a Polish Javadoc for StatementFilterFunction 2023-05-25 13:58:00 +02:00
Sam Brannen 01abd521e2 Merge branch '6.0.x' 2023-05-25 13:48:15 +02:00
Sam Brannen cfb3a45479 Improve Javadoc for ExchangeFilterFunction
See gh-30543
2023-05-25 13:47:37 +02:00
galingerv 7d7d7bcced Fix typos in Javadoc for ExchangeFilterFunction
Closes gh-30543
2023-05-25 13:40:18 +02:00
Sam Brannen f91fae5dfb Avoid deprecation warnings for imports 2023-05-25 13:30:54 +02:00
Sam Brannen 7169577f9c Merge branch '6.0.x' 2023-05-24 16:57:30 +02:00
Sam Brannen 6dfd330fa5 Polish JavaMailSenderTests 2023-05-24 16:54:44 +02:00
Sam Brannen 72152ff1f3 Merge branch '6.0.x' 2023-05-24 14:02:51 +02:00
Evgeny Nikonchuk 7f9349b7ae Remove non-empty filename check in ContentDisposition builder
This commit ensures that the ContentDisposition.Builder is consistent
with ContentDisposition and accepts null/empty filenames.

Closes gh-30537
2023-05-24 13:53:46 +02:00
Juergen Hoeller 1d6246d700 Merge branch '6.0.x' 2023-05-23 20:34:58 +02:00
Juergen Hoeller 4c8f1910c8 Align HibernateJpaVendorAdapter with Hibernate ORM 6.2
Includes documentation and test revisions.

Closes gh-30288
2023-05-23 20:33:19 +02:00
Juergen Hoeller 5441796675 Polishing 2023-05-23 20:01:28 +02:00
Juergen Hoeller 876e417eb4 Javadoc for setVariables and registerFunction
See gh-30045
2023-05-23 20:01:02 +02:00
rstoyanchev e6c812e2ab Merge branch '6.0.x' 2023-05-23 15:13:04 +01:00
rstoyanchev 3b364c2a3d Add cached-antora-playbook.yml back to .gitignore
See gh-30481
2023-05-23 15:12:35 +01:00
rstoyanchev 0e5e2f5d2e Merge branch '6.0.x' 2023-05-23 15:10:10 +01:00
rstoyanchev 0930407d0e Revert "Download the playbook to build dir"
This reverts commit d8f6567c89.

See gh-30481
2023-05-23 15:05:11 +01:00
rstoyanchev 5bca25fe44 Remove commented out check->antora task dependency
Instead of having antora run always, which happens regardless of
whether anything has changed, we'll have it invoked as part of the CI
build, and we'll have to run it locally ourselves when necessary.

See gh-30481
2023-05-23 14:55:39 +01:00
Sam Brannen ab253470f0 Update copyright headers 2023-05-23 15:12:32 +02:00
Sam Brannen 02f152c6e1 Merge branch '6.0.x' 2023-05-23 15:11:19 +02:00
Sam Brannen 4bb12c4ba4 Update copyright headers 2023-05-23 15:10:08 +02:00
Sam Brannen 8d6d99731f Delete unused code 2023-05-23 15:09:38 +02:00
Sam Brannen b5902f4fbf Suppress unused warnings in tests 2023-05-23 15:09:10 +02:00
Sam Brannen 791802fdf7 Merge branch '6.0.x' 2023-05-23 12:41:26 +02:00
Sam Brannen a455317122 Treat directly registered class as configuration 'lite' mode candidate
Prior to this commit, if a non-annotated [1] class was registered
directly with an ApplicationContext -- for example, via
AnnotatedBeanDefinitionReader, AnnotationConfigApplicationContext, or
@ContextConfiguration -- it was not considered a configuration class in
'lite' mode unless @Bean methods were declared locally. In other words,
if the registered class didn't declare local @Bean methods but rather
extended a class that declared @Bean methods, then the registered class
was not parsed as a @Configuration class in 'lite' mode, and the @Bean
methods were ignored.

Whereas, a non-annotated class registered via @Import is always
considered to be a configuration class candidate.

To address this discrepancy between @Import'ed classes and classes
registered directly with an ApplicationContext, this commit treats any
class registered via AnnotatedBeanDefinitionReader as a @Configuration
class candidate with @Bean 'lite' mode semantics.

[1] In this context, "non-annotated" means a class not annotated (or
meta-annotated) with @Component, @ComponentScan, @Import, or
@ImportResource.

Closes gh-30449
2023-05-23 12:19:58 +02:00
Sam Brannen f4f8066877 Merge branch '6.0.x' 2023-05-23 11:36:40 +02:00
Sam Brannen a8b400803b Upgrade to TestNG 7.8.0 2023-05-23 11:36:25 +02:00
Sam Brannen d95ecbe0fd Merge branch '6.0.x'
# Conflicts:
#	spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java
2023-05-23 11:29:10 +02:00
greg.lee fa85657801 Introduce method in MockHttpServletRequestBuilder to set remote address
Co-authored-by: Sam Brannen <sam@sambrannen.com>
See gh-30510
Closes gh-30497
2023-05-23 11:26:26 +02:00
Sébastien Deleuze cba77c6909 Merge branch '6.0.x' 2023-05-23 11:21:03 +02:00
Sébastien Deleuze 424daede2f Add missing EntityManagerFactory hints for SharedEntityManagerCreator
Closes gh-30523
2023-05-23 11:18:54 +02:00
Sébastien Deleuze b4eb352e1d Merge branch '6.0.x' 2023-05-23 09:11:07 +02:00
Sébastien Deleuze e92c9c5619 Disable Hibernate reflection optimizer with native
Closes gh-30521
2023-05-23 09:10:47 +02:00
rstoyanchev 5fc937d558 Remove asciidoctor build plugins after move to antora 2023-05-23 07:19:52 +01:00
rstoyanchev f926deda89 Fix link to code in documentation
See gh-30013
2023-05-23 07:18:16 +01:00
Sébastien Deleuze c3e28728ce Upgrade to Kotlin Serialization 1.5
Closes gh-30515
2023-05-22 18:07:32 +02:00
Sébastien Deleuze f956d399ae Upgrade to Kotlin Coroutines 1.7
Leverages Kotlin/kotlinx.coroutines#3487.

Closes gh-30514
2023-05-22 18:07:21 +02:00
Sébastien Deleuze 7efd347da6 Upgrade to Kotlin 1.8
This commit also disables the JVM target validation
introduced in Kotlin 1.8 since Kotlin is not yet
compatible with Java 21.

Closes gh-29754
2023-05-22 15:43:37 +02:00
Stephane Nicoll 5e07141846 Merge branch '6.0.x' 2023-05-22 15:30:47 +02:00
Stephane Nicoll 7660dbfd77 Merge pull request #30512 from izeye
* pr/30512:
  Add Javadoc since to InjectedElement.shouldInject()

Closes gh-30512
2023-05-22 15:30:33 +02:00
Johnny Lim 15a7f43c7b Add Javadoc since to InjectedElement.shouldInject()
See gh-30512
2023-05-22 15:30:05 +02:00
Brian Clozel 40543e0a58 Polish SnakeYAML 2.0 upgrade
See gh-30048
2023-05-22 14:52:59 +02:00
Andrey Somov 097758baf3 Upgrade to SnakeYAML 2.0
This commit raises the SnakeYAML baseline version to 2.0.
While most Spring applications are not affected by CVE-2022-1471,
upgrading this version should prevent automated tools from raising this
as a security issue. Such tools usually do not understand that YAML
parsing in Spring is about reading configuration, not parsing untrusted
content.

Closes gh-30048
2023-05-22 14:31:27 +02:00
Brian Clozel 96a429a561 Move reactive server instrumentation out of WebFilter
Prior to this commit, the Observation instrumentation for Reactive
server applications was implemented with a `WebFilter`. This allowed to
record observations and set up a tracing context for the controller
handlers.

The limitation of this approach is that all processing happening at a
lower level is not aware of any observation. Here, the
`HttpWebHandlerAdapter` handles several interesting aspects:

* logging of HTTP requests and responses at the TRACE level
* logging of client disconnect errors
* handling of unresolved errors

With the current instrumentation, these logging statements will miss the
tracing context information. As a result, this commit deprecates the
`ServerHttpObservationFilter` in favor of a more direct instrumentation
of the `HttpWebHandlerAdapter`. This enables a more precise
instrumentattion and allows to set up the current observation earlier in
the reactor context: log statements will now contain the relevant
information.

Fixes gh-30013
2023-05-22 11:03:02 +02:00
greg.lee e5ee369e70 Introduce method in MockHttpServletRequestBuilder to set remote address
Co-authored-by: Sam Brannen <sam@sambrannen.com>
Closes gh-30497
2023-05-16 17:30:48 +02:00
Simon Baslé f5bc084ce2 Merge branch '6.0.x' (javadoc changes) 2023-05-16 15:05:42 +02:00
Simon Baslé 1721e42988 Remove JBossAS catch-all javadoc external link
This commit removes the JBoss Application Server external javadoc link,
which covers too many packages and can thus problematically take
precedence for said packages and lead to dead links.

It is replaced by Hibernate javadocs for `org.hibernate.*` packages,
JakartaEE and jsr305 for annotations. We lose a limited number of links
around org.xnio classes and Hibernate-and-JTA-related classes, as a
trade-off.

See gh-30455
See gh-30428
2023-05-16 15:04:34 +02:00
Simon Baslé eabb846d07 Improve how the build deals with javadoc invalid references
This commit improves how the build deals with javadoc invalid references
in two ways.

Link/see references that are temporarily invalid during javadoc
generation of individual modules are better masked by using the option
`Xdoclint:syntax` instead of `Xdoclint:none` (warnings were still
visible in some cases, e.g. when individually building the javadoc for
a specific module).

Global javadoc-building task `api` now combines `syntax` and `reference`
`Xdoclint` groups, allowing to raise truly invalid references even when
all the modules have been aggregated.

This commit also fixes the 20+ errors which appeared following the later
change in doclet configuration.

Closes gh-30428
2023-05-16 15:04:10 +02:00
Sam Brannen d86cfc949d Polishing 2023-05-15 16:07:15 +02:00
Sam Brannen 1d708510df Merge branch '6.0.x' 2023-05-15 15:23:16 +02:00
Jan Mewes 280b0de646 Docs: Remove duplicate in SpEL feature list
Closes gh-30404
2023-05-15 15:22:44 +02:00
Sam Brannen 1275b10d9c Merge branch '6.0.x' 2023-05-15 15:09:56 +02:00
Sam Brannen 2738b3e50f Polishing
See gh-30482
2023-05-15 15:09:06 +02:00
Anyuruf 169795d673 Fix wording in r2dbc Statement Filters section of ref docs
Co-authored-by: Sam Brannen <sam@sambrannen.com>
Closes gh-30482
2023-05-15 15:08:58 +02:00
Sébastien Deleuze 1f3dd3e2ee Merge branch '6.0.x' 2023-05-15 11:49:31 +02:00
Sébastien Deleuze 085565a771 Skip class transformer in PersistenceUnitInfoDescriptor for native images
In order to restore native support with Hibernate 6.2, this
change updates the PersistenceUnitInfoDescriptor instance
created by SpringHibernateJpaPersistenceProvider in order to
skip the class transformer for native images.

Closes gh-30492
2023-05-15 11:48:56 +02:00
Sam Brannen c227fbfdf2 Reorganize helper methods to align with first usage principle 2023-05-13 19:29:48 +02:00
Sam Brannen f3f3dc693a Fix logic for validating @RecordApplicationEvents config
Prior to this commit, the SpringExtension looked up the
TestInstance.Lifecycle and ExecutionMode using
TestContextAnnotationUtils; however, using TestContextAnnotationUtils is
problematic since the TestInstance.Lifecycle and ExecutionMode can be
configured globally via configuration parameters instead of locally via
the @TestInstance and @Execution annotations.

This commit addresses these issues by looking up the
TestInstance.Lifecycle and ExecutionMode via JUnit Jupiter's
ExtensionContext which takes into account both global and local
configuration.

See gh-30020
2023-05-13 19:27:46 +02:00
Sam Brannen 5e1a4740d7 Suppress unused warning in test 2023-05-13 18:49:44 +02:00
Brian Clozel b4866e51b2 Configure toolchain locations when building PRs
This commit updates the script that builds PRs to add locations to the
installed JDK within the CI image. Without this change, PRs fail to
build because of the recently introduced JDK21 toolchain requirement in
the Spring Framework build.

Closes gh-30472
2023-05-12 11:33:17 +02:00
rstoyanchev a9fa813a75 Merge branch '6.0.x' 2023-05-12 10:20:11 +01:00
rstoyanchev 806519f78a Comment out check->antora dependency
See gh-30481
2023-05-12 10:19:52 +01:00
Sébastien Deleuze d99c2cf31e Refine JVM checkpoint/restore support
This commit:
 - Refine the wording used in logs and Javadoc
 - Avoid calling awaitPreventShutdownBarrier() in afterRestore()
 - Add logs to print the restart duration

See gh-29921
2023-05-12 09:29:35 +02:00
Stephane Nicoll ffa431da7b Merge branch '6.0.x' 2023-05-12 08:59:57 +02:00
Stephane Nicoll c3c5eaf914 Align AOT contributions for injection with the runtime behavior
Bean post processors that use InjectionMetadata checks if a property
value for the element it is about to inject is set and skip it, so
that the property value is used. Previously, the AOT contribution for
the same behavior did not check if a matching property value is set
and therefore override the user-defined value.

This commit introduces an additional method that filters the injected
element list so that only the elements that should be processed are
defined.

Closes gh-30476
2023-05-12 08:49:22 +02:00
Brian Clozel a91effcd86 Ignore some FreeMarker tests for JDK21
This reverts commit 07a5d8c91 and instead disables the relevant
FreeMarker tests for JDK21+ runs.
2023-05-11 18:00:23 +02:00
Brian Clozel 07a5d8c91c Fix FreeMarker tests for JDK21 build
Prior to this commit, some FreeMarker tests would fail when involving
property lookup in a template file, where this bean property is linked
with a method implemented as a default method on an interface.

While I did not manage to reproduce this behavior in an independent test
case, this is most likely related to a change in JDK 21:
https://bugs.openjdk.org/browse/JDK-8071693

This commit changes the template expression to using the default method
directly.
2023-05-11 17:10:26 +02:00
Stephane Nicoll 0bd0578ff9 Merge branch '6.0.x' 2023-05-11 16:36:38 +02:00
Stephane Nicoll a9b94241af Fix typo
Closes gh-30473
2023-05-11 16:35:20 +02:00
Brian Clozel 2f3a73a59e Merge branch '6.0.x' 2023-05-11 15:28:30 +02:00
Spring Builds 7066dc4ba7 Next development version (v6.0.10-SNAPSHOT) 2023-05-11 12:47:00 +00:00
Juergen Hoeller 1e74d793a2 Merge branch '6.0.x' 2023-05-10 18:51:40 +02:00
Juergen Hoeller 3f889e997c Clarify RootBeanDefinition vs GenericBeanDefinition
Closes gh-30444
2023-05-10 18:50:27 +02:00
Juergen Hoeller 6622a3c7d6 Consistent package-info declarations for CGLIB fork
Closes gh-30461
2023-05-10 18:50:17 +02:00
rstoyanchev 3d96e3f8c8 Merge branch '6.0.x' 2023-05-10 17:39:56 +01:00
Rob Winch d8f6567c89 Download the playbook to build dir
Closes gh-30465
2023-05-10 17:39:40 +01:00
Sam Brannen d8215a62f6 Merge branch '6.0.x' 2023-05-10 17:40:42 +02:00
Sam Brannen 111309605c Support Test AOT processing with GraalVM tracing agent and NBT
Prior to this commit, test AOT processing failed when using the GraalVM
tracing agent and GraalVM Native Build Tools (NBT) plugins for Maven
and Gradle.

The reason is that the AOT support in the TestContext framework (TCF)
relied on AotDetector.useGeneratedArtifacts() which delegates
internally to NativeDetector.inNativeImage() which does not
differentiate between values stored in the
"org.graalvm.nativeimage.imagecode" JVM system property.

This commit addresses this issue by introducing a TestAotDetector
utility that is specific to the TCF. This detector considers the
current runtime to be in "AOT runtime mode" if the "spring.aot.enabled"
Spring property is set to "true" or the GraalVM
"org.graalvm.nativeimage.imagecode" JVM system property is set to any
non-empty value other than "agent".

Closes gh-30281
2023-05-10 17:39:46 +02:00
Sam Brannen 89bcee68bb Add author tag 2023-05-10 17:39:46 +02:00
Juergen Hoeller 841124af75 Merge branch '6.0.x' 2023-05-10 17:19:39 +02:00
Juergen Hoeller c8927ae753 Polishing 2023-05-10 17:18:31 +02:00
Juergen Hoeller e228f4ba64 Consistent pre-resolution of event type vs payload type
Restores proper event type propagation to parent context.
Selectively applies payload type to given payload object.
Also reuses cached type for regular ApplicationEvent now.

Closes gh-30360
2023-05-10 17:17:48 +02:00
Simon Baslé dbc42f56b3 Merge branch '6.0.x' 2023-05-10 15:18:57 +02:00
Simon Baslé c733ae0f22 Fix ApplicationListenerMethodAdapter#supportsEventType check
This commit fixes the check by avoiding a fallback to eventType's
hasUnresolvableGenerics(). This could previously lead to checking a
generic event type `A<T>` against a listener which accepts unrelated
`B` and return `true` despite the inconsistency.

Note that this wouldn't necessarily surface to the user because there is
a `catch (ClassCastException e)` down the line, which was primarily put
in place to deal with lambda-based listeners but happens to catch an
exception thrown due to the bad result of `supportsEventType`.

The `supportsEventType` now matches generic `PayloadApplicationEvent`
types with a raw counterpart, using the above fallback only in that case
and otherwise ultimately returning `false`.

Closes gh-30399
2023-05-10 15:00:11 +02:00
Sam Brannen 96fbcb26c9 Merge branch '6.0.x' 2023-05-10 14:36:09 +02:00
Sam Brannen aefcb9d2d6 Make maximum SpEL expression length configurable
Closes gh-30380
2023-05-10 14:35:36 +02:00
Sam Brannen 6a6dd599a1 Remove duplicate Checkstyle suppressions 2023-05-10 14:31:24 +02:00
Sam Brannen 5e52259fb3 Suppress warnings in tests 2023-05-10 14:27:43 +02:00
Sam Brannen e51c71bcd6 Delete unused code 2023-05-10 14:26:41 +02:00
Stephane Nicoll 4d5e235166 Merge branch '6.0.x' 2023-05-10 13:55:36 +02:00
Stephane Nicoll 120c228b70 Handle injection of several persistence units
This commit adapts the generated code so that each injection point has
a dedicated namespace in the form of a private method. That prevents
the same variable to be reused twice which lead to a compilation failure
previously.

Closes gh-30437
2023-05-10 13:55:26 +02:00
rstoyanchev 5236d17ac4 Re-enable flaky tests after bd66c70b
See gh-29287
2023-05-10 11:44:32 +01:00
rstoyanchev d9f659171b Merge branch '6.0.x' 2023-05-10 11:43:38 +01:00
rstoyanchev bd66c70b2b Potential fix for flaky STOMP integration tests
When ReactorNetty2StompBrokerRelayIntegrationTests fail, typically there
are multiple exceptions "Connection refused: /127.0.0.1:61613" that
appear after we've conneted, sent CONNECT, and expecting CONNECTED, but
that does not come within the 10 second timeout.

61613 is the default port for STOMP. However, in all integration tests
we start ActiveMQ with port 0 which results in a random port. Moreover,
the stacktrace is for Netty 4 (not 5), and the eventloop thread id's
are different than the one where the connection to the correct, random
port was established.

The suspicion is that these are log messages from
MessageBrokerConfigurationTests which focuses on testing configuration
but nevertheless as a bean starts and attempts to connect to the default
port and fails. Perhaps those attempts to connect on the default port
somehow affect the ActiveMQ server, and it stops responding.

This change adds a no-op TcpClient in MessageBrokerConfigurationTests
to avoid unnecessary attempts to connect that are not needed.

See gh-29287
2023-05-10 11:42:45 +01:00
Stephane Nicoll 993a69d3a9 Deprecate spring context indexer
This commit deprecates the context indexer as our efforts on the AOT
engine cover the indexer in a much broader fashion.

Closes gh-30431
2023-05-10 09:13:57 +02:00
rstoyanchev 944305b9f1 Merge branch '6.0.x' 2023-05-09 19:59:11 +01:00
rstoyanchev e737980033 Ensure chunks released on cancel in StringDecoder
The current test were not catching the issue because they request 1
via StepVerifier, wait for it, and then cancel. In the case of
StringDecoder it means all chunks are used up to produce that first
String and so the cancel doesn't catch any cached chunks.

Closes gh-30299
2023-05-09 19:58:36 +01:00
Stephane Nicoll 6eb63f778e Merge branch '6.0.x' 2023-05-09 16:27:23 +02:00
Stephane Nicoll 93fa01004c Document AOT best practices
This commit augment the AOT section with best practices we have
experienced while working on the AOT engine. In particular, it describes
how a FactoryBean with an unresolved generic should be handled.

Closes gh-30434
2023-05-09 16:25:36 +02:00
Stephane Nicoll eb240016ed Merge branch '6.0.x' 2023-05-09 14:52:49 +02:00
Stephane Nicoll c1f6d7197b Add support for InjectionPoint with AOT
This commit reviews BeanInstanceSupplier to reuse more code from
ConstructorResolver. Previously, the autowired argument resolution was
partially duplicated and this commit introduces a new common path via
RegisteredBean#resolveAutowiredArgument.

Closes gh-30401
2023-05-09 14:52:23 +02:00
Arjen Poutsma b674906e3a Document @ResponseStatus behavior
This commit documents that the ResponseStatus annotation does not
override the status set through other means.

Closes gh-30305
See gh-18019
2023-05-09 14:08:04 +02:00
Arjen Poutsma a133aae8d6 Document @ResponseStatus behavior
This commit documents that the ResponseStatus annotation does not
override the status set through other means.

Closes gh-30305
See gh-18019
2023-05-09 14:01:33 +02:00
rstoyanchev bc7ba8cf2b Merge branch '6.0.x'
Closes gh-30435
2023-05-09 12:16:13 +01:00
Rob Winch 3a0a19cff8 Fix migration to asciidoctor tabs
The automation to asciidoctor tabs did not migrate properly for all
cases this commit fixes the migration.

See gh-30435
2023-05-09 12:15:43 +01:00
Juergen Hoeller 6930d4d531 Upgrade to Reactor 2022.0.7 and Micrometer 1.10.7
Includes Protobuf 3.23, Woodstox 6.5.1, Caffeine 3.1.6, Picocli 4.7.3, BlockHound 1.0.8, ActiveMQ 5.17.4

Closes gh-30450
Closes gh-30451
2023-05-09 12:55:44 +02:00
Brian Clozel b4649137fc Merge branch '6.0.x' 2023-05-09 09:34:33 +02:00
Brian Clozel 6bc674b2dd Upgrade CI image to Ubuntu Jammy 2023-05-09 09:34:16 +02:00
Arjen Poutsma c8b920a05d Fix SimpleAsyncTaskExecutor virtual thread path
This commit makes sure that the SimpleAsyncTaskExecutor only creates a
virtual thread when the virtualThreadDelegate is set, and not an
additional kernel thread as well.

See gh-30241
2023-05-08 16:59:35 +02:00
Brian Clozel c564725f46 Upgrade to Java 21 EA build 21 2023-05-08 15:42:35 +02:00
Brian Clozel e599fec685 Make JDK21 available as toolchain in main build
See gh-30339
See gh-30241
2023-05-08 15:27:30 +02:00
Juergen Hoeller 657fe1fa43 Merge branch '6.0.x' 2023-05-08 14:52:26 +02:00
Juergen Hoeller 4aa8619ac2 Upgrade to Tomcat 10.1.8, Jetty 11.0.15 / 12.0.0.beta1, Netty 4.1.92, Jackson 2.14.3, Mockito 5.3.1, Checkstyle 10.10 2023-05-08 13:06:19 +02:00
Juergen Hoeller 2c7e8661cf Respect TaskDecorator configuration on DefaultManagedTaskExecutor
Closes gh-30442
2023-05-08 12:02:25 +02:00
Juergen Hoeller c09055b83a Consistent support for MultiValueMap and common Map implementations
Closes gh-30440
2023-05-08 12:01:58 +02:00
Juergen Hoeller 697d5e6247 Configuration options for virtual threads (on JDK 21)
VirtualThreadDelegate built on JDK 21 for multi-release jar.
Includes dedicated VirtualThreadTaskExecutor as lean option.
Includes setVirtualThreads flag on SimpleAsyncTaskExecutor.
Includes additional default methods on AsyncTaskExecutor.

Closes gh-30241
2023-05-08 11:22:47 +02:00
Juergen Hoeller d8d7e0a762 Deprecate default constructor on ConcurrentTaskExecutor/Scheduler
Includes revision of null Executor configuration.
Respects TaskDecorator configuration on DefaultManagedTaskExecutor.

Closes gh-27914
2023-05-08 11:21:29 +02:00
rstoyanchev 73d30dd875 Polishing contribution
Closes gh-30403
2023-05-05 20:53:52 +01:00
Olga MaciaszekSharma 033548a760 Remove default blockTimeout on interface clients
See gh-30403
2023-05-05 20:53:52 +01:00
Sébastien Deleuze e416dfdbc0 Merge branch '6.0.x' 2023-05-05 18:20:43 +02:00
Sébastien Deleuze 2c15dcc56b Fix native support for generic array parameters
This commit adds a workaround for oracle/graal#6529
triggered by b374824319.

When the GraalVM fix will have reached a wide enough
audience, it should be removed via gh-30394.

Closes gh-30407
2023-05-05 18:20:08 +02:00
rstoyanchev 592a3074e1 Merge branch '6.0.x'
Closes gh-30430
2023-05-05 16:57:08 +01:00
Rob Winch 06f16f15ed Remove PDF Link
See gh-30430
2023-05-05 16:56:25 +01:00
Simon Baslé b39e93d0d1 Add test support to record async events, with Junit5 caveat
This commit modifies the way the `@RecordApplicationEvents` annotation
works in tests, allowing for capture of events from threads other than
the main test thread (async events) and for the assertion of captured
event from a separate thread (e.g. when using `Awaitility`).

This is done by switching the `ApplicationEventsHolder` to use an
`InheritedThreadLocal`.

There is a mutual exclusion between support of asynchronous events vs
support of JUnit5 parallel tests with the `@TestInstance(PER_CLASS)`
mode. As a result, we favor the former and now `SpringExtension` will
invalidate a test class that is annotated (or meta-annotated, or
enclosed-annotated) with `@RecordApplicationEvents` AND
`@TestInstance(PER_CLASS)` AND `@Execution(CONCURRENT)`.

See gh-29827
Closes gh-30020
2023-05-05 17:10:41 +02:00
Simon Baslé 906c54faff Add SpEL support for registered MethodHandles
This commit adds support for MethodHandles in SpEL, using the same
syntax as user-defined functions (which also covers reflective Methods).

The most benefit is expected with handles that capture a static method
with no arguments, or with fully bound handles (where all the arguments
have been bound, including a target instance as first bound argument
if necessary). Partially bound MethodHandle should also be supported.

A best effort approach is taken to detect varargs as there is no API
support to determine if an argument is a vararg or an explicit array,
unlike with Method. Argument conversions are also applied. Finally,
array repacking is not always necessary with varargs so it is only
performed when the vararg is the sole argument to the invoked method.

See gh-27099
Closes gh-30045
2023-05-05 16:18:25 +02:00
Simon Baslé d3c3088c6b Clarify behavior of the Elvis SpEL operator in documentation (#30352)
This commit improves both the javadoc and the reference guide section on
the Elvis SpEL operator to clarify that in addition to `null` objects,
empty Strings also lead the operator to evaluate to its second operand.

The reference guide's advanced snippet is modified to use such an empty
String instead of `null` to make that behavior prominent with some code.

See gh-30318
Closes gh-30352
2023-05-05 16:13:06 +02:00
Stephane Nicoll f2c0b30641 Merge branch '6.0.x' 2023-05-05 15:04:15 +02:00
Stephane Nicoll da37deec1b Merge pull request #30423 from izeye
* pr/30423:
  Polish "Introduce internal constants for implicit bounds in TypeUtils"
  Introduce internal constants for implicit bounds in TypeUtils

Closes gh-30423
2023-05-05 15:03:58 +02:00
Stephane Nicoll 88361a4f3e Polish "Introduce internal constants for implicit bounds in TypeUtils"
See gh-30423
2023-05-05 15:01:46 +02:00
Johnny Lim 92cf7f1a7f Introduce internal constants for implicit bounds in TypeUtils
See gh-30423
2023-05-05 14:58:24 +02:00
Rob Winch 601de66c03 nohttp exclude **/.gradle/** 2023-05-04 17:47:37 +01:00
rstoyanchev 91ea2d4c27 Merge branch '6.0.x'
Closes gh-30414
2023-05-04 15:46:54 +01:00
rstoyanchev 8a8fb31f4a Update target repository for Antora
See gh-30414
2023-05-04 15:37:21 +01:00
Sébastien Deleuze b7884ddd02 Disable flaky ReactorNetty2StompBrokerRelayIntegrationTests
See gh-29287
2023-05-04 16:37:17 +02:00
Rob Winch 719553f627 Fix Web Reactive link on the landing page 2023-05-04 15:35:05 +01:00
Rob Winch 993447deb0 Remove invalid deploy-docs.yml 2023-05-04 15:35:05 +01:00
Rob Winch 88c9b0f467 Use the shared antora playbook 2023-05-04 15:35:05 +01:00
Rob Winch 39146f9066 Migrate to Asciidoctor Tabs 2023-05-04 15:35:05 +01:00
Rob Winch 71154fd16b Add ./github/workflow/deploy-docs.yml 2023-05-04 15:35:05 +01:00
Rob Winch 7b0ba0188f Structural Fixes 2023-05-04 15:35:05 +01:00
Rob Winch 3774e9be7a Trim IDs with parent 2023-05-04 15:35:05 +01:00
Rob Winch 9c38f8c3c6 Make local build (temporary) 2023-05-04 15:35:05 +01:00
Rob Winch 26171d9efb Fix Title in antora.yml 2023-05-04 15:35:05 +01:00
Rob Winch 68235464fc Use include-code Macro 2023-05-04 15:35:05 +01:00
Rob Winch 51ada4e19d Fix invalid nav elements 2023-05-04 15:35:05 +01:00
Rob Winch 1a8e0031fe Fix index Overview link 2023-05-04 15:35:05 +01:00
Rob Winch d8bcbd53e1 Fix invalid attributes 2023-05-04 15:35:05 +01:00
Rob Winch 6993a9eee4 fix antora.yml attributes 2023-05-04 15:35:05 +01:00
Rob Winch d2720741a5 Fix antora.yml gradle command 2023-05-04 15:35:05 +01:00
Rob Winch 067e6c2a9e fix framework-docs.gradle 2023-05-04 15:35:05 +01:00
Rob Winch 35229c8bff Enable Section Summary TOC for small pages 2023-05-04 15:35:05 +01:00
Rob Winch 139cde47e2 Fix cross references 2023-05-04 15:35:05 +01:00
Rob Winch 6b341ddf19 Remove includes 2023-05-04 15:35:05 +01:00
Rob Winch 5aecfb1878 Generate a default navigation 2023-05-04 15:35:05 +01:00
Rob Winch 9f49d24833 Split files 2023-05-04 15:35:05 +01:00
Rob Winch ac69a5dac3 Copy default antora files 2023-05-04 15:35:05 +01:00
Rob Winch 7f9061a3cb Fix image::image 2023-05-04 15:35:05 +01:00
Rob Winch a05ff6c126 Remove unnecessary asciidoc attributes 2023-05-04 15:35:05 +01:00
Rob Winch 9ceb75b228 Insert explicit ids for headers 2023-05-04 15:35:05 +01:00
Rob Winch 3fe7c65218 Migrate Structure 2023-05-04 15:35:05 +01:00
Rob Winch a78836c18b Remove duplicated testing from .adoc file path 2023-05-04 15:35:05 +01:00
Rob Winch 2a4a1cc550 Remove -languages suffix from .adoc files 2023-05-04 15:35:05 +01:00
Rob Winch c762c07290 Remove integration- prefix from .adoc files 2023-05-04 15:35:05 +01:00
Rob Winch 957467aa32 Remove data-access- prefix from .adoc files 2023-05-04 15:35:04 +01:00
Rob Winch 49a4734cfa Remove core- prefix from .adoc files 2023-05-04 15:35:04 +01:00
Sébastien Deleuze 9fec516560 Skip CRaC support with native images
Skip CRaC support with native images to avoid compiling related
infrastructure to the native image and to fix tests via
gh-30422.

See gh-30242
2023-05-04 15:36:29 +02:00
Sébastien Deleuze f469eff97b Update RuntimeHintsAgentPlugin to use the native image code path
RuntimeHintsAgentPlugin purpose is to verify that the reflective
invocations expected match the ones performed.

gh-30242 introduces a code path where the reflective invocation
is skipped when running on native.

This issue set the system property "org.graalvm.nativeimage.imagecode"
to "runtime" when running runtime tests with the agent in order to
make sure the code path tested for those tests is the native one.

Closes gh-30422
2023-05-04 15:31:31 +02:00
Stephane Nicoll 69cde11a51 Merge branch '6.0.x' 2023-05-04 12:23:46 +02:00
Stephane Nicoll 44b427c3e1 Add AOT support for Qualifiers
This commit handles AutowiredCandidateQualifier instances, rather than
relying on qualifiers being statically defined and meta-annotated with
`@Qualifier`.

Closes gh-30410
2023-05-04 12:17:07 +02:00
Juergen Hoeller 7d2047cdbd Prevent JVM shutdown before checkpoint
See gh-30242
2023-05-03 18:16:32 +02:00
Juergen Hoeller c76116b970 Keep CracResourceAdapter strongly reachable
See gh-30242
2023-05-03 17:50:36 +02:00
Juergen Hoeller 8d604350e4 Support for Project CRaC in DefaultLifecycleProcessor
Includes stopForRestart/restartAfterStop functionality.

Closes gh-30242
2023-05-03 16:01:41 +02:00
Juergen Hoeller 4db724984e Suppress deprecations for compiling on JDK 19/20 2023-05-03 10:17:12 +02:00
Juergen Hoeller 87942ed71d Support for SequencedCollection/Set/Map (on JDK 21)
Includes consistent support for MultiValueMap.

Closes gh-30239
2023-05-03 10:16:25 +02:00
Juergen Hoeller dd871e0d8c Trigger rollback for (Completable)Future exception on method return
Closes gh-30018
2023-05-03 10:03:31 +02:00
Juergen Hoeller c1014f5989 Relax relative path existence assertion for parsed URIs
See gh-29481
See gh-28522
2023-05-01 00:01:49 +02:00
Juergen Hoeller 6a2262969e Upgrade to Tomcat 10.1.8, Jetty 11.0.15, Netty 4.1.92, Mockito 5.3.1 2023-04-30 23:08:28 +02:00
Juergen Hoeller d39e44c209 Deprecate AutowireCapableBeanFactory.createBean(Class, int, boolean)
Includes consistent usage of createBean(Class) in SpringBeanJobFactory and SpringBeanContainer.

Closes gh-30345
See gh-29855
See gh-30041
2023-04-30 23:07:29 +02:00
Juergen Hoeller 4d15b58ca4 Remove LocalVariableTableParameterNameDiscoverer
Closes gh-29559
2023-04-30 23:05:09 +02:00
Juergen Hoeller 9342317291 Avoid use of java.net.URL constructors (for JDK 20 compatibility)
Explicit path computation also leads to consistent relative path semantics for resource URLs.

Closes gh-29481
Closes gh-28522
2023-04-30 23:03:39 +02:00
Sam Brannen dfd74495bd Merge branch '6.0.x' 2023-04-28 16:09:15 +02:00
Sam Brannen aabd685225 Update major/minor version properties in MockServletContext
ServletContext has sets of major/minor version properties that we have
not updated in MockServletContext in several years.

Since we upgraded the baseline to Servlet 6.0 in Spring Framework 6.0,
now seems like a good time to update those version properties.

Closes gh-30395
2023-04-28 15:43:29 +02:00
Sébastien Deleuze 90ffa95b6a Merge branch '6.0.x' 2023-04-28 10:00:59 +02:00
Sébastien Deleuze cefb734763 Restore native support for record beans
After b374824319 related
to gh-29246, `"queryAllDeclaredMethods": true` is now added
on all registered beans.

This legit change triggers oracle/graal#6510. This
commit workarounds this GraalVM bug, and should be
removed once the GraalVM fix has reached a wide enough
audience.

Closes gh-30383
2023-04-28 09:57:22 +02:00
Stephane Nicoll 825f160369 Merge branch '6.0.x' 2023-04-26 16:55:10 +02:00
Stephane Nicoll 82e5464972 Avoid extra "__BeanDefinitions" suffix for inner classes
This commit makes AOT class names for bean definitions shorter.
Previously, the "__BeanDefinitions" suffix was applied for all
classes, but it was unnecessary for inner classes as the container
class already has the qualifier.

Closes gh-29846
2023-04-26 16:52:46 +02:00
Stephane Nicoll 834e694e94 Merge branch '6.0.x' 2023-04-26 14:39:58 +02:00
Stephane Nicoll 02132bd060 Infer resource hints for PropertySource#value
This commit adds a resource hints for the target(s) of a @PropertySource
declaration.

Closes gh-30376
2023-04-26 14:13:19 +02:00
Stephane Nicoll f6875b11ff Generate missing hints for custom PropertySource factories
Closes gh-30175
2023-04-26 13:40:48 +02:00
Sam Brannen ce3e9b0c29 Polishing 2023-04-26 11:21:34 +02:00
Sam Brannen 1c7ceaa2ca Improve Javadoc for AbstractEnvironment and Profiles 2023-04-26 11:09:38 +02:00
Sam Brannen 7e0620a143 Use new Environment.matchesProfiles() method 2023-04-26 11:09:38 +02:00
Sam Brannen fb039a3e0c Merge branch '6.0.x' 2023-04-26 10:37:35 +02:00
Sam Brannen 230840a41c Upgrade to JUnit 5.9.3 2023-04-26 10:26:56 +02:00
Sam Brannen 05e4234525 Merge branch '6.0.x' 2023-04-25 19:52:06 +02:00
Sam Brannen 3b8a9b18f9 Upgrade to Gradle 8.1.1
Closes gh-30351
2023-04-25 19:51:54 +02:00
Sam Brannen e19472568f Merge branch '6.0.x' 2023-04-25 18:11:35 +02:00
Sam Brannen d023b94a42 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.

Closes gh-30206
2023-04-25 18:10:50 +02:00
Sam Brannen 47ba819f96 Polish Environment and StandardEnvironmentTests
See gh-30206
2023-04-25 18:10:39 +02:00
Sam Brannen 845488af8d Improve toString() for Profiles.of() implementation
Prior to this commit, the toString() implementation in ProfilesParser
(which is the internal implementation of Profiles.of()) concatenated
profile expressions with " or ".

For example, the string representation of
Profiles.of("spring & framework", "java | kotlin") was
"spring & framework or java | kotlin".

This commit improves the toString() implementation by wrapping
individual profile expressions in parentheses and concatenating them
with " | ".

For example, the string representation from the previous example is now
"(spring & framework) | (java | kotlin)".

This makes it easier to read (for example, when debugging) and
comprehend.

As an additional benefit, the result of invoking toString() can even be
used as a logically equivalent composite profile expression, though
that is not the primary goal of this change.

Closes gh-30374
2023-04-25 16:49:34 +02:00
Sam Brannen b924b7b4c6 Merge branch '6.0.x' 2023-04-25 15:15:45 +02:00
Sam Brannen ea4c64ebc4 Polish ProfilesParser internals 2023-04-25 15:08:03 +02:00
Sam Brannen b368fc03ea Merge branch '6.0.x' 2023-04-25 14:09:30 +02:00
Sam Brannen de113f1d11 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.

Closes gh-30371
2023-04-25 13:46:30 +02:00
Sam Brannen ca13b5cbca Polish SpelParserTests and TemplateExpressionParsingTests 2023-04-25 13:46:30 +02:00
Sam Brannen 982a094646 Rename determineResource() to resolveResource()
See gh-30369
2023-04-25 11:35:00 +02:00
Sam Brannen dfe320f172 Reorganize methods in ReloadableResourceBundleMessageSource
See gh-30369
2023-04-25 11:08:56 +02:00
Sam Brannen 2537c7c735 Polish Javadoc in ReloadableResourceBundleMessageSource
See gh-30369
2023-04-25 11:08:56 +02:00
Arjen Poutsma 54853ee239 Support setCharacterEncoding(null) in MockHttpServletResponse
Closes gh-30341
2023-04-25 10:53:44 +02:00
Brian Clozel b408cee29f Merge branch '6.0.x' 2023-04-25 10:26:40 +02:00
James Yuzawa 5dacf50b9b Optimize MultiValueMap iteration operations
* use forEach and putIfAbsent to copy headers in DefaultClientRequestBuilder
* use forEach in ReactorClientHttpRequest and ReactorNetty2ClientHttpRequest
* circumvent ReadOnlyHttpHeaders.entrySet()
* ensure the fast path to LinkedCaseInsensitiveMap for forEach and putIfAbsent exists

Closes gh-29972
2023-04-25 09:57:26 +02:00
Simon Baslé e63d89973a Add ReloadableResourceBundleMessageSource Resource selection hook
This commit enables sub-classes to better customize resource selection
and resource loading in `ReloadableResourceBundleMessageSource`, without
a need to duplicate the caching logic of `refreshProperties`.

See gh-30334
Closes gh-30369
2023-04-24 17:57:45 +02:00
Han LiandSimon Baslé b311088f5a Optimize DefaultLifecycleProcessor::stopBeans
This commit optimizes `DefaultLifecycleProcessor::stopBeans` by using a
`TreeMap` when gathering the `LifecycleGroup`s during stopBeans. It also
switches to a functional style using `computeIfAbsent`.

Finally, it further optimizes `LifecycleGroup` by removing sorting of
`LifecycleGroupMember` members list entirely, turning the class into a
simple record.
This is possible because the members list is already comprised of
members which all share the same phase value, so sorting according to
each member's phase is redundant.

Closes gh-30361

Co-authored-by: Simon Baslé <sbasle@vmware.com>
2023-04-24 16:45:24 +02:00
Arjen Poutsma d9c534b13d Merge branch '6.0.x' 2023-04-24 12:56:37 +02:00
Arjen Poutsma beb23b5da6 Updated CI image JDK 2023-04-24 12:56:18 +02:00
Arjen Poutsma 95e311fd02 Merge branch '6.0.x' 2023-04-24 12:30:16 +02:00
Arjen Poutsma d07df24adc Updated sdkmanrc 2023-04-24 12:30:02 +02:00
Kai Zander 5b2aa0be81 Fix link in Javadoc of PassThroughFilterChain
Closes gh-30365
2023-04-23 15:50:14 +02:00
Simon Baslé 33b4995547 Fix glob pattern in CheckstyleConventions to be Windows-compatible
On windows, the `*` character is not allowed in a directory's name.
When trying to append a glob pattern to a `Path` (`path.resolve("**")`),
if the underlying `Path.getFileSystem()` is windows then an
`InvalidPathException` is thrown.

The NoHttp plugin doesn't really need a `Path` but a glob `String`, so
this commit uses a simple String concatenation in order to append the
wildcard part (with the canonical path separator for good measure).

Closes gh-30355
2023-04-20 16:44:58 +02:00
Sam Brannen c16dab236a Merge branch '6.0.x' 2023-04-20 16:21:16 +02:00
Sam Brannen 2d1ddbb65c Polish contribution
See gh-30282
2023-04-20 16:18:08 +02:00
David Szigecsan af54ee9eba Polish ClassUtils and TypeUtils
Closes gh-30282
2023-04-20 15:51:25 +02:00
Stephane Nicoll 202c46035a Merge branch '6.0.x' 2023-04-20 15:49:01 +02:00
Stephane Nicoll 7a78092934 Merge pull request #30343 from divcon
* pr/30343:
  Polish contribution
  Use putIfAbsent in Netty5HeadersAdapter

Closes gh-30343
2023-04-20 15:48:52 +02:00
Stephane Nicoll ea0340f892 Polish contribution
See gh-30343
2023-04-20 15:46:12 +02:00
divcon f79d145b4c Use putIfAbsent in Netty5HeadersAdapter
See gh-30343
2023-04-20 15:45:56 +02:00
Stephane Nicoll ea83d66fb5 Merge branch '6.0.x' 2023-04-20 15:43:19 +02:00
Stephane Nicoll 5deab3afd0 Merge pull request #30357 from izeye
* pr/30357:
  Polish

Closes gh-30357
2023-04-20 15:43:07 +02:00
Johnny Lim 66bd891a0b Polish
See gh-30357
2023-04-20 15:42:01 +02:00
Arjen Poutsma 9f85e397d4 Support XmlSeeAlso in Jaxb2XmlDecoder
This commit adds support for the @XmlSeeAlso annotation in the
Jaxb2XmlDecoder. This includes

- Finding the set of possible qualified names given a class name, rather
  than a single name.
- Splitting the XMLEvent stream when coming across one of the names in
  this set.

Closes gh-30167
2023-04-20 10:46:27 +02:00
Sam Brannen 7df2e2a8d2 Remove APIs deprecated for removal in 6.1
This is the first commit that removes deprecated APIs.

Subsequent commits will remove additional deprecated APIs.

See gh-29449
2023-04-19 17:23:49 +02:00
Sam Brannen d446de62a4 Update copyright headers 2023-04-19 15:55:11 +02:00
Arjen Poutsma dd9f03d9b9 Merge pull request #29890 from making:support-biconsumer-validator
* gh-29890:
  Polish contribution
  Introduce functional factory methods in Validator
2023-04-19 15:19:45 +02:00
Arjen Poutsma 3c57d5518a Polish contribution
- Split Validator::of into two factory methods:
  - forInstanceOf using Class::isAssignableFrom
  - forType using Class::equals
- Moved anonymous implementation into TypedValidator with default access

Closes gh-30341
2023-04-19 15:17:31 +02:00
Toshiaki Maki 5f98afc180 Introduce functional factory methods in Validator
This commit introduces `of` method in `Validator` to provide a way to
create a validator for the specific type `<T>` using `BiConsumer<T, Errors>`
and define the validator in a functional way.
This also eliminates the boilerplate for implementing the `supports` method.
2023-04-19 13:54:51 +02:00
Arjen Poutsma 7492c0ea03 Merge branch '6.0.x' 2023-04-18 15:35:36 +02:00
Arjen Poutsma 685548b58b Merge pull request #30252 from luozhenyu:content-disposition
* gh-30252:
  Polish contribution
  Quote question marks in content-disposition
2023-04-18 15:33:52 +02:00
Arjen Poutsma 74d3268656 Polish contribution
This commit polishes an external contribution, ensuring that not just
spaces are encoded as underscores, and that underscores are encoded
as non-printable.

See gh-30252
2023-04-18 15:30:31 +02:00
luozhenyu 5a4a46af78 Quote question marks in content-disposition
This commit ensures that question marks are encoded, in accordance
with RFC 2047, section 4.2, rule (3).

Closes gh-30252
2023-04-18 14:47:57 +02:00
Sam Brannen 65a430bb42 Upgrade to Checkstyle 10.9.3 again
Commit ed4404f350 inadvertently switched back to 10.9.1.
2023-04-18 14:09:43 +02:00
Stephane Nicoll bd62f47afa Merge pull request #30340 from jstansel
* pr/30340:
  Fix link to releases feed

Closes gh-30340
2023-04-17 18:02:25 +02:00
James Stansell 3e0aa4c603 Fix link to releases feed
See gh-30340
2023-04-17 18:02:01 +02:00
Brian Clozel 8b5bfdfa44 Fix CI image reference to JDK21
See gh-30339
2023-04-15 10:06:09 +02:00
Brian Clozel a465b16f7c Set current version to 6.0.9-SNAPSHOT 2023-04-14 12:35:24 +02:00
Brian Clozel da88ac8cca Move NoHttp config to Gradle conventions
See gh-30339
2023-04-14 12:31:43 +02:00
Brian Clozel a66f3e02f4 Upgrade CI Concourse resources 2023-04-14 10:39:39 +02:00
Brian Clozel 7f44861f32 Configure CI pipeline for 6.1.x milestone 2023-04-14 10:39:03 +02:00
Brian Clozel 63e20404a2 Configure JDK 21 CI build
This commit replaces the JDK 20 compatibility build with a JDK 21 (early
access) variant.

See gh-30339
2023-04-14 10:35:51 +02:00
Brian Clozel 5c574b9878 Refactor toolchain support in Gradle build
This commit removes the `-PmainToolchain` option from our build, since
it was not broadly used. Instead, the language level is now configured
in the `JavaConventions` for JDK 17.

The `-PtestToolchain` option is still available for testing Spring
Framework with other JDKs (i.e., compiling and running tests with a JDK
that's not the baseline).

See gh-30339
2023-04-14 10:30:12 +02:00
Brian Clozel 9562a1c146 Move build test configuration to Gradle convention
This commit moves the Gradle test configuration to a convention so it
can be applied to all test tasks, including from other source sets.

See gh-30339
2023-04-14 10:27:56 +02:00
Brian Clozel ed4404f350 Move checkstyle config to Gradle convention
This commit moves the checkstyle conventions from the build.gradle
script to a buildSrc convention, ensuring that the same configuration is
applied to all checkstyle tasks.

See gh-30339
2023-04-14 10:27:52 +02:00
Brian Clozel bd55b647c7 Switch to 6.1.0-SNAPSHOT version 2023-04-14 10:17:09 +02:00
Brian Clozel 5d1abfbc2d Update CI pipeline to 6.0.x branch 2023-04-13 12:46:06 +02:00
Spring Builds 19c7527376 Next development version (v6.0.9-SNAPSHOT) 2023-04-13 08:30:07 +00:00
Sam Brannen be17c8d85f 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-30326
2023-04-13 09:40:23 +02:00
Sam Brannen b73f5fcac2 Limit SpEL expression length
This commit enforces a limit of the maximum size of a single SpEL
expression.

Closes gh-30325
2023-04-13 09:39:53 +02:00
Sam Brannen bc1511d667 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-30324
2023-04-13 09:39:32 +02:00
Sam Brannen db9b139cf0 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 09:39:27 +02:00
rstoyanchev bd029b9218 Ensure RestClientResponseException is serializable
Closes gh-30224
2023-04-12 15:38:27 +01:00
rstoyanchev 5f2264816a Polishing contribution
Closes gh-30294
2023-04-12 15:22:57 +01:00
Yanming Zhou a8f31f5b9e Improve ProblemDetail equals and hashCode
Lazy computed title property should be taken into account

See gh-30294
2023-04-12 15:07:22 +01:00
Stephane Nicoll 90627b4345 Upgrade to Micrometer 1.10.6
Closes gh-30317
2023-04-12 14:45:54 +02:00
Juergen Hoeller 4acc71b282 Upgrade to Reactor 2022.0.6 and Netty 4.1.91
Includes Checkstyle 10.9.3 and Mockito 5.3.0

Closes gh-30316
2023-04-12 13:36:01 +02:00
kyuarl21 cd0379a67f Modified to slf4j2-impl in build.gradle
due to slf4j-api versions 1.7 x or earlier issue
2023-04-12 13:11:48 +02:00
Simon Baslé e262e98bab ConstructorResolver error hints about mixing indexed and named args
This commit adds a note to an exception in `ConstructorResolver`'s
`autowireConstructor` method hinting that attention should be paid to
cases that mix indexed arguments and named arguments. This is especially
when inheriting bean definitions in xml.

Closes gh-29976
Close gh-PR
2023-04-12 13:09:28 +02:00
SW 59c65fa940 Replace Collections.unmodifiableList(new ArrayList(..)) with List.copyOf() (#30166) 2023-04-12 13:07:20 +02:00
Stephane Nicoll 695601aa06 Merge pull request #30308 from izeye
* pr/30308:
  Add since tags to sameSite() and attribute() in CookieResultMatchersDsl

Closes gh-30308
2023-04-11 14:57:13 +02:00
Johnny Lim 8f5a1fe7e2 Add since tags to sameSite() and attribute() in CookieResultMatchersDsl
See gh-30308
2023-04-11 14:56:55 +02:00
rstoyanchev 073226d792 Polishing contribution
Closes gh-30120
2023-04-11 11:43:24 +01:00
Aleksandrs Jansons 1abe155663 Ensure WebSocket disconnect msg reaches the client
In some application setups, the WebSocket server does not transmit
the disconnect message to the client, so that the client has no idea
that the established connection has been terminated.

This issue arises when the application uses SimpleBrokerMessageHandler
and the error handler is set to the instance of
StompSubProtocolErrorHandler or an extended class that does not
override the handleErrorMessageToClient method.

The commit fixes disconnect message population so that
`java.lang.IllegalArgumentException: No StompHeaderAccessor` exception
is not thrown in the handleErrorMessageToClient method in
StompSubProtocolErrorHandler class.

See gh-30120
2023-04-11 11:43:23 +01:00
divcon 33ef9107e0 Minor refactoring in PayloadMethodArgumentResolver
Closes gh-30168
2023-04-11 11:36:41 +01:00
rstoyanchev 8463eade33 Polishing contribution
Closes gh-30192
2023-04-10 21:24:25 +01:00
James Yuzawa e77faf7484 Improve performance of canRead() in HttpMessageReader's
Use MimeType.WILDCARD_TYPE for faster String.equals().
Move cheaper checks to the front of the canRead implementations.

See gh-30192
2023-03-25 12:21:10 -04:00
Sam Brannen b23cc01cb7 Revise "Ignore nonexistent default-destroy-method in XML config"
This commit revises the fix in c811428512.

Closes gh-30301
2023-04-07 18:48:52 +02:00
Brian Clozel 01f97887ea Improve WebClient observations handling of CANCEL signal
Prior to this commit, `WebClient` observations would be recorded as
aborted (with tags "outcome":"UNKNOWN", "status":"CLIENT_ERROR")
for use cases like this:

```
Flux<String> result = client.get()
    .uri("/path")
    .retrieve()
    .bodyToFlux(String.class)
    .take(1);
```

This is due to operators like `take` or `next` that consume *some*
`onNext` signals and then cancels the subscription before completion.
This means the subscriber is only partially interested in the response
and we should not count this as a client error.

This commit ensures that observations are only recorded as aborted if
the response was not published at the time the CANCEL signal was
received.

The code snippet above will now publish observations with
"outcome":"SUCCESS" and "status":"200" tags, for example.

Closes gh-30070
2023-04-07 16:37:09 +02:00
Sam Brannen cef597bedd Update copyright headers 2023-04-07 14:24:22 +02:00
Sam Brannen 01fabfe66d Suppress warnings in tests 2023-04-07 14:23:55 +02:00
Sam Brannen c811428512 Ignore nonexistent default-destroy-method in XML config
Prior to this commit, DisposableBeanAdapter attempted to invoke a
configured default-destroy-method on every bean, including beans that
do not declare the named destroy method, resulting in a
NullPointerException being thrown and logged at WARN level.

This commit addresses this by effectively ignoring any nonexistent
destroy method.

Closes gh-30301
2023-04-07 13:58:49 +02:00
Sébastien Deleuze b5b115e52c 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-30277
2023-04-07 11:25:47 +02:00
Sam Brannen 310344cf61 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-30265
2023-04-06 17:53:03 +02:00
Sam Brannen 2bac371c5b Improve Javadoc for ObjectUtils.nullSafeConciseToString() 2023-04-06 17:35:50 +02:00
Arjen Poutsma cef9166833 Encode IPV6 Zone IDs in ReactorServerHttpRequest
This commit ensures that the zone id in the ReactorServerHttpRequest is
properly encoded.

Closes gh-30188
2023-04-06 11:32:44 +02:00
Simon Baslé d6460e0d57 Add Cookie attributes + SameSite CookieResultMatchers in MockMvc
This commit adds assertions to MockMvc's CookieresultMatchers:
 - `attribute` for arbitrary attributes
 - `sameSite` for the SameSite well-known attribute

Note that the `sameSite` methods delegate to their `attribute`
counterparts. Note also that Jakarta's `Cookie#getAttribute` method is
case-insensitive, which is reflected in the documentation of the
`attribute` assertion method and the tests.

Closes gh-30285
2023-04-05 17:02:38 +02:00
Sam Brannen 842490beeb Add tests for corner cases
See gh-30290
See gh-30286
2023-04-05 15:05:25 +02:00
Sam Brannen e746230de6 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 14:13:28 +02:00
Sam Brannen 8161316b1d 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 13:50:13 +02:00
Krzysztof Krasoń 1734deca1e Refactor AssertJ assertions into more idiomatic ones
This commit refactors some AssertJ assertions into more idiomatic and
readable ones. Using the dedicated assertion instead of a generic one
will produce more meaningful error messages. 

For instance, consider collection size:
```
// expected: 5 but was: 2
assertThat(collection.size()).equals(5);
// Expected size: 5 but was: 2 in: [1, 2]
assertThat(collection).hasSize(5);
```

Closes gh-30104
2023-04-04 17:34:07 +02:00
Justin Tay dd97ee4e99 Support SameSite cookie attribute in MockMvcHttpConnector
Closes gh-30264
2023-04-04 16:57:21 +02:00
Simon Baslé 90b0f451f0 Add a couple missing java.time types to StatementCreatorUtils
This commit adds mapping for two types from the `java.time` package,
complementing the types that are already translatable to Sql types
TIME, DATE and TIMESTAMP:
 - `OffsetTime` maps to a `TIME_WITH_TIMEZONE`
 - `OffsetDateTime` maps to a `TIMESTAMP_WITH_TIMEZONE`

This is in accordance with the B.4 table provided in the JDBC 4.2
specification.

When preparing statements, these `java.time` types use the `setObject`
method. Tests covering the 5 `java.time` classes have also been added.

See gh-28778
See gh-28527
Closes gh-30123
2023-04-04 16:51:24 +02:00
Sam Brannen 9fb61c57ae Sync MockCookie implementations
See gh-30263
2023-04-04 16:32:30 +02:00
Sam Brannen f9cb0eba87 Update Javadoc regarding Servlet 6 baseline for mocks 2023-04-04 16:29:51 +02:00
Sam Brannen d1d2d5943e Polish contribution
See gh-30263
2023-04-04 16:29:03 +02:00
Justin Tay 281736f14e Update MockCookie to use Servlet 6.0 APIs and semantics for "attributes"
Closes gh-30263
2023-04-04 16:13:37 +02:00
Sam Brannen 6bfc70b61e Polishing 2023-04-04 16:02:54 +02:00
Simon Baslé 95883b9eb7 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.

Closes gh-30220
Closes gh-30238
See gh-29953
See gh-28660
2023-04-04 15:06:14 +02:00
Arjen Poutsma f0eb43a6af Merge pull request #30157 from srivatsa-cfp:main
* gh-30157:
  Add non-null assertions in DefaultServerResponseBuilder
2023-04-04 12:42:39 +02:00
Vatsa 6c8ebc7f7e Add non-null assertions in DefaultServerResponseBuilder
This commit adds various non-null assertions to
DefaultServerResponseBuilder, in both Spring MVC and WebFlux.

Closes gh-30157
2023-04-04 12:36:46 +02:00
Sam Brannen 69c8f8e9c7 Update copyright headers 2023-04-03 16:45:49 +02:00
Sam Brannen 02f2d94f57 Polish contribution
See gh-30271
2023-04-03 16:45:49 +02:00
wizard 7fcbc869a6 Specify initial capacity when creating ArrayList in SpringFactoriesLoader
Closes gh-30271
2023-04-03 16:42:00 +02:00
Sam Brannen 4eed2ced74 Polishing 2023-04-03 14:42:38 +02:00
Sébastien Deleuze 98f1287f3a Fix HttpServiceMethod support for suspending functions
This commit fixes nested type handling for suspending
functions in HttpServiceMethod.

Closes gh-30266
2023-04-03 10:30:49 +02:00
Brian Clozel 8234fa2a13 Fix JDK20 env variable declaration in CI pipeline
See gh-30185
2023-04-03 09:43:37 +02:00
Filip Blondeel 8b9d2e3f95 Fix incorrect jakarta.inject artifact version
Closes gh-30270
2023-04-03 09:36:22 +02:00
hongxue.zou 534d1cd35b Polishing
This commit includes a null-safety fix in
HttpComponentsHeadersAdapter.

Closes gh-30267
2023-04-03 09:04:39 +02:00
Sam Brannen ca545ac3d4 Upgrade dependencies 2023-04-02 19:20:49 +02:00
Sam Brannen ca7c2779bf Suppress warnings displayed in Gradle build for test source code 2023-04-01 18:36:56 +02:00
Sam Brannen 4a90257a84 Upgrade to Gradle 8
This commit upgrades the build to use Gradle 8.0.2 and Dokka 1.8.10.

Closes gh-30000
2023-04-01 18:36:28 +02:00
Sam Brannen 49a4ed2ffa Improve Javadoc for @PropertySource 2023-04-01 18:15:19 +02:00
Sam Brannen 717d03a29d Fix grammar 2023-04-01 18:15:19 +02:00
1993heqiang 2b427efe7f Fix PathVariable reference documentation code snippets
Closes gh-30243
2023-03-31 15:51:56 +02:00
Sam Brannen 3632bea51e Polishing 2023-03-31 13:52:05 +02:00
Brian Clozel 1efa162cf0 WebClient defaultStatusHandler do not apply to exchangeTo*
This commit documents the fact that default status handlers configured
on the `WebClient` are not applied to `exchangeTo*` methods as those
variants give full access to the client response.

Applying them here would restrict the ability to adapt the behavior
depending on the HTTP response status.

Closes gh-30059
2023-03-31 11:19:40 +02:00
Harry Yang a8b7a5e037 Refine initRequestBuilder in DefaultWebClient
Closes gh-30254
2023-03-31 10:53:51 +02:00
Sébastien Deleuze 807325916f Add class hints for Jackson annotations on fields and methods
Before this commit, only class level annotations were
processed.

Closes gh-30208
2023-03-31 10:39:18 +02:00
Brian Clozel d451d6adcc Ensure that client responses are observed when filters fail
Prior to this commit, an error thrown by a `ExchangeFilterFunction`
configured on a `WebClient` instance would be recorded as such by the
client observation, but the response details would be missing from the
observation.
All filter functions and the exchange function (performing the HTTP
call) would be merged into a single `ExchangeFunction`; this instance
was instrumented and osberved. As a result, the instrumentation would
only get the error signal returned by the filter function and would not
see the HTTP response even if it was received. This means that the
recorded observation would not have the relevant information for the
HTTP status.

This commit ensures that between the configured `ExchangeFilterFunction`
and the `ExchangeFunction`, an instrumentation `ExchangeFilterFunction`
is inserted. This allows to set the client response to the observation
context, even if a later error signal is thrown by a filter function.

Note that with this change, an error signal sent by a filter function
will be still recorded in the observation.

See gh-30059
2023-03-30 20:04:48 +02:00
Juergen Hoeller 8fca258207 Propagate HttpStreamResetException itself if cause is null
Closes gh-30245
2023-03-30 19:22:30 +02:00
Sébastien Deleuze d126b99c91 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-30214
2023-03-30 18:07:01 +02:00
Sébastien Deleuze c5f0f7bb11 Refine DisposableBeanAdapter method discovery for native
After this commit, DisposableBeanAdapter can find destruction related methods
even when hints are just specified at interface level, which is typically the
case when a bean is exposed via one of its interfaces.

Closes gh-29545
2023-03-30 15:28:50 +02:00
Brian Clozel 3a36d51473 Polish
See gh-29246
2023-03-30 14:49:11 +02:00
Brian Clozel fe6589d5af Add runtime hint test for inherited destroy methods
This commit ensures that init/destroy methods that are provided as
default methods from interfaces are properly covered by runtime hints at
runtime.

Closes gh-29246
2023-03-30 14:42:19 +02:00
Brian Clozel b374824319 Contribute introspection hints on registered beans
Prior to this commit, reflection hints registered for beans was
selectively applied to only consider the methods that we'll actually
need reflection on at runtime. This would rely on an undocumented
behavior of GraalVM Native where calling `getDeclaredMethods` on a type
would only return known metadata at runtime, ignoring the ones that were
not registered during native compilation.

As of oracle/graal#5171, this behavior is now fixed in GraalVM and
aligns with the JVM behavior: all methods will be returned. This means
that if during native compilation, introspection was not registered for
the type a new `MissingReflectionMetadataException` will be raised.

As a follow up of #29205, this commit contributes the "introspection on
declared method" reflection hint for all registered beans.

Closes gh-29246
2023-03-29 21:16:59 +02:00
Juergen Hoeller 7e905e3e00 Use JdkDynamicAopProxy class loader instead of JDK bootstrap/platform loader
Closes gh-30115
2023-03-29 13:46:29 +02:00
Juergen Hoeller 491ae1e3be Use MethodInvocationInfo class loader in case of JDK platform loader as well
Closes gh-30210
2023-03-29 13:46:18 +02:00
Brian Clozel 66cdf43b56 Polish
Closes gh-30223
2023-03-29 10:55:48 +02:00
James Yuzawa 2ba206f8ba Order metric labels in ObservationConventions
See gh-30223
2023-03-29 10:55:34 +02:00
James Yuzawa 5ba6944145 Remove String.formatter from DefaultServerRequestObservationConvention
Closes gh-30218
2023-03-28 20:24:55 +02:00
Arjen Poutsma 5609e67100 Improve Javadoc of MultipartBodyBuilder
This commit improves the Javadoc of MultipartBodyBuilder, to make it
clear that it is intended for multipart/form-data.

See gh-30179
2023-03-28 14:04:09 +02:00
Juergen Hoeller b2be07c73c Polishing 2023-03-28 13:26:29 +02:00
Juergen Hoeller ce2689eead Use MethodInvocationInfo class loader in case of core JDK interface type
Closes gh-30210
2023-03-28 13:20:49 +02:00
Johnny Lim 2184d4e80e Fix incomplete assertions
Closes gh-30209
2023-03-28 10:56:41 +02:00
Ed .d 50d01ce405 feat: Add support for Vavr's Try monad to trigger transaction rollbacks
Updated the Spring Framework documentation to include an example of using Vavr's Try monad to trigger transaction rollbacks when a @Transactional-annotated method returns a Failure. The modified documentation demonstrates how to use Try in a transactional method and how to check if an exception has been wrapped inside a Try.Failure instance. Additionally, a link to the official Vavr documentation was added to provide more information on the Try method.
2023-03-28 10:38:03 +02:00
Sam Brannen 0c0cda9815 Polish contribution
See gh-30189
2023-03-27 19:31:35 +02:00
Harry Yang 47aca90c58 Optimize array creation in SpEL ConstructorReference
- Create primitive arrays directly instead of using Array#newInstance.

- Replace if-else blocks with enhanced switch statement.

Closes gh-30189
2023-03-27 19:31:35 +02:00
Sam Brannen ddd6b123bb Polish TypeCode 2023-03-27 19:31:35 +02:00
heqiang ec270c7135 Use diamond operator in examples in reference manual
Closes gh-30204
2023-03-27 18:27:29 +02:00
Sébastien Deleuze 7cc72ddf7a Add HttpMethod reflection hint to ObjectToObjectConverterRuntimeHints
This commit adds a reflection hint for HttpMethod#valueOf in order
to be able to support conversion required for Spring Boot
configuration properties binding as described in
https://github.com/spring-projects/spring-boot/issues/34483.

Closes gh-30201
2023-03-27 15:13:15 +02:00
Sam Brannen 5f0ee2e4dd Polish ConstructorReference 2023-03-25 17:40:00 +01:00
Johnny Lim 43031509c8 Update versions in Javadoc
Closes gh-30170
2023-03-25 17:13:36 +01:00
ghostg00 e66c80667f 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-30183
2023-03-24 17:54:33 +01:00
Sam Brannen 84714fbae9 Allow JDK 20 builds to pass by using legacy locale data
After setting up a JDK 20 CI build pipeline, numerous tests involving
date/time parsing and formatting began to fail [0]. (The failing JPA
tests are not specific to JDK 20.)

For example, we encounter visually confusing assertion failures such as
the following.

org.opentest4j.AssertionFailedError:
	expected: "12:00 PM"
	but was:  "12:00 PM"

The expected string contains a normal space (which has always been the
case prior to JDK 20); whereas, the actual string now contains a narrow
non-breaking space.

The cause of this is mentioned in the JDK 20 Release Notes [1] as "NBSP
prefixed to a, instead of a normal space". Note, however, that the
links for the first two bullet points in that section are mixed up.
"NBSP prefixed to a, instead of a normal space" should point to [2].
Furthermore, the new whitespace character is not a non-breaking space
(NBSP) but rather a narrow non-breaking space (NNBSP). In addition, the
second bullet point should technically read "NNBSP prefixed to `a`,
instead of a normal space" -- even though `a` provides limited value to
most readers.

The downside for the Java community is that this constitutes a breaking
change for parsing and formatting date/time values that include "AM"
and "PM" units (any may potentially apply to other date/time
parsing/formatting scenarios). In Spring Framework's test suite we have
witnessed this in conjunction with Spring's @DateTimeFormat and
DateTimeFormatterFactory infrastructure as well as with Google's
Gson-to-JSON support.

A colleague who works at Oracle graciously informed me that one can use
"legacy locale data" by supplying `-Djava.locale.providers=COMPAT` as a
JVM argument, noting however that this option limits some newer
functionalities (but without enumerating which new functionalities one
might be missing when using this option).

In any case, this commit adds that JVM argument to our Gradle toolchain
builds so that our test suite passes on JDK 20, and we will continue to
investigate further options for our builds and for our users.

Note, however, that one must manually configure the
`-Djava.locale.providers=COMPAT` JVM argument when running affected
tests within an IDE.

See gh-30185

[0] https://ge.spring.io/s/kmiq2bz2afafs/tests/overview?outcome=failed
[1] https://jdk.java.net/20/release-notes#JDK-8284840
[2] https://unicode-org.atlassian.net/browse/CLDR-14032
2023-03-24 16:08:38 +01:00
Sam Brannen 0ca02ce677 Disable affected tests on Java 18+/19+
See gh-30185
2023-03-24 16:05:40 +01:00
Sam Brannen db29b65399 Polishing 2023-03-24 16:05:40 +01:00
Sam Brannen 18adf905a8 Polishing 2023-03-23 17:04:41 +01:00
Sam Brannen ce9a72f95c Update copyright headers 2023-03-23 16:56:20 +01:00
Sam Brannen dfb4a951ae Suppress deprecation warnings instead of deprecating tests 2023-03-23 16:55:12 +01:00
Brian Clozel d9776941bf Update Java version for compatibility tests in CI
This commit configures Java 20 for compatibility tests in our CI,
replacing Java 19.
2023-03-23 15:47:06 +01:00
Giuseppe 24b359d519 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-30161
2023-03-22 15:39:53 +01:00
Arjen Poutsma ae70bf7c38 Merge pull request #30138 from yuzawa-san:LiteralPathElement-string-equals
* gh-30138:
  Polish external contribution
  Use String.equals() in LiteralPathElement
2023-03-22 12:13:45 +01:00
Arjen Poutsma c68e986b75 Polish external contribution
This commit removes the text char[] in favor of the text String
introduced through the PR.

Closes gh-30138
2023-03-22 12:10:18 +01:00
James Yuzawa 2bc1aa7827 Use String.equals() in LiteralPathElement 2023-03-22 12:10:18 +01:00
Kukri 570d21ebbd Fix anchor in link to "Web on Reactive Stack" chapter
Closes gh-30158
2023-03-22 11:30:35 +01:00
James Yuzawa 800b13492b Optimize some iterations in BodyExtractor and BodyInserter
This commit turns some stream-based iterations back into simpler
enhanced for loops.

For simple use cases like these, where the stream API is merely used to
map/filter + collect to a List, a for loop is more efficient.
This is especially true for small collections like the ones we deal
with in BodyInserters/BodyExtractors here (in the order of 50ns/op vs
5ns/op). These cases are also simple enough that they don't lose in
readability after the conversion.

Closes gh-30136
2023-03-22 11:04:54 +01:00
Сергей Цыпанов 4e896c8125 Use InputStream.readAllBytes() in FileCopyUtils.copyToByteArray()
InputStream.readAllBytes() allows us to avoid the creation of an
intermediate ByteArrayOutputStream and is likely to perform better.

Closes gh-30155
2023-03-21 15:37:26 +01:00
Arjen Poutsma 9421fe1d75 Merge pull request #30139 from yuzawa-san:cache-reactor-request-methods
* gh-30139:
  Cache ServerHttpRequest::getMethod in AbstractServerHttpRequest
  cache reactor request methods
2023-03-21 11:36:11 +01:00
Arjen Poutsma 37a4e84450 Cache ServerHttpRequest::getMethod in AbstractServerHttpRequest
This commit ensures that the HttpMethod, exposed through
ServerHttpRequest::getMethod, is cached in AbstractServerHttpRequest so
that potentially expensive HTTP method lookups are only done once.

Closes gh-30139
2023-03-21 11:29:32 +01:00
James Yuzawa c27a5687dc cache reactor request methods 2023-03-21 09:39:04 +01:00
Spring Builds 4e8162c6dd Next development version (v6.0.8-SNAPSHOT) 2023-03-20 09:53:24 +00:00
rstoyanchev 202fa5cdb3 Polishing and minor refactoring in HandlerMappingIntrospector
Closes gh-30127
2023-03-20 08:36:40 +00:00
Sam Brannen 8010de8b63 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-30144
2023-03-19 23:57:55 +01:00
Sam Brannen 5529294ec9 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-30142
2023-03-19 23:57:55 +01:00
Sam Brannen 935c29e3dd 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-30140
2023-03-19 23:57:55 +01:00
Sam Brannen 4a3518b4d6 Polishing 2023-03-19 23:55:45 +01:00
Sam Brannen dd4a34778b Stop printing to System.out in SpEL tests 2023-03-19 23:55:36 +01:00
Brian Clozel 46bd6add15 Mention JAR signing key in SECURITY.md
This commit adds a link to the now published information on spring.io
about the GPG key used to sign the Spring artifacts published on Maven
Central.

Closes gh-23434
2023-03-17 22:32:33 +01:00
Juergen Hoeller 19384ac8ad Polishing 2023-03-17 17:37:23 +01:00
Juergen Hoeller a0358a4650 Upgrade to Reactor 2022.0.5 and Netty 4.1.90
Includes Checkstyle 10.9.1 and Mockito 5.2.0

Closes gh-30133
2023-03-17 17:36:51 +01:00
Juergen Hoeller 88bc504625 Skip validation constraint hint inference if no provider available
Closes gh-30130
2023-03-17 17:36:31 +01:00
Brian Clozel 3af8efbdc7 Add anchor rewrites in the reference documentation
This commit adds an `anchor-rewrite.properties` file in the reference
documentation sources. This allows to redirect from one anchor to
another when they are renamed.

This also populates the file with anchors that were renamed in the AOT
section of the documentation.

Closes gh-30132
2023-03-17 17:28:12 +01:00
Brian Clozel 2e08a07d7c Add a list of produced observations
This commit adds a list observations produced by Spring Framework in the
reference documentation.

Closes gh-30060
2023-03-17 17:27:11 +01:00
Sam Brannen df4e7d1929 Polishing 2023-03-15 15:08:47 +01:00
Brian Clozel 2a5eab4b89 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-29915
2023-03-15 10:16:27 +01:00
Sam Brannen 1de36abc07 Revise contribution
See gh-25316
2023-03-14 17:28:12 +01:00
mrcoffee77 97b5af8a55 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-14 17:19:06 +01:00
Sam Brannen 4751769a7c Polishing 2023-03-14 17:18:43 +01:00
Arjen Poutsma 1f8e9f5c55 Support Windows path in ContentDisposition::parse
This commit makes sure that ContentDisposition::parse supports Windows
path with a backslash.

Closes gh-30111
2023-03-14 14:19:33 +01:00
rstoyanchev c3ce847871 Polishing contribution
Closes gh-30092
2023-03-14 11:10:02 +00:00
James Yuzawa cd8955fa72 Remove extra copy in WebClient headers/cookies
See gh-30092
2023-03-14 10:49:53 +00:00
rstoyanchev d18bcb3f3d Raise MethodArgumentNotValidException consistently
Closes gh-30100
2023-03-14 09:08:57 +00:00
Sam Brannen e17f5c50a8 Update copyright headers 2023-03-13 21:53:40 +01:00
Sam Brannen 00be19c647 Consistently declare Object::equals argument as @Nullable 2023-03-13 21:43:21 +01:00
Sam Brannen a6dab10309 Update code regarding null-safety semantics
See gh-30083
2023-03-13 21:19:46 +01:00
Sam Brannen b617e16d8d Polishing 2023-03-13 21:16:02 +01:00
Sam Brannen 9cf7b0e230 Polishing 2023-03-12 18:38:50 +01:00
Juergen Hoeller 3431b2330a Avoid unnecessary parameter name inspection for factory method type check
Closes gh-30103
See gh-29612
2023-03-10 19:19:19 +01:00
Sam Brannen 99e54fec3a Ensure all packages declare package-info.java with null-safety annotations
This commit picks up where the two previous commits left off.

Specifically, this commit:

- Removes the "severity=warning" configuration to ensure that violations
  actually fail the build.
- Fixes regular expressions for suppressions by matching forward
  slashes using `[\\/]` instead of `\/`.
- Moves the configuration for newly introduced checks to locations in
  checkstyle.xml that align with the existing organization of that file.
- Renames the IDs for RegexpSinglelineJava checks from
  javaDocPackageNonNullApiAnnotation/javaDocPackageNonNullFieldsAnnotation
  to packageLevelNonNullApiAnnotation/packageLevelNonNullFieldsAnnotation,
  respectively, since these checks are not related to Javadoc.
- Simplifies the null-safety annotation checks to match against
  imported annotation types, which enforces consistency across
  package-info.java files for the annotation declarations.
- Simplifies the RegEx for JavadocPackage suppressions to only exclude
  packages not under src/main/java (vs src/main) and those in the
  framework-docs module.
- Consistently suppresses all checks for the `asm`, `cglib`, `objenesis`,
  and `javapoet` packages in spring-core.
- Adds explicit suppressions for null-safety annotations for the `lang`
  package in spring-core.
- Adds explicit suppressions for null-safety annotations for the
  `org.aopalliance` package in spring-aop.
- Revises the RegEx for null-safety annotation suppressions to only
  exclude package-info.java files not under src/main/java and
  additionally to exclude package-info.java files in the framework-docs
  module as well as those in the spring-context-indexer,
  spring-instrument, and spring-jcl modules.
- Adds all missing package-info.java files.
- Adds null-safety annotations to package-info.java files where
  appropriate.

Closes gh-30069
2023-03-10 17:33:52 +01:00
Ed .d 7e32f504b0 Configure Checkstyle to require package-level null-safety annotations
This commit updates the project's checkstyle configuration to check
that package-info.java files contain the @NonNullApi and @NonNullFields
null-safety annotations.

See gh-30069
2023-03-10 16:12:07 +01:00
Ed .d 268e3fec99 Configure Checkstyle to require package-info.java files
This commit updates the project's checkstyle configuration to require
the existence of a package-info.java file for all packages within the
src/main directory while excluding the framework-docs module and
certain packages inside the spring-core module. A missing
package-info.java file will result in emitting a warning.

See gh-30069
2023-03-10 16:09:17 +01:00
Simon Baslé 9b50c0d590 Ensure reactive transaction rollback on commit error
This change fixes a situation where error handling was skipped during
`processCommit()` in case the `doCommit()` failed. The error handling
was set up via an `onErrorResume` operator that was nested inside a
`then(...)`, applied to an inner `Mono.empty()`. As a consequence,
it would never receive an error signal (effectively decoupling the
onErrorResume from the main chain).

This change simply moves the error handling back one level up. It also
simplifies the `doCommit` code a bit by getting rid of the steps that
artificially introduce a `Mono<Object>` return type, which is not really
needed.

A pre-existing test was missing the fact that the rollback didn't occur,
which is now fixed. Another dedicated test is introduced building upon
the `ReactiveTestTransactionManager` class.

Closes gh-30096
2023-03-10 12:23:44 +01:00
Sam Brannen 2e5d0470dc Polishing 2023-03-09 14:19:59 +01:00
liupeng d2868f5dd0 Use Set to track ignored properties in BeanUtils.copyProperties()
Closes gh-30088
2023-03-09 14:11:22 +01:00
Abel Salgado Romero 1acbc97b16 Fix minor spacings in webflux docs
Closes gh-30078
2023-03-09 11:58:16 +01:00
Arjen Poutsma e88ec06a36 Disable flaky unit test for undertow 2023-03-09 10:03:07 +01:00
Juergen Hoeller 2302358606 Upgrade to Log4J 2.20, Tomcat 10.1.7, Jetty 11.0.14, Undertow 2.3.4 2023-03-08 16:53:43 +01:00
Juergen Hoeller d213522dfc Polishing 2023-03-08 16:49:32 +01:00
Juergen Hoeller 95710646d1 Pass pre-determined merged bean definition into InstanceSupplier (for inner beans)
Replaces useless protected obtainFromSupplier method with obtainInstanceFromSupplier.
Moves InstanceSupplier handling to appropriate subclass (DefaultListableBeanFactory).
BeanInstanceSupplier throws BeanInstantiationException instead of BeanCreationException.

Closes gh-29803
2023-03-08 16:49:25 +01:00
Brian Clozel 6cd67412cc 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.

Fixes gh-30066
2023-03-08 16:23:32 +01:00
Arjen Poutsma e427ea8086 Merge pull request #30046 from srivatsa-cfp:main
* gh-30046:
  Add non-null assertions in DefaultServerRequestBuilder
2023-03-08 15:36:37 +01:00
Vatsa d8fbd35467 Add non-null assertions in DefaultServerRequestBuilder
This commit adds various non-null assertions to
DefaultServerRequestBuilder, in both Spring MVC and WebFlux.

Closes gh-30046
2023-03-08 12:50:02 +01:00
Sam Brannen a31cfba992 Apply "instanceof pattern matching" in remainder of spring-websocket module
See gh-30067
2023-03-07 19:18:25 +01:00
Sébastien Deleuze 14973fd6f3 Unset reproducibleFileOrder and preserveFileTimestamps Gradle flags
This commit reverts the changes done via 50a0094a47
in order to ensure consistency across modules (those changes were specific to
spring-core).

Reproducible builds are likely desirable, but it is a complex topic
(see gradle/gradle#14819) that needs to be addressed portfolio wide, with
a better control than what Gradle currently allows (for example to allow
using EPOCH instead of the current 1980 date).

Basic tests did not show an obvious impact on testing avoidance with modern
Gradle versions.

Closes gh-29633
2023-03-07 18:54:19 +01:00
Sam Brannen ffe7ec4a99 Apply "instanceof pattern matching" in remainder of spring-webmvc module
See gh-30067
2023-03-07 18:23:15 +01:00
Sam Brannen 9b811a01f6 Polishing 2023-03-07 15:20:10 +01:00
Sam Brannen 2b23d1693d Remove unused service package 2023-03-07 15:20:10 +01:00
Sam Brannen 9011ce9c68 Apply "instanceof pattern matching" in remainder of spring-web module
See gh-30067
2023-03-07 15:20:10 +01:00
Sam Brannen 29fe0a3c6a Update TODO for linking to JUnit 5 docs
See gh-27497
2023-03-07 13:28:25 +01:00
Sébastien Deleuze c20efba45c End javadoc generated AOT with a period consistently
Closes gh-29357
2023-03-07 11:20:37 +01:00
Sam Brannen fa95bf4dc1 Apply "instanceof pattern matching" in remainder of spring-test module
See gh-30067
2023-03-06 17:49:26 +01:00
Sam Brannen eea000d034 Apply "instanceof pattern matching" in remainder of spring-r2dbc module
See gh-30067
2023-03-06 17:21:28 +01:00
Sam Brannen a6338fcc43 Update copyright headers 2023-03-06 17:20:42 +01:00
Sam Brannen dafc7a2aab Apply "instanceof pattern matching" in remainder of spring-oxm module
See gh-30067
2023-03-06 17:07:49 +01:00
Sam Brannen b7288a4073 Apply "instanceof pattern matching" in remainder of spring-orm module
See gh-30067
2023-03-06 17:03:02 +01:00
Sam Brannen 004a144bdc Apply "instanceof pattern matching" in remainder of spring-messaging module
See gh-30067
2023-03-06 16:23:10 +01:00
Sam Brannen 09b60220d8 Apply "instanceof pattern matching" in remainder of spring-jms module
See gh-30067
2023-03-06 15:32:07 +01:00
Sam Brannen 7f1b81ff53 Apply "instanceof pattern matching" in remainder of spring-jdbc module
See gh-30067
2023-03-06 15:18:05 +01:00
Sam Brannen 8175a3bf09 Polishing 2023-03-06 15:17:39 +01:00
Sam Brannen 7eadedae36 Apply "instanceof pattern matching" in spring-jcl module
See gh-30067
2023-03-06 14:56:53 +01:00
Sam Brannen cb4f93561e Apply "instanceof pattern matching" in remainder of spring-expression module
See gh-30067
2023-03-06 14:45:28 +01:00
Sam Brannen f3cb331e4e Optimize find[Getter|Setter]ForProperty() in ReflectivePropertyAccessor 2023-03-06 14:45:28 +01:00
Sam Brannen 74f6725a37 Update copyright headers 2023-03-06 13:56:33 +01:00
Enric Sala edf0ae77e5 Avoid rollback after a commit failure in TransactionalOperator
A failure to commit a reactive transaction will complete the
transaction and clean up resources. Executing a rollback at
that point is invalid, which causes an
IllegalTransactionStateException that masks the cause of the
commit failure.

This change restructures TransactionalOperatorImpl and
ReactiveTransactionSupport to avoid executing a rollback after
a failed commit. While there, the Mono transaction handling in
TransactionalOperator is simplified by moving it to a default
method on the interface.

Closes gh-27572
2023-03-06 10:05:59 +01:00
Sam Brannen 95481018d0 Apply "instanceof pattern matching" in spring-core-test
See gh-30067
2023-03-05 19:37:59 +01:00
Sam Brannen 56523d5014 Polishing 2023-03-05 19:37:11 +01:00
Sam Brannen 8ebd746d69 Apply "instanceof pattern matching" in remainder of spring-core module
See gh-30067
2023-03-05 19:09:32 +01:00
Sam Brannen 162c09d036 Apply "instanceof pattern matching" in remainder of spring-context-support module
See gh-30067
2023-03-05 19:09:32 +01:00
Sam Brannen 7766b518d3 Apply "instanceof pattern matching" in spring-context-indexer module
See gh-30067
2023-03-05 19:09:32 +01:00
Sam Brannen 24de8c6f4c Apply "instanceof pattern matching" in remainder of spring-context module
See gh-30067
2023-03-05 19:09:32 +01:00
Sam Brannen d9500e60a1 Apply "instanceof pattern matching" in remainder of spring-beans module
See gh-30067
2023-03-05 19:09:32 +01:00
Sam Brannen e5d20a4f9d Convert EventExpressionRootObject to a record 2023-03-05 19:09:32 +01:00
Sam Brannen 37458d28d9 Covert InterceptorAndDynamicMethodMatcher to a record 2023-03-05 19:09:32 +01:00
Juergen Hoeller c9aba1eaad Enable Jetty 12 support in WebFlux
Closes gh-29575
2023-03-04 17:37:26 +01:00
Sam Brannen 3854861a8a Polishing 2023-03-03 15:39:24 +01:00
Spring Builds 3dd0fbfb57 Next development version (v6.0.7-SNAPSHOT) 2023-03-02 17:45:24 +00:00
Sam Brannen 57b838ddda Upgrade to spring-asciidoctor-backends 0.0.5 2023-03-02 16:50:48 +01:00
Sam Brannen 8c784085d2 Update copyright dates 2023-03-02 16:22:53 +01:00
Sam Brannen c0a1e1718e Polishing 2023-03-02 16:22:42 +01:00
Sam Brannen fe29e734ae Revise documentation for @AspectJ argument name resolution algorithm
Closes gh-30026
2023-03-02 15:26:21 +01:00
rstoyanchev 50c3a62589 Upgrade to Reactor Netty 2022.0.4
Closes gh-30063
2023-03-02 13:58:57 +00:00
Juergen Hoeller a936a6a8ce Javadoc-only reference to SubscribeMapping from simp package (-> package dependency cycle)
See gh-30002
2023-03-02 13:57:17 +01:00
Juergen Hoeller 8d112b8514 Test for explicit URI decoding in convertClassLoaderURL
See gh-30031
2023-03-02 13:33:53 +01:00
Juergen Hoeller f8cb0fa2a0 Custom resolution of preferred constructors for createBean(Class)
Avoids side effects of traditional AUTOWIRE_CONSTRUCTOR algorithm.

Closes gh-30041
2023-03-02 12:54:26 +01:00
rstoyanchev c56c16d7ba Polishing contribution
Closes gh-30010
2023-03-02 11:28:16 +00:00
Patrick Strawderman df1f8139cc Use Content-Length for optimal read to byte[]
If content-length is available, pass it to readNBytes in
ByteArrayHttpMessageConverter. When the content length is less than
the internal buffer size in InputStream (8192), this avoids a copy,
as readNBytes will return the buffer directly. When the content length
is greater than the buffer size used in InputStream, passing the
content-length at least avoids over-allocating the final buffer (e.g.,
if the content length were 8193 bytes, 1 byte more than the default
buffer size).

If the content length isn't present or is too large to represent as
an integer, fall back to the default behavior of readAllBytes by
passing in Integer.MAX_VALUE.

See gh-30010
2023-03-02 11:19:57 +00:00
rstoyanchev 9624ea392a Resolve baseUrl to String vs temporary URI
Along the lines of what was suggested in #30047.

Closes gh-30062
2023-03-02 10:20:05 +00:00
Violeta Georgieva 682a4d5353 Prefer request hostName and hostPort in ReactorServerHttpRequest
See gh-30062
2023-03-02 10:20:05 +00:00
Juergen Hoeller 4419d56178 Explicit URI decoding for FileSystemResource in convertClassLoaderURL
Also raising the log level to warn for file system retrieval failures.

Closes gh-30031
2023-03-02 10:18:13 +01:00
Sam Brannen 244c97993b Update documentation for @AspectJ argument name resolution algorithm
Closes gh-30026
2023-03-01 17:06:38 +01:00
Sam Brannen 9d28fe90f5 Simplify AbstractAspectJAdvisorFactory internals 2023-03-01 16:04:43 +01:00
Sébastien Deleuze d2a4ac519c Update build badge and link 2023-03-01 15:51:07 +01:00
Sébastien Deleuze dbbebf541d Refine reflection hints handling for anonymous class
Before this commit, anonymous classes could throw an
unexpected NullPointerException in
ReflectionsHint#registerType and lambdas entries could
be created in the related generated reflect-config.json.

This commit refines how anonymous classes are handled by
explicitly checking for null class and canonical name in
ReflectionTypeReference#of, while skipping such class in
ReflectionHints#registerType in order to keep a lenient
behavior.

Closes gh-29774
2023-03-01 15:41:30 +01:00
rstoyanchev fe73c630da Use URI String if necessary in ReactorClientHttpConnector
Closes gh-30053
2023-03-01 11:47:49 +00:00
Sam Brannen 3456fd054f 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-02-28 16:42:57 +01:00
Sam Brannen 5fd75dd27b Add missing package-info.java file for autoproxy.target package 2023-02-28 16:38:03 +01:00
Sam Brannen 6c29a5779e 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-02-28 16:36:32 +01:00
Sam Brannen e9413b93c6 Apply "instanceof pattern matching" in BeanFactoryAdvisorRetrievalHelper 2023-02-28 16:33:56 +01:00
Radek Kraus 4cc02fe3bc 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.

Closes gh-29116
See gh-29115
2023-02-28 16:10:05 +01:00
Sam Brannen b1cf832c28 Apply "instanceof pattern matching" in spring-tx
This commit applies "instanceof pattern matching" to the rest of the
code in spring-tx.

See gh-30019
2023-02-28 16:03:37 +01:00
Sam Brannen 34e5ce9360 Fix Checkstyle violations
See gh-30019
2023-02-28 16:03:37 +01:00
diguage 375114defa Apply "instanceof pattern matching" in spring-tx
Closes gh-30019
2023-02-28 15:33:59 +01:00
Sam Brannen 00c2c1d2a1 Polish "Support @Value for record injection"
See gh-28774
2023-02-28 13:12:15 +01:00
nanfeng 7c9fc575ff Support @Value for record injection
Add @Value support for record injection by disabling populateBean() for
records, since records are immutable.

See gh-28770
Closes gh-28774
2023-02-28 13:01:13 +01:00
rstoyanchev c859211f7a Polishing contribution
Closes gh-29691
2023-02-27 17:37:28 +00:00
Baljit Singh 4dbe9d6709 Use ContextView in ServerWebExchangeContextFilter 2023-02-27 17:20:16 +00:00
rstoyanchev acedbfbaba Polishing contribution
Closes gh-30014
2023-02-27 17:18:53 +00:00
Sergiu Prodan 5d6f151031 Update Javadoc of ServletRequestPathFilter
See gh-30014
2023-02-27 17:10:27 +00:00
Sam Brannen a09495d4e9 Polish contribution
See gh-30034
2023-02-27 16:38:55 +01:00
1993heqiang 5cab6a1f3a Fix "Configuring a Global Date and Time Format" example
Closes gh-30034
2023-02-27 16:33:38 +01:00
Sébastien Deleuze a02a017e6e Add tests for SpEL on Kotlin suspending function parameters
This was broken at some point but seems to work now.
This commit adds related tests.

Closes gh-26867
2023-02-27 16:09:43 +01:00
Sébastien Deleuze 9f2f93129b Move HttpServiceProxyFactoryExtensions.kt to spring-web module
HttpServiceProxyFactoryExtensions.kt has been mistakenly created
in spring-webflux module instead of spring-web, breaking JPMS for
WebFlux users.

This commit moves this file and related tests to the spring-web
module.

Closes gh-30042
2023-02-27 14:48:28 +01:00
Johnny Lim 475ac6ef5d Fix KotlinCoroutinesUtilsTests.invokeNonSuspendingFunctionWithContext()
Closes gh-30029
2023-02-27 14:02:49 +01:00
Sébastien Deleuze 79f43041ad Catch defensively validator exceptions in AOT processing
An ArrayIndexOutOfBoundsException is thrown by
Validator.getConstraintsForClass when processing Kotlin beans
with extensions functions (Kotlin or Hibernate Validator bug).

This commit catches those exceptions and report them as warning
without the full stactrace, and report as well other
ones thrown as errors with the full stracktrace.

Closes gh-30037
2023-02-27 12:06:37 +01:00
Sam Brannen edb4a3467a Update copyright headers 2023-02-26 18:37:18 +01:00
Sam Brannen 024d02225c Apply "instanceof pattern matching" to remaining Validation classes 2023-02-26 18:37:18 +01:00
Sam Brannen 9305a64a50 Polish contribution
See gh-29994
2023-02-26 18:30:14 +01:00
divcon 40672c3715 Apply "instance of patten matching" in context and messaging modules
Closes gh-29994
2023-02-26 18:30:14 +01:00
Sam Brannen 7c50464bba Polishing 2023-02-26 18:30:14 +01:00
Patrick Strawderman 0d10d4beee Initialize ArrayList with exact size in HttpHeaders 2023-02-24 17:09:58 +00:00
Sébastien Deleuze f60bec986f Add missing @Nullable annotations to LogMessage methods
Closes gh-30006
2023-02-24 17:45:50 +01:00
Sébastien Deleuze 6825a842b5 Support package private methods on CGLIB proxies with AOT
Closes gh-29582
Closes gh-29764
2023-02-24 17:00:41 +01:00
Sam Brannen 7ace9aa429 Polish AspectJAdviceParameterNameDiscoverer
This commit also converts PointcutBody to a record.
2023-02-24 11:40:34 +01:00
Sam Brannen 8979ac789f Fix layout in "Determining Argument Names" section 2023-02-24 11:40:34 +01:00
Sébastien Deleuze 9cb4c5565a Fix proxy hint Kotlin extensions
Closes gh-30025
2023-02-24 10:46:27 +01:00
Sam Brannen 08f38c52c7 Revise AspectJ examples in the reference manual
The extensive use of shared pointcuts can be confusing to users who
read a given AspectJ example without having read the "Sharing Common
Pointcut Definitions" section of the AOP chapter.

The primary purpose of this commit is therefore to reduce the extensive
use of shared pointcuts in AspectJ examples by favoring "inline
pointcuts" over shared "named pointcuts" and by cross referencing the
declaration of shared pointcuts when they are used.

Since the affected parts of the documentation are intertwined, this
commit also refactors the examples to use a common "com.xyz" package
namespace for greater clarity.

In order to avoid the need to escape asterisks (\*) in examples, this
commit also removes the `subs="quotes"` configuration for code blocks.

Closes gh-30003
2023-02-24 10:21:32 +01:00
Sam Brannen afa936e985 Polish AOP chapter 2023-02-24 10:21:32 +01:00
AlexElin 3677d3597b Improve @Lazy's javadoc by adding @code tag 2023-02-23 17:27:01 +00:00
Sam Brannen 76bc7deb8e Polish AOP chapter 2023-02-22 17:30:20 +01:00
Sam Brannen 6c3cb5d2e0 Revise chomp and fold settings in reference documentation
This commit overrides the `chomp` and `fold` settings for
spring-asciidoctor-backends on a per-block basis.

Closes gh-30001
2023-02-22 12:49:20 +01:00
Sam Brannen 3ce71932c0 Polish reference docs 2023-02-22 12:48:40 +01:00
Sam Brannen 3a9c7524f0 Polishing 2023-02-22 11:21:00 +01:00
Sam Brannen ce66b251ab Fix Javadoc for MockRestRequestMatchers 2023-02-21 22:13:41 +01:00
Sébastien Deleuze 626a7fc52a Add native support for @SubscribeMapping and @MessageExceptionHandler
Closes gh-30002
2023-02-21 18:47:30 +01:00
Sébastien Deleuze 3d8455b257 Add unit tests for CoroutinesUtils
Closes gh-29968
2023-02-21 10:20:00 +01:00
Sébastien Deleuze fd38c23699 Refine CoroutinesUtils#invokeSuspendingFunction contract
This commit refines CoroutinesUtils#invokeSuspendingFunction in order
to clarify the behavior when used on a non suspending function, and
support usages with or without the Continuation argument.

Closes gh-30005
2023-02-21 10:20:00 +01:00
Sam Brannen e47418c948 Polish attributes.adoc 2023-02-20 17:23:07 +01:00
Sam Brannen d6de374424 Restore package & import statements in AOP examples in ref docs
See gh-30001
2023-02-20 17:23:07 +01:00
Sam Brannen b437b7be34 Introduce test for perthis with @Aspect and shared pointcut
This commit modifies PerThisAspect (which is used indirectly in
AspectJAutoProxyCreatorTests.perThisAspect()) so that it uses a shared
@Pointcut for both the @Aspect and @Around declarations, in order to
refute claims made in gh-29998 that the documentation in the reference
manual is incorrect.
2023-02-20 17:23:07 +01:00
Sam Brannen 2d56505ea9 Polishing 2023-02-20 16:49:27 +01:00
Sam Brannen 8a44b6445d Revise queryParam() and header() support in MockRestRequestMatchers
See gh-29953
See gh-29964
2023-02-19 18:52:44 +01:00
Sam Brannen 6d24e62e83 Polishing 2023-02-19 17:43:31 +01:00
Johnny Lim 2d62be8590 Fix Javadoc since for MockRestRequestMatchers queryParam() and header() (#29986)
See gh-29953
See gh-29964
2023-02-19 16:04:53 +01:00
Sam Brannen 2e1374b459 Update copyright headers 2023-02-19 13:41:36 +01:00
Sam Brannen bb6150e44e Use correct Kotlin file extension in update_copyright_headers.sh 2023-02-19 13:41:36 +01:00
Sam Brannen 38a4f23f16 Polishing 2023-02-19 13:41:36 +01:00
Johnny Lim 6739ca82ce Polishing
See gh-23846
See gh-29955
Closes gh-29992
2023-02-19 13:41:36 +01:00
Arjen Poutsma 88e6544d9d Fix regression in WebFlux support for WebDAV methods
This commit ensures that WebFlux's RequestMethodsRequestCondition
supports HTTP methods that are not in the RequestMethod enum.

- RequestMethod::resolve is introduced, to convert from a HttpMethod
(name) to enum values.
- RequestMethod::asHttpMethod is introduced, to convert from enum value
to HttpMethod.
- HttpMethod::valueOf replaced Map-based lookup to a switch statement
- Enabled tests that check for WebDAV methods

See gh-27697
Closes gh-29981
2023-02-17 12:46:26 +01:00
Spring Builds 1999c78350 Next development version (v6.0.6-SNAPSHOT) 2023-02-15 16:20:19 +00:00
Arjen Poutsma afd67a0deb Fix DataBufferUtils::write AsynchronousFileChannel race condition
See gh-29943
2023-02-15 15:38:48 +01:00
Jerome Prinet dcaddddbc5 Update Gradle Enterprise plugin
Closes gh-29969
2023-02-15 14:43:31 +01:00
Johnny Lim ce3be72e7f Polish 2023-02-15 22:22:58 +09:00
Juergen Hoeller 3e3f046dc9 Polishing 2023-02-15 12:57:44 +01:00
rstoyanchev 5847454aa4 Prefer local hostAddress in ReactorServerHttpRequest
Closes gh-28601
2023-02-15 10:26:49 +00:00
Sébastien Deleuze 569df6eecc Refine ModelAttributeMethodProcessor Kotlin exception handling
This commit refines ModelAttributeMethodProcessor Kotlin exception
handling in order to throw a proper MethodArgumentNotValidException
instead of a NullPointerException when Kotlin null-safety constraints
are not fulfilled, translating to an HTTP error with 400 status code
(Bad Request) instead of 500 (Internal Server Error).

Closes gh-23846
2023-02-15 11:02:46 +01:00
Juergen Hoeller 979118c1eb Polishing 2023-02-15 10:13:16 +01:00
Juergen Hoeller f87a87e29d Consistent ordering of Resource methods
See gh-24651
2023-02-15 10:13:03 +01:00
Juergen Hoeller 0619e19140 Upgrade to Reactor 2022.0.3
Closes gh-29900
2023-02-15 10:12:48 +01:00
Sébastien Deleuze ac521a366a Refine instance supplier check in BeanDefinitionMethodGenerator
This commit refines the instance supplier check in
BeanDefinitionMethodGenerator constructor in order to allow
overriding by an AOT contribution.

Closes gh-29556
2023-02-15 09:32:00 +01:00
rstoyanchev 9a4df5a97d DefaultHandlerExceptionResolver respects custom ModelAndView
Closes gh-29971
2023-02-14 20:13:15 +00:00
rstoyanchev f54e1ef880 Initialize propertyName
MethodArgumentTypeMismatchException and
MethodArgumentConversionNotSupportedException are TypeMismatchException
subclasses with MethodParameter information and should initialize
propertyName in TypeMismatchInformation.

Closes gh-29959
2023-02-14 18:12:48 +00:00
rstoyanchev a3efcabe0c Polishing contribution
Closes gh-29954
2023-02-14 17:40:12 +00:00
James Yuzawa dd3dc2d0d0 Pass URI to Reactor Netty HttpClient
See gh-29954
2023-02-14 17:40:12 +00:00
Brian Clozel 2578e3894e Upgrade to Micrometer 1.10.4
Closes gh-29899
2023-02-14 17:10:10 +01:00
Brian Clozel 5335778d8d Polish
See gh-29955
2023-02-14 17:08:24 +01:00
Toshiaki Maki 616e7779e0 Add RFC-8246 support to CacheControl
This commit adds the "immutable" Cache-Control directives in `CacheControl`.

Closes gh-29955
2023-02-14 17:08:24 +01:00
Juergen Hoeller 84c7f07364 Consistent @Bean method return type for equivalence with XML example
Closes gh-29338
2023-02-14 16:36:31 +01:00
Juergen Hoeller ac429a4ef7 Restore fallback to request attributes in FreeMarker template model
Closes gh-29787
2023-02-14 16:36:07 +01:00
Arjen Poutsma 12d4dc1bae Polishing external contribution
This commit makes several changes to PR #24651.

- Add byte[] getContentAsByteArray() on Resource.
- Remove getContentAsString() from Resource, as it relied on the default
charset which is not reliable.
- Add getContentAsString() to EncodedResource, as a charset is provided
through the constructor.

See gh-24651
2023-02-14 14:56:34 +01:00
Derrick Anderson 4da2499613 Introduce Resource::getContentAsString
This commit introduces the getContentAsString method to Resource,
returning the string contents of the resource.

Closes gh-24651
2023-02-14 14:37:40 +01:00
rstoyanchev 18896aceca Adapt empty path to "/" in MockMvc
Closes gh-29933
2023-02-14 12:01:59 +00:00
Juergen Hoeller d7824c7831 Polishing 2023-02-14 11:00:01 +01:00
Juergen Hoeller f91b2249b3 Upgrade to Netty 4.1.89 2023-02-14 10:58:15 +01:00
Juergen Hoeller 33b329e13a Latest patch from ASM master
See gh-29910
2023-02-14 10:58:03 +01:00
rstoyanchev b23316302d Avoid blocking in InMemoryWebSessionStore#changeSessionId
Closes gh-29212
2023-02-13 18:39:19 +00:00
rstoyanchev dc843adb45 Improve docs on {@code Accept-Language} negotiation
Closes gh-28673
2023-02-13 18:39:19 +00:00
rstoyanchev 9fcafd2650 WebSocketConnectionManager accepts prepared URI
Closes gh-28524
2023-02-13 18:39:19 +00:00
rstoyanchev ccbb4bdd27 PayloadMethodArgumentResolver supports Optional
Closes gh-28945
2023-02-13 18:39:19 +00:00
rstoyanchev 5b79a57f14 Polishing
See gh-28945
2023-02-13 18:39:19 +00:00
Simon Baslé 189d4e3e4c 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-28660
Closes gh-29953
2023-02-13 17:51:01 +01:00
Arjen Poutsma 79a1fcb099 Polishing DataBuffer::write(CharSequence, Charset)
See gh-29943
2023-02-13 16:34:04 +01:00
Sébastien Deleuze 026be04b75 Polish CoroutinesAnnotationTransactionInterceptorTests 2023-02-13 15:34:01 +01:00
Sébastien Deleuze 45ae00fda3 Propagate the context in Coroutines transactions
This commit ensures that CoroutineContext is properly
propagated in transactional suspending functions. Both
annotation and functional variants are supported.

Closes gh-27308
2023-02-13 15:34:01 +01:00
Arjen Poutsma 3e2f58cdd2 Offer restricted access to DataBuffer's ByteBuffer
This commit introduces DataBuffer::readableByteBuffers and
DataBuffer::writableByteBuffers, allowing restricted access to the
ByteBuffer used internally by DataBuffer implementations.

Closes gh-29943
2023-02-13 15:28:29 +01:00
Boris Fox 72926c29f9 Temporarily set LocaleContextHolder to provide validation message interpolator with locale context (fixes SPR-17231). 2023-02-13 11:45:45 +00:00
rstoyanchev f5c1e2ffa1 Polishing contribution
Includes small refactoring in DefaultServerWebExchange and adjustment
of initMultipartData to get involved for any "multipart/" prefixed
media type.

In addition, "multipart/related" is now in the list of media types
supported by FormHttpMessageConverter, which aligns it with
MultipartHttpMessageReader.

Closes gh-29671
2023-02-13 11:40:36 +00:00
Ronny Perinke 67df0756cd Support multipart/mixed and related in DefaultServerWebExchange
See gh-29671
2023-02-13 10:39:23 +00:00
rstoyanchev 17bc3facaa Polishing contribution
Closes gh-29220
2023-02-13 09:16:33 +00:00
Anatolii Zhmaiev 1de9426df0 Set reason for WebSocket CloseStatus.SESSION_NOT_RELIABLE
See gh-29220
2023-02-13 09:16:33 +00:00
rstoyanchev 27fdf56ed5 Polishing contribution
Closes gh-29949
2023-02-13 07:52:01 +00:00
Yanming Zhou 55392dfbd7 Define xml namespace as constant
See gh-29949
2023-02-13 07:51:30 +00:00
Juergen Hoeller ca9439657e Detect MSSQL code 2601 as duplicate key (aligned with sql-error-codes.xml)
Closes gh-29950
2023-02-09 14:59:09 +01:00
Sébastien Deleuze 5819d76d98 Document AOT limitation regarding to @Bean type
Closes gh-29944
2023-02-09 10:34:42 +01:00
Johnny Lim 431ae03447 Polish
Closes gh-29928
2023-02-09 09:54:19 +01:00
rstoyanchev a7ec6b4a2a Unwrap session before selecting stats counter
See gh-29375
2023-02-08 18:12:42 +00:00
rstoyanchev e5ff54955f ProblemDetail XML support via Jackson
Closes gh-29927
2023-02-08 10:39:41 +00:00
rstoyanchev 9c0b28ffdc Fix StringIndexOutOfBoundsException
Closes gh-29588
2023-02-07 20:17:07 +00:00
Sam Brannen 08e7f5a292 Clearly document that DataClassRowMapper supports Java records
Closes gh-29814
2023-02-07 19:05:47 +01:00
Sam Brannen 5f458e2578 Polish RowMapper tests 2023-02-07 19:05:38 +01:00
Sam Brannen 7584dfc79a 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 18:31:50 +01:00
Juergen Hoeller dc2c33e0ab Upgrade to Hibernate ORM 5.6.15, FreeMarker 2.3.32, TestNG 7.7.1, XMLUnit 2.9.1 2023-02-07 17:20:11 +01:00
Juergen Hoeller dbf360997a Convert non-pattern ClassLoader results to FileSystemResource if possible
Closes gh-29934
2023-02-07 17:19:23 +01:00
Juergen Hoeller b719a87061 Suggest AOP proxy or CGLIB_CLASS_SEPARATOR check instead of isCglibProxyClass
See gh-22706
2023-02-07 17:19:12 +01:00
Sam Brannen 97e557c886 Update copyright headers 2023-02-07 16:37:18 +01:00
Manthan BhattandSimon Baslé 89c170b095 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.

Closes gh-29483
Closes gh-29557

Co-authored-by: Simon Baslé <sbasle@vmware.com>
2023-02-07 16:23:56 +01:00
Sam Brannen 482482f62b Revise Testcontainers examples based on feedback
Closes gh-29939
2023-02-07 15:55:00 +01:00
Sébastien Deleuze a2a676241c Introduce HttpServiceProxyFactory#createClient Kotlin extension
Closes gh-29942
2023-02-07 15:50:30 +01:00
Johnny Lim 28602ad012 Add MockMvc.multipart() Kotlin extensions with HttpMethod
See gh-28545
See gh-28631
Closes gh-28634
2023-02-07 15:13:17 +01:00
Sam Brannen 8e9dc3590d Update @DynamicPropertySource examples regarding changes in Testcontainers
Closes gh-29939
2023-02-07 13:34:22 +01:00
Sébastien Deleuze b8a7aa9395 Refine ControllerMappingReflectiveProcessor documentation
Closes gh-29938
2023-02-07 12:00:07 +01:00
Sébastien Deleuze cb63164593 Refine Coroutines support in HttpServiceProxyFactory
Closes gh-29527
2023-02-07 11:07:30 +01:00
Sébastien Deleuze 9f061f1eec Refine KotlinWebClientHttpServiceProxyTests
See gh-29527
2023-02-07 11:07:30 +01:00
Donghyeon Kim 1d4bf58e8d Support Coroutines in HttpServiceProxyFactory
See gh-29527
2023-02-07 11:07:29 +01:00
rstoyanchev ce85fdc5c7 Always use application/problem+json with ProblemDetail
See gh-gh-29588
2023-02-07 08:57:24 +00:00
rstoyanchev 7851994a17 Refine empty path handling in MvcUriComponentsBuilder
Return "" from methods that obtain controller or method mapping to
avoid side effect of a trailing slash appearing.

Closes gh-29897
2023-02-07 08:57:24 +00:00
Sam Brannen 84bc1dfa89 Polish RowMapper tests 2023-02-03 17:47:50 +01:00
Sam Brannen 159a3e71f2 Clarify semantics of primitivesDefaultedForNullValue in BeanPropertyRowMapper
Closes gh-29923
2023-02-03 17:47:50 +01:00
Sam Brannen adbba712d6 Polish Javadoc for RowMappers 2023-02-03 17:47:50 +01:00
danuandSimon Baslé e050c37158 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.

Closes gh-29703

Co-authored-by: Simon Baslé <sbasle@vmware.com>
2023-02-03 17:33:55 +01:00
Brian Clozel eff1a1a664 Upgrade to Artifactory Resource 0.0.18 2023-02-03 00:38:57 +01:00
Brian Clozel 8838e0d825 Use Docker Hub credentials for CI release tasks 2023-02-03 00:34:58 +01:00
Brian Clozel 0d21f0b1d4 Remove Java 18 from CI image 2023-02-02 21:02:01 +01:00
Brian Clozel 41aeb07585 Rely only on Docker Hub for fetching OCI images 2023-02-02 20:56:50 +01:00
Sam Brannen 70aaec2a8d Use static imports for AssertJ assertions in Kotlin tests 2023-02-02 20:12:42 +01:00
Sam Brannen 3029b7b9be Fix build 2023-02-02 20:12:18 +01:00
Brian Clozel 708f600afe Document how to mark an observation as an error
The `ServerHttpObservationFilter` implementations record observations
for processed HTTP exchanges. The `Observation.Context` contains various
metadata contributed by the observation convention. The instrumentation
can also mark the observation as an error by setting any `Throwable` on
the context.

Because the instrumentation is done as filters, only exceptions reaching
the filter can be considered. Any error handled at a lower level by the
Framework can, or cannot be considered as an error for an observation.

This commit documents how a web application should opt-in for
considering a handled exception as an error for the current observation.

Closes gh-29848
2023-02-02 18:19:17 +01:00
Sébastien Deleuze f7418704de Add ResponseEntity.ofNullable()
To deal with non-Optional nullable objects.

Closes gh-29117
2023-02-02 16:42:42 +01:00
Brian Clozel 7440afe571 Document how to enable HTTP client Observation instrumentation
This commit documents how Observation instrumentation should be
activated for `RestTemplate` and `WebClient`: they both need an
`ObservationRegistry` configured to create and record actual
observations.
This is being done automatically in Spring Boot if auto-configured
builders (`RestTemplateBuilder`, `WebClient.Builder`) are used.

Closes gh-29904
2023-02-02 16:03:11 +01:00
Sam Brannen bc583ea74f Polish "Use switch expressions in SpEL's CodeFlow"
See gh-29020
2023-02-02 15:14:34 +01:00
Roman Ivanov dcda127b60 Use switch expressions in SpEL's CodeFlow
Closes gh-29020
2023-02-02 15:02:10 +01:00
Sam Brannen ac6385025b Polishing 2023-02-02 15:02:10 +01:00
Sébastien Deleuze e170c16b02 Refine TransactionalOperator.executeAndAwait nullability
Before this commit, TransactionalOperator.executeAndAwait had a rigid
null-safety handling. This commit takes advantage of Kotlin capability
to allow to deal with both non-null and nullable depending on the
nullability of the lambda.

Closes gh-29919
2023-02-02 14:39:33 +01:00
Olga Maciaszek-Sharma 4beb05ddb3 Add native support for RSocketExchange.
This commit introduces new AOT processors that look for
`@RSocketExchange` annotated methods on interfaces implemented by beans
and registers reachability metadata accordingly:

* JDK proxies for the beans themselves
* invocation reflection for annotated methods
* binding reflection for arguments and return types

This allows to compile such clients to Native Images.

Closes gh-29877
2023-02-01 18:22:33 +01:00
Juergen Hoeller 06fd6ecf1f Upgrade to Groovy 4.0.8, Tomcat 10.1.5, Netty 4.1.87, Undertow 2.3.3, Jackson 2.14.2, Woodstox 6.5, Mockito 5.1.1, AssertJ 3.24.2, HtmlUnit 2.70, Checkstyle 10.7 2023-02-01 18:18:52 +01:00
Juergen Hoeller b8827d8e11 Clarify postProcessBeanFactory lifecycle state
Closes gh-29064
2023-02-01 18:18:37 +01:00
Sam Brannen 23a60aeb27 Sync MockHttpServletRequest implementations 2023-02-01 16:28:38 +01:00
Arjen Poutsma 58fbf60d2d Include quoted printable filename in ContentDisposition::toString
This commit ensures the ContentDisposition class prints the filename in
both in the regular filename parameter and the extended filename*
parameter (RFC 5987).
Quoted printable (RFC 2047) is used to encode any non-ASCII characters
in the regular filename parameter.

Closes gh-29861
2023-02-01 13:40:03 +01:00
Sébastien Deleuze ebca9f726f Provide Kotlin extensions for RuntimeHints
To be able to register hints using for example registerType<MyClass>()
instead of registerType(MyClass::class.java).

Closes gh-29831
2023-02-01 12:04:18 +01:00
Brian Clozel 5fd73f0bae Fix MockHttpServletRequest InputStream for empty body
Prior to this commit, a recent change applied in gh-29125 changed the
behavior of `MockHttpServletRequest` instances. In case of an empty
request body, the returned `InputStream` would be static and could not
be reused across requests.
This could result in `java.io.IOException: Stream closed` exceptions if
a previous request was read.

This commit ensures that a new instance of an empty stream is returned
for each request instance.

Fixes gh-29901
2023-01-31 19:28:15 +01:00
Juergen Hoeller 16937c7ce5 Polishing 2023-01-31 18:15:28 +01:00
Juergen Hoeller c0c9ba5c2c Polishing 2023-01-31 16:14:32 +01:00
Juergen Hoeller 4d6249811e Explicit target ClassLoader for interface-based infrastructure proxies
Includes direct JDK Proxy usage instead of ProxyFactory where possible.

Closes gh-29913
2023-01-31 16:11:34 +01:00
Juergen Hoeller 3a08d643ed Upgrade to ASM master (including early support for Java 21 bytecode)
Closes gh-29910
2023-01-31 16:06:33 +01:00
Juergen Hoeller a74b86e812 Lazily load ContextLoader.properties (and lazily fail if not present)
Closes gh-29905
2023-01-31 16:05:07 +01:00
Juergen Hoeller 7c9dca3d2e Declare no-op close() method in order to avoid container-triggered shutdown call
Closes gh-29892
2023-01-31 16:03:26 +01:00
Brian Clozel 64219783f6 Start building with Reactor 2022.0.3-SNAPSHOT
See gh-29900
2023-01-31 15:37:04 +01:00
Brian Clozel 846a54aef4 Start building with Micrometer 1.10.4-SNAPSHOT
See gh-29899
2023-01-31 15:36:24 +01:00
Chen Jianbin 9e735d4f0f Normalize and optimize internals of CGLIB ParallelSorter
Closes gh-29516
2023-01-31 12:20:45 +01:00
Arjen Poutsma 0ddb394fd0 Register callback for HttpComponentsClientHttpConnector
This commit ensures that we register a result callback when executing
the request (next to the existing response callback), which gets
notified of invalid hosts and other connection issues.

Closes gh-29156
2023-01-31 12:16:43 +01:00
Sam Brannen f5a39308a0 Polishing 2023-01-31 11:54:21 +01:00
Johnny Lim e4ceb80678 Use EnumMap for DateFormatter.ISO_PATTERNS again
This commit changes to use `EnumMap` for `DateFormatter.ISO_PATTERNS`
again by partially reverting commit ba136dcf40.

See gh-29321
Closes gh-29485
2023-01-31 11:52:25 +01:00
Sam Brannen 64b89429cb Update copyright headers 2023-01-31 11:52:25 +01:00
Arjen Poutsma 8e843c242a Merge pull request #29853 from ThomHurks:cors-configuration-small-memory-optimization
* gh-29853:
  Polish external contribution
  Optimize CorsConfiguration::checkHeaders
2023-01-31 10:30:46 +01:00
Arjen Poutsma 635f010de3 Polish external contribution 2023-01-31 10:28:42 +01:00
Thom Hurks aac1ed6ee5 Optimize CorsConfiguration::checkHeaders
In the checkHeaders method, if allowedHeaders contains * the result
size can be requestHeaders.size(), but if this is not the case
then the result size can only be as big as the minimum value
of requestHeaders.size() and allowedHeaders.size().
requestHeaders.size() can be potentially big (user input) and
allowedHeaders.size() could be small, so this saves memory in
that case.

Closes gh-29853
2023-01-31 10:28:42 +01:00
Sam Brannen d5b0782700 Polishing 2023-01-31 10:10:44 +01:00
Sam Brannen ebe717ff6c Update release version due to backport
See gh-29790
See gh-29902
2023-01-31 10:00:18 +01:00
Sébastien Deleuze 89c7c6e9dd Fix bean validation on suspending function parameters
This commit leverages Hibernate Validator's own internal use
of standard Java reflection to perform validation on suspending
function, which fixes the ArrayIndexOutOfBoundsException previously
observed.

Validation of suspending function return values remains unsupported
as Hibernate Validator is not Coroutines aware.

Closes gh-23499
2023-01-31 09:41:47 +01:00
rstoyanchev 9c6fd3ed06 Consistently list supported media types
Add constructors to HttpMediaTypeNotSupportedException and
UnsupportedMediaTypeStatusException for a parse error that also accept
the list of supported media types to include in the response headers.

Closes gh-28062
2023-01-30 17:46:08 +00:00
rstoyanchev e564a0de46 Provide access to interceptors in AbstractHandlerMapping
Closes gh-28985
2023-01-30 17:46:08 +00:00
rstoyanchev 17f1eadb6f Polishing contribution
Closes gh-29610
2023-01-30 17:46:08 +00:00
divcon 09991f2492 Polishing in ResponseEntityResultHandler
See gh-files
2023-01-30 17:46:08 +00:00
rstoyanchev 15931532cd Polishing contribution
Closes gh-29868
2023-01-30 17:46:08 +00:00
Eden Tyler-Moss aa9f445422 Add @Nullable to ProblemDetail.setProperty argument
See gh-29868
2023-01-30 17:46:08 +00:00
rstoyanchev b578ff1296 Polishing contribution
Closes gh-29696
2023-01-30 17:46:08 +00:00
Kevin Yue cf9fc69d6b Don't swallow exception when logging response status
See gh-29696
2023-01-30 17:46:08 +00:00
Sam Brannen 04321d0577 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-29790
2023-01-30 17:42:00 +01:00
Sam Brannen 67c141f15b Polishing 2023-01-30 15:33:47 +01:00
fml2 ad4e0d9ad7 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-29790
2023-01-30 15:19:45 +01:00
Arjen Poutsma c13dfc5144 Merge pull request #29889 from xavier-b:main
* gh-29889:
  Use DataBuffer::toString instead of CharBuffer
2023-01-30 15:03:04 +01:00
xavier-b b7d53ac9a4 Use DataBuffer::toString instead of CharBuffer
This commit ensures that converting DataBuffers to a String does not
use an expensive ByteBuffer allocation.

Closes gh-29889
2023-01-30 14:58:48 +01:00
Arjen Poutsma f9884e08af Polish external contribution 2023-01-30 14:19:41 +01:00
Vatsa 9819cb3eb5 Update HandlerFunctionAdapter::setAsyncRequestTimeout Javadoc
Closes gh-29882
2023-01-30 14:19:41 +01:00
Sam Brannen 9b0929c392 Update copyright headers 2023-01-30 13:00:22 +01:00
Arjen Poutsma af21ebe6c6 Fix CronExpression::parse javadoc
Closes gh-29884
2023-01-30 11:49:34 +01:00
Johnny Lim 0b446a94c5 Add Javadoc since for CLIENT_NAME enums
See gh-29839
Closes gh-29893
2023-01-30 10:10:31 +01:00
Brian Clozel 5dfa61eb0b Restrict "uri" KeyValue for client observations
Prior to this commit, the "uri" KeyValue for low cardinality metadata
would contain the entire uri template given to the HTTP client when
creating the request. This was a breaking change for existing metrics
dashboards, as previous support was removing the protocol, host and port
parts of the URI.
Indeed, this information is available in the "client.name" and
"http.uri" KayValue.

This commit parses and removes the protocol+host+port information from
the uri template for the "uri" KeyValue.

Fixes gh-29885
2023-01-30 10:09:45 +01:00
Brian Clozel b267547fb4 Contribute "uri" KeyValue for "/" client requests
Prior to this commit, client HTTP requests performed by `WebClient`
could miss the "uri" KeyValue for simple "/" requests.
This can happen when the baseUri is configured for the client with a
host and a root base path like "https://example.org/"; given the nature
of the `WebClient` API, in these cases, one can perform requests like
this:

```
WebClient client = WebClient.builder()
    .observationRegistry(registry)
    .baseUrl("https://example.org/")
    .build();

String response = client.get().retrieve().bodyToMono(String.class).block();
```

Such a call would contribute a `"none"` value for the `"uri"` KeyValue.

While only templates should be allowed for this keyvalue, we can assume
that requests to `"/"` should be recorded anyway and won't cause
cardinality explosion.

Fixes gh-29879
2023-01-30 10:09:41 +01:00
Sam Brannen e0f60dc09d Apply "instanceof pattern matching" in spring-context and polishing
See gh-29222
2023-01-29 14:21:15 +01:00
Adam Ostrožlík 8783075e40 Apply "instanceof pattern matching" and minor refactorings in spring-context
Closes gh-29222
2023-01-29 13:52:43 +01:00
Adam Ostrožlík f2cdced501 Apply minor polishing in spring-aop
Closes gh-28984
2023-01-29 13:32:33 +01:00
Sam Brannen 33a0e65135 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-29894
2023-01-29 12:35:13 +01:00
Sam Brannen e3fb0a39a2 Clean up compiler warnings 2023-01-28 21:18:19 +01:00
Sam Brannen 57fb072215 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-29886
2023-01-28 20:42:21 +01:00
Sam Brannen 75046bbea0 Update copyright headers 2023-01-28 20:42:21 +01:00
Sam Brannen 8e2eeb5364 Apply "instanceof pattern matching" in spring-beans 2023-01-27 17:54:03 +01:00
Sam Brannen 556863d401 Polishing 2023-01-27 17:54:03 +01:00
rstoyanchev 6a6a35a0b9 Support method validation for interface-only proxies
Closes gh-29782
2023-01-27 14:46:22 +00:00
Brian Clozel 7da6e93597 Set WebClient Observation as current in reactor context
Prior to this commit, the `DefaultWebClient` would be instrumented for
client observations and would start/stop a `"http.client.requests"`
observation. This would not set this new observation as the current one
in the Reactor context under `ObservationThreadLocalAccessor.KEY`.
This means that potential child observations would not detect it as
their parent; this can happen if the Reactor Netty `HttpClient`
observation is enabled.

This commit ensures that the reactor context is properly populated for
upstream operators.

Fixes gh-29891
2023-01-27 14:42:08 +01:00
Brian Clozel 963274a915 Polish 2023-01-27 09:52:24 +01:00
Simon Baslé d72df5ace4 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.

Closes gh-29367
2023-01-26 14:35:31 +01:00
Brian Clozel 767f59a3ae Make client.name low cardinality keyvalue for client observations
Prior to this commit, the `"client.name"` key value for the
`"http.client.requests"` client HTTP observations would be considered as
high cardinality, as the URI host is technically unbounded.
In practice, the number of hosts used by a client in a given application
can be considered as low cardinality. This commit moves this keyvalue to
low cardinality so that it's present for both metrics and traces.

Closes gh-29839
2023-01-25 20:51:15 +01:00
Sam Brannen da088e58c3 Increase number of TOC levels to 4 in generated PDF documentation
Closes gh-29781
2023-01-24 15:31:14 +01:00
Arjen Poutsma 5502e61519 Support Optional in AbstractJackson2HttpMessageConverter
This commit introduces support for Optional in the
AbstractJackson2HttpMessageConverter, similar the existing support for
collection types were supported.

Closes gh-24498
2023-01-24 13:08:21 +01:00
Sébastien Deleuze ab9bea1d93 Polish RouterFunctionDsl KDoc 2023-01-23 13:28:10 +01:00
Sébastien Deleuze e6397c8a38 Infer reflection hints for Jackson annotation class attributes
Closes gh-29646
Closes gh-29386
2023-01-23 13:21:34 +01:00
Sébastien Deleuze 1e47f31210 Support code generation for Set with non-comparable elements
Closes gh-29792
2023-01-23 10:55:34 +01:00
Sébastien Deleuze 57b6f7e494 Infer hints for custom constraint validators
This commit introduces a BeanValidationBeanRegistrationAotProcessor
which adds reflection hints for custom ConstraintValidator discovered
on beans constructors, methods and properties.

Closes gh-29823
2023-01-23 10:15:58 +01:00
Brian Clozel d37ef61b30 Resolve static resources without wildcard pattern
Prior to this commit, the reactive `ResourceWebHandler` would only look
at the path within the current mapping when resolving static resources
to be served. This means that when registering a handler at
`"/resources/**"` with a `"classpath:/static/"` location, the handler
would process a `"GET /resources/file.txt"` as the `"/static/file.txt"`
classpath location.

When a developer registers a fixed pattern like `"/resources/file.txt"`
with the same location, the path within the handler mapping is empty as
there is no dynamic part in the given pattern. While the typical use
case for this feature is to register multiple resources at once with a
pattern, we should support a single registration like this.

This commit ensures that if the matching `PathPattern` for the current
request does not have a pattern syntax (i.e. no regexp, no wildcard), we
can use it to match the resource directly. Otherwise, we can use the
path within the handler mapping to resolve the resource as before.

Closes gh-29739
2023-01-20 17:15:52 +01:00
Sam Brannen 3f148c2aaa Avoid warnings / Polishing 2023-01-20 15:22:47 +01:00
Sam Brannen fa1ef1dc85 Deprecate obsolete ConcurrentExecutorAdapter for removal in 6.1
Closes gh-29865
2023-01-20 14:20:18 +01:00
Sam Brannen 58872c79ee Update copyright headers 2023-01-20 14:17:53 +01:00
Sam Brannen 24f18275dd Stop referring to "Spring 3.x" features in documentation and code 2023-01-20 14:13:18 +01:00
Sébastien Deleuze 8f94c4e933 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-28902
2023-01-20 13:59:39 +01:00
Arjen Poutsma 20c79e1481 Support double-quoted in HttpHeaders::getValuesAsList
This commit introduces support for double-quoted HTTP header values in
HttpHeaders::getValuesAsList, as described in RFC 9110 section 5.5.

Closes gh-29785
2023-01-20 13:42:51 +01:00
Sébastien Deleuze fb0aa5abb3 Fix WebClientIntegrationTests flaky Jetty tests
Ensure the port used by the client in malformedResponseChunksOnBodilessEntity
and malformedResponseChunksOnEntityWithBody has correctly been set.

Closes gh-29862
2023-01-20 11:38:22 +01:00
Sam Brannen 86a40716bd Polishing 2023-01-20 10:28:25 +01:00
Sam Brannen 7f48d1b55a Remove obsolete Tiles documentation from Javadoc
See gh-29852
2023-01-20 10:27:48 +01:00
Sébastien Deleuze fd84b0997a 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-29859
2023-01-20 10:17:17 +01:00
Juergen Hoeller 0e8838db90 Flexible constructor resolution in AutowireCapableBeanFactory.createBean(Class)
Closes gh-29855
See gh-29823
2023-01-19 17:10:42 +01:00
Sébastien Deleuze 94fc24b6fb Document that bean instance suppliers are not supported with AOT/native
Closes gh-29835
2023-01-19 16:45:52 +01:00
Sébastien Deleuze ab0d1c395d Fail explicitly in AOT transformations of instance supplier
It is by design not possible to generate code that handles
bean definitions with user-provided instance suppliers because
the JVM does not allow to get a stable reference reusable at
runtime on the lambda or method reference in the code generated
AOT.

Before this commit, such instance supplier was ignored.
After this commit, an IllegalArgumentException is thrown,
allowing projects to be aware this is not supported and enforce
related refactorings.

The related issue gh-29555 describes how this limitation could
be relaxed in the future.

Closes gh-29556
2023-01-19 16:45:52 +01:00
Sam Brannen 047f660572 Remove obsolete Tiles documentation from reference manual
Tiles support was officially removed in conjunction with gh-27423.

Closes gh-29852
2023-01-19 16:43:51 +01:00
Sam Brannen 22323072fd Polishing 2023-01-19 16:32:29 +01:00
Thom Hurks a34b1af49e Remove extra empty line in DefaultCorsProcessor (#29854) 2023-01-19 16:28:18 +01:00
Sam Brannen 1ace42f245 Enable JRubyScriptTemplateTests 2023-01-19 16:20:03 +01:00
Sam Brannen 0502d18e3d Update copyright headers 2023-01-19 16:20:03 +01:00
Sam Brannen c4c786596f Migrate to Mockito.mock(T...) where feasible 2023-01-19 16:20:02 +01:00
Sam Brannen c3d123fef7 Allow @Aspect classes to extend concrete @Aspect classes
Closes gh-29830
2023-01-19 14:35:27 +01:00
Sam Brannen e4b25ab480 Polishing 2023-01-19 14:35:27 +01:00
Arjen Poutsma 1680502313 Updated Java 17 version in sdkmanrc 2023-01-19 10:03:18 +01:00
Brian Clozel e725e3a51b Update Java versions and remove Java 18 build 2023-01-19 09:40:25 +01:00
Johnny Lim 2fe75c1a24 Polish HttpStatus 103 EARLY_HINTS javadocs (#29841)
This commit polishes the EARLY_HINTS javadocs a bit:
 - fix a typo
 - fix `since` tags to include the patch version

See gh-29816
2023-01-18 14:50:02 +01:00
Arjen Poutsma 9ebd1e8d64 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.

Closes gh-29794
2023-01-18 10:38:09 +01:00
Sam Brannen 64de6de725 Update copyright headers 2023-01-17 15:49:26 +01:00
Sam Brannen c3e8ff9ce7 Do not use Mockito to mock ReactiveAdapterRegistry 2023-01-17 15:44:57 +01:00
Brian Clozel 5448e81021 Deprecate Base64Utils in favor of Java's Base64
Originally, `Base64Utils` was providing base64 encoding and decoding
utilities, bridging to commons-codecs or Java 8, if available. Since
then, only the Java 8 variant remains and Spring Framework 6 requires
now Java 17. This utility class doesn't provide additional checks or
syntactic sugar over what's in Java already.

As a result, this commit deprecates this class in favor of `Base64` and
schedules the removal of this class completely.

Closes gh-28434
2023-01-17 15:30:45 +01:00
j3graham f7e07322ab Simplify Base64Utils by using java.util.Base64
This commit simplifies the `Base64Utils` implementation by relying more
on the `Base64` methods that perform similar work.

See gh-28434
2023-01-17 15:29:58 +01:00
정준영 37217a63e1 Remove unnecessary calls to Reference::clear
Prior to this commit, `ConcurrentReferenceHashMap` subclasses extending
`Reference` would call `Reference::clear` right next to
`Reference::enqueue`; this is not needed as the latter calls it already.

Closes gh-28863
2023-01-17 14:44:39 +01:00
Sam Brannen ad5c636aff Upgrade to Mockito 5.0 2023-01-17 14:31:11 +01:00
Brian Clozel ebdc82b86b Add serialization hint for ProblemDetail
Prior to this commit, a Spring web application would not be able to
serialize a `ProblemDetail` object instance in a Native Image, as
serialization hints would be missing.

This commit adds a RuntimeHints registrar that processes the
`ProblemDetail` type accordingly during the AOT phase.

Fixes gh-29801
2023-01-17 10:59:52 +01:00
Sam Brannen a12c9a0430 Update copyright headers 2023-01-16 19:24:30 +01:00
Sam Brannen 0d14c3bc1a Polish Javadoc in spring-jms 2023-01-16 19:24:30 +01:00
Sam Brannen 8be542016b Apply "instanceof pattern matching" in spring-jms 2023-01-16 19:24:30 +01:00
Arjen Poutsma 3a585f8c29 Introduce CoWebFilter
This commit introduces the CoWebFilter, an abstract WebFilter
implementation that allows for coroutine usage.

Closes gh-29672
2023-01-16 15:45:08 +01:00
Minsoo Cheong(Merlin) c0e38a2f1e 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.
2023-01-16 11:29:43 +01:00
Simon Baslé 5de1460f88 Deprecate HttpStatus 103 CHECKPOINT in favor of new EARLY_HINTS (#29816)
This commit takes rfc8297 into account and introduces a newer code 103
HttpStatus value which uses `Early Hints` as the more correct reason
phrase, deprecating the outdated `CHECKPOINT` enum value for 103.

Additionally:
  - `HttpStatus.valueOf(103)` will return the new enum value
  - `HttpStatusCode#isSameCodeAs(HttpStatusCode)` is introduced to ease
  comparison of deprecated enums vs their newer counterparts (or any
  instance of a more generic `HttpStatusCode`) by comparing the integer
  `value()`
  - `HttpStatusTests` covers the new deprecation as well as the three
  previously deprecated codes, including a check with the above new
  method to ensure they have comparable integer values

Supersedes and Closes gh-27960
2023-01-16 11:22:43 +01:00
rstoyanchev 312db36849 Combined, empty RequestMapping matches both "" and "/"
Closes gh-29625
2023-01-13 14:58:11 +00:00
Sam Brannen 46875c91ce Update copyright year in reference manual 2023-01-11 17:32:31 +01:00
Sam Brannen 86305c45a9 Upgrade to spring-asciidoctor-backends 0.0.4 2023-01-11 17:30:02 +01:00
Sam Brannen 1342837686 Upgrade to nohttp 0.0.11 2023-01-11 17:26:35 +01:00
Sam Brannen 012b8f18c6 Add Simon to mailmap 2023-01-11 15:26:31 +01:00
Brian Clozel 5ea310452c Add Simon to the Changelog generator configuration
This prevents Simon from being listed as an external contributor.
2023-01-11 14:12:03 +01:00
Sam Brannen a4956dfe26 Update copyright headers 2023-01-11 13:52:20 +01:00
Sam Brannen 0415975dd1 Polish contribution and related code 2023-01-11 13:52:20 +01:00
Krzysztof Krason afb8a0d1b1 Use new Java features (switch expressions, text blocks, new JDK methods)
Closes gh-29747
2023-01-11 13:51:28 +01:00
Spring Builds 48abd493fe Next development version (v6.0.5-SNAPSHOT) 2023-01-11 12:25:34 +00:00
Brian Clozel 3d571e8ab5 Upgrade to Micrometer 1.10.3
Closes gh-29802
2023-01-11 11:55:43 +01:00
Juergen Hoeller c7cfdfc26c Downgrade to Mockito 4.9 for spring-beans tests
Includes upgrade to HtmlUnit 2.69
2023-01-11 00:26:30 +01:00
Juergen Hoeller 4d27aee7cf Upgrade to Checkstyle 10.6 2023-01-11 00:03:23 +01:00
Juergen Hoeller 63f0beb209 Upgrade to Reactor 2022.0.2
Includes Mockito 4.11 and AssertJ 3.24.1

Closes gh-29797
2023-01-11 00:01:34 +01:00
Sam Brannen 8dbdfb0449 Polishing 2023-01-10 16:08:02 +01:00
Sam Brannen d5fb5d029b Polish contribution 2023-01-10 16:07:48 +01:00
Vasiliy Kudriavtsev 3738a45658 Avoid wasted memory on empty maps and sets
This commit avoids wasted memory on empty hash maps in
MergedAnnotationReadingVisitor and empty sets in InjectionMetadata.

Closes gh-29742
2023-01-10 15:52:17 +01:00
Sam Brannen fd3e99c7ee Upgrade to JUnit 5.9.2 2023-01-10 15:23:20 +01:00
Sébastien Deleuze 4396801933 Add reflection hints for Kotlin reflection on functions
Kotlin reflection API invocation on a specific function
may require iterating on all Java methods to find the right
Kotlin function. As a consequence, this commit adds introspection
hints on the class declared methods for all Kotlin beans since
the impact on the footprint is low.

Closes gh-29663
2023-01-10 14:49:26 +01:00
Brian Clozel a516ed8739 Upgrade Gradle Enterprise & Conventions plugins 2023-01-10 09:10:59 +01:00
Juergen Hoeller 88cac6a4a3 Reduce creation of composite interfaces to actual method references in current pointcut
Closes gh-29519
2023-01-09 20:34:20 +01:00
Sam Brannen 11df955d88 Update copyright headers 2023-01-09 18:33:06 +01:00
Sam Brannen 77832a6da9 Apply "instanceof pattern matching" in HttpHeaders 2023-01-09 18:27:13 +01:00
Sam Brannen ce1f6cf0bf Polishing 2023-01-09 18:27:13 +01:00
rstoyanchev c702cd418e Polishing
See gh-29721
2023-01-06 16:50:19 +00:00
Simon Baslé 4bcc24372a Add ExecutingResponseCreator
This commit adds a new `ResponseCreator` implementation that uses a
`ClientHttpRequestFactory` to perform an actual request.

Closes gh-29721
2022-12-20 16:36:06 +01:00
rstoyanchev ae7cff35dc Polishing 2022-12-20 09:39:15 +00:00
IDJack 8282be682c Fix typo in core-aot.adoc
Closes gh-29788
2023-01-09 13:19:16 +01:00
Sébastien Deleuze b81a291c85 Add reflection hints for @RequestPart
Closes gh-29749
2023-01-06 17:26:33 +01:00
Sébastien Deleuze 3348e74ab8 Add native support for @Convert on JPA entities
This commit infers the reflection hints required for converters
when they are specified with the @Convert annotation at class or
field level.

It also refines the hints generated for @Converter in order
to just generate the construct hint, not the public method one
which should be not needed.

Closes gh-29771
2023-01-06 12:56:26 +01:00
Simon Baslé e2832ea596 Polish #29727: Mention Kotlin andExpectAll in reference manual (#29766)
This just adds a Kotlin snippet alongside the Java snippet in the
reference manual.

Relates to gh-29727
Closes gh-27317
2023-01-04 19:11:54 +01:00
Simon Baslé 74f58198fd Add Kotlin DSL support for MockMVC andExpectAll (#29727)
As the DSL internally calls `ResultActions.andExpect`, this is done with
a trick where a synthetic `ResultActions` is provided at top level which
stores each `ResultMatcher` in a mutable list.

Once the DSL usage is done, the top level DSL `andExpectAll` turns that
list into a `vararg` passed down to the actual `actions.andExpectAll`.

Closes gh-27317
2023-01-03 18:26:26 +01:00
Juergen Hoeller 42b16591ec SpringPersistenceUnitInfo leniently ignores transformer if no LoadTimeWeaver is present
Closes gh-29736
2023-01-03 11:55:33 +01:00
Johnny Lim 62cf2f0a4f Fix wrong asserted code in SQLExceptionSubclassTranslatorTests (#29748)
There was a typo in the test, covering the wrong SQLState code.

Polishes a644245.
Relates to gh-29699.
2023-01-03 10:57:02 +01:00
Juergen Hoeller 32e1a6452a Upgrade to Undertow 2.3.2, Apache HttpClient 5.2.1, Selenium HtmlUnit Driver 2.67 2022-12-23 16:11:16 +01:00
Juergen Hoeller 55295faff0 Upgrade to Tomcat 10.1.4, Jetty 11.0.13, Netty 4.1.86, Protobuf 3.21.12, SLF4J 2.0.6 2022-12-23 15:14:52 +01:00
Juergen Hoeller 254c3725e2 Polishing 2022-12-23 15:14:11 +01:00
Juergen Hoeller d5ff232246 Defensive check for null returned from createConnection()
Closes gh-29706
2022-12-23 15:13:41 +01:00
Juergen Hoeller a644245e0e Check well-known database error codes in case of generic SQL state 23000
Closes gh-29699
2022-12-23 15:13:29 +01:00
Sam Brannen 697292ba0c Apply update_copyright_headers.sh 2022-12-20 15:21:54 +01:00
Brian Clozel 5366ac84e6 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.

Fixes gh-29712
2022-12-19 10:15:39 +01:00
Sam Brannen b71db12c43 Apply "instanceof pattern matching" in spring-aop 2022-12-18 14:14:40 +01:00
Sam Brannen ab571e3562 Revert incorrect change to ParamAware Javadoc 2022-12-18 14:14:40 +01:00
Sam Brannen 5e42a6eb0a Update Trigger & TriggerContext reference documentation
Closes gh-29702
2022-12-18 13:21:27 +01:00
Sam Brannen 0bfddbc9cb Polishing 2022-12-18 13:20:46 +01:00
diguage 511dab1ade Apply "instanceof pattern matching" (#29710) 2022-12-18 12:46:15 +01:00
Sam Brannen d4623a393b Update copyright headers 2022-12-18 12:16:19 +01:00
Sam Brannen c2c3be4ee3 Polishing 2022-12-18 12:05:24 +01:00
Sam Brannen 270f8526d1 Fix typos in anchors 2022-12-18 12:05:24 +01:00
Sam Brannen 4171e35546 Fix formatting in examples 2022-12-18 12:05:18 +01:00
Sam Brannen bea505d32e Fix typos in reference manual 2022-12-18 12:05:18 +01:00
Sam Brannen 5c28b56823 Remove duplicated words in Javadoc 2022-12-18 12:05:18 +01:00
Sam Brannen d2b54e2611 Remove duplicate words in reference manual
Found using regular expression: \b(\w+)\s+\1\b
2022-12-18 10:46:30 +01:00
Sam Brannen f8a58f2bc4 Update Jakarta Mail info in ref docs
Closes gh-29707
2022-12-17 14:24:38 +01:00
Sam Brannen f6e1fb3150 Cross reference WebTestClient section 2022-12-17 14:01:21 +01:00
Simon Baslé 14c7b9bd08 Change plain 'WebMVC' links to 'See equivalent in the Servlet stack'
Closes gh-29694
2022-12-17 13:51:29 +01:00
Sam Brannen 11f3edc352 Change plain 'WebFlux' links to 'See equivalent in the Reactive stack'
Closes gh-29694
2022-12-17 13:51:29 +01:00
Simon Baslé fbd4463f20 Fix subsection style in WebFlux Concurrency Model
The block title style previously used was not rendered in HTML and the
title couldn't be differentiated from the text. Though, it was in the
PDF, as italics.

Introducing delimited blocks in the open (`--`) style did introduce
styling, but the vertical alignment isn't great.

This commit turns these block titles to actual (deep) section titles.
In the final HTML, at this depth there is no numbering but bold styling
is there. The PDF rendering has also been verified to have relevant
style.

Closes gh-29694
2022-12-17 13:43:08 +01:00
Simon Baslé a3a94950f6 Rework linking to Spring MVC Async support vs WebFlux section
The link was previously named "Compared to WebFlux", which is easy to
mix up with the various links to equivalent sections in the WebFlux
chapter. Here the links point to a small section comparing the Servlet
Async API to the WebFlux stack from a high perspective.

In this commit we eliminate most of these links, except at the
beginning of the Asynchronous section. We also add a small mention of
the Servlet configuration in the comparison paragraphs, since the
Configuring section is the one furthest from the comparison paragraphs
that used to have a link to it.

Closes gh-29694
2022-12-17 13:43:04 +01:00
Simon Baslé b51a14ff92 Remove statement that users could be on Java < 5
Closes gh-29694
2022-12-17 13:42:59 +01:00
Simon Baslé 929d5567b8 Remove ref to JOTM, inactive since 2009
Closes gh-29694
2022-12-17 13:42:55 +01:00
Simon Baslé beaa7ba0e3 Fix link to Jakarta Mail
Closes gh-29694
2022-12-17 13:42:50 +01:00
Simon Baslé 1a839f5103 Fix typos in reference manual
Closes gh-29694
2022-12-17 13:42:46 +01:00
Sam Brannen 8df4f927fd Polish contribution
See gh-29697
2022-12-17 11:10:44 +01:00
Simon Baslé 5965917d16 Extract ResourceEntityResolver HTTPS schema resolution fallback
This commit extracts the DTD/XSD remote lookup fallback from the
resolveEntity() method into a protected method.

A WARN-level logging statement is added to the extracted fallback in
order to make it clear that remote lookup happened.

Overriding the protected method would allow users to avoid this
fallback entirely if it isn't desirable, without the need to duplicate
the local resolution code.

Closes gh-29697
2022-12-17 10:34:15 +01:00
Sam Brannen 57cfb94f1f Improve documentation for literals in SpEL expressions
Closes gh-29700
2022-12-16 14:50:07 +01:00
Sam Brannen b5b80d0a07 Polishing 2022-12-16 14:50:02 +01:00
Sam Brannen e5cfbae3fd Polishing 2022-12-16 13:48:45 +01:00
Carlos Belizón 5d2ca11315 Fix manipulating property sources example in Javadoc for ConfigurableEnvironment
The "manipulating property sources" example in the Javadoc for
`ConfigurableEnvironment` states that `MutablePropertySources`
expect a `Map<String,String>`; whereas it expects a
`Map<String,Object>`.

Closes gh-29693
2022-12-16 13:47:40 +01:00
Spring Builds 858394b720 Next development version (v6.0.4-SNAPSHOT) 2022-12-15 09:12:22 +00:00
Sam Brannen 6e08c56076 Improve Javadoc for RepeatableContainers 2022-12-14 13:40:43 +01:00
Sam Brannen fb6d3f5b5c Remove duplicated test code 2022-12-14 13:26:51 +01:00
Arjen Poutsma 6fe5652783 Support non-standard HTTP methods in FrameworkServlet
This commit ensures that HTTP methods not supported by HttpServlet, for
instance WebDAV methods, are still supported in FrameworkServlet.

Closes gh-29689
2022-12-14 12:54:41 +01:00
Brian Clozel ca68bbc9ff Upgrade to Reactor 2022.0.1
Closes gh-29679
2022-12-13 22:52:24 +01:00
Sam Brannen e7bcb48e57 Remove obsolete AttributeMethods.hasOnlyValueAttribute() method
See gh-29685
2022-12-13 16:01:05 +01:00
Sam Brannen 433b1c480c 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.

Closes gh-29685
2022-12-13 16:00:55 +01:00
Sam Brannen 0b08246760 Revise RepeatableContainersTests 2022-12-13 15:54:43 +01:00
Sam Brannen c7bdfbea4f Add missing Javadoc
See gh-29574
2022-12-13 13:46:31 +01:00
Sam Brannen 618989d317 Update copyright date 2022-12-13 13:44:18 +01:00
Sam Brannen 7fe78b745f Polish Javadoc 2022-12-13 13:44:03 +01:00
Juergen Hoeller 98f152e8d5 Polishing 2022-12-13 11:07:46 +01:00
Juergen Hoeller d74191427e Avoid NPE on BeanDescriptor access with SimpleBeanInfoFactory
Closes gh-29681
2022-12-13 11:07:22 +01:00
Juergen Hoeller 4c69892f39 Detect SQL state 23505/40001 as DuplicateKeyException/CannotAcquireLockException
Favors PessimisticLockingFailureException over plain ConcurrencyFailureException.
Deprecates CannotSerializeTransactionException and DeadlockLoserDataAccessException.

Closes gh-29511
Closes gh-29675
2022-12-13 11:07:13 +01:00
Arjen Poutsma c79ae0c842 Align multipart codecs on client and server
This commit ensures that the same multipart codecs are registered on
both client and server. Previously, only the client enabled only sending
 multipart, and the server only receiving.

Closes gh-29630
2022-12-13 10:13:46 +01:00
Sam Brannen 46fc28fd1a Clean up Javadoc and source code regarding " ." typos 2022-12-12 16:31:14 +01:00
Johnny Lim f8a1dac593 Use consistent visibility for ResponseEntityExceptionHandler.getMessageSource()
See gh-29574
Closes gh-29676
2022-12-12 16:15:52 +01:00
Brian Clozel 9712bb62fd Upgrade optional dependencies 2022-12-12 14:58:21 +01:00
Brian Clozel e85f6342a2 Start building against Reactor 2022.0.1
See gh-29679
2022-12-12 14:58:21 +01:00
Brian Clozel 7199782d45 Upgrade to Micrometer 1.10.2
Closes gh-29678
2022-12-12 14:58:13 +01:00
Sébastien Deleuze 5ed4a14e2b Make @ModelAttribute and @InitBinder reflective
Closes gh-29572
2022-12-11 12:02:55 +01:00
Sébastien Deleuze b27735d4a6 Refine BindingReflectionHintsRegistrar Kotlin support
Closes gh-29593
2022-12-11 12:02:55 +01:00
Sébastien Deleuze dc5a773b2b Support properties on records in BindingReflectionHintsRegistrar
Closes gh-29571
2022-12-10 16:12:23 +01:00
Sam Brannen 2b6f3caff4 Remove dead code in MockClientHttpRequest 2022-12-09 15:57:35 -05:00
Sam Brannen 83eb8ac0ea Introduce additional constructors in MockClientHttp[Request|Response]
This commit introduces additional constructors in MockClientHttpRequest
and MockClientHttpResponse that were previously only present in the
internal "test fixtures" in spring-web.

This commit also aligns the mocks in spring-test with the test fixtures
in spring-web to simplify continued maintenance of the mocks and test
fixtures.

Closes gh-29670
2022-12-09 15:46:08 -05:00
Sam Brannen 9b38e43c17 Use URI#create instead of URI constructor where feasible in spring-websocket 2022-12-09 13:27:34 -05:00
Sam Brannen 284cb12f8f Use URI#create instead of URI constructor where feasible in spring-webmvc 2022-12-09 13:27:13 -05:00
Sam Brannen 67644a28b6 Use URI#create instead of URI constructor where feasible in spring-webflux 2022-12-09 13:26:30 -05:00
Sam Brannen 1b57f2bda5 Use URI#create instead of URI constructor where feasible in spring-web 2022-12-09 13:26:01 -05:00
Sam Brannen a1a140f7d5 Use URI#create instead of URI constructor where feasible in spring-test 2022-12-09 12:27:06 -05:00
Sam Brannen 4caf3c8ce0 Polish tests in spring-test 2022-12-09 12:26:38 -05:00
Sam Brannen 485c80fcf3 Apply 'instanceof pattern matching' in spring-test and Servlet mocks 2022-12-09 11:56:14 -05:00
rstoyanchev aae46263cc Restore top-level read permission for backport bot 2022-12-09 12:02:56 +00:00
rstoyanchev 39d4d2041a Polishing contribution
Closes gh-29634
2022-12-09 10:24:42 +00:00
koo.taejin 5ac97b16a8 Optimize object creation PartialMatchHelper
See gh-29634
2022-12-09 10:19:54 +00:00
rstoyanchev f457c17c78 Remove top-level permissions from backport-bot.yml 2022-12-09 09:10:03 +00:00
Sam Brannen b0b2bbc857 Polish CGLIB fork
- primarily automated "clean up" using Eclipse IDE
2022-12-09 00:56:38 -05:00
Sam Brannen 69f47e7700 Polishing
- primarily automated "clean up" using Eclipse IDE
2022-12-09 00:56:00 -05:00
Sam Brannen 52af5c2b38 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-29665
2022-12-08 18:17:45 -05:00
Sam Brannen 404661d5cb Polishing 2022-12-08 16:03:05 -05:00
Sam Brannen f07a4587bb Apply 'instanceof pattern matching' in spring-expression 2022-12-07 17:15:25 -05:00
Sam Brannen 114d6a9256 Apply 'instanceof pattern matching' in spring-jdbc 2022-12-07 17:15:25 -05:00
Sam Brannen 73a18046c3 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, gh-28356
2022-12-07 15:43:47 -05:00
Sam Brannen c899af0e03 Polishing 2022-12-07 15:43:47 -05:00
Sam Brannen 098c924e32 Introduce @Suite classes for individual modules 2022-12-07 12:12:41 -05:00
Sam Brannen 4289a64e24 Improve Javadoc for SqlLobValue 2022-12-07 12:12:41 -05:00
Sam Brannen 7615762039 Update copyright headers 2022-12-07 12:11:45 -05:00
Brian Clozel d601f3196a Fix BindingReflectionHintsRegistrar anonymous classes support
This commit ensures that giving an anonymous class for reflection hints
registration does not result in a NullPointerException, since the
canonical name of anonymous classes is null.

Fixes gh-29657
2022-12-07 16:37:01 +01:00
Arjen Poutsma 92a6e7ddcd Fix InputStream violation in DataBufferInputStream
This commit fixes an issue in DataBufferInputStream::mark, which before
did not follow the contract defined by InputStream.

Closes gh-29642
2022-12-07 15:23:19 +01:00
ShenFeng312 c79474d269 Polish var-args declarations
Closes gh-29640
2022-12-07 04:30:40 +01:00
Sam Brannen f4bc9ffb98 Reintroduce component index support for Jakarta annotations
Spring Framework 6.0 GA introduced a regression in the component index
support for Jakarta annotations such as @Named and @ManagedBean.

Prior to this commit, @Named and @ManagedBean components were
registered in the component index at build time; however, component
scanning failed to find those component at run time.

This commit updates ClassPathScanningCandidateComponentProvider so that
`jakarta.*` annotation types are once again supported for component
scanning via the component index at run time.

Closes gh-29641
2022-12-06 16:23:31 -05:00
Sam Brannen e124e802a3 Polishing 2022-12-06 16:23:31 -05:00
Sam Brannen 348cc01284 Rename MultipartWebClientIntegrationTests classes to avoid duplicate names 2022-12-06 12:50:36 -05:00
Sam Brannen 9f7a510f90 Polishing 2022-12-06 12:29:03 -05:00
divcon f64397d822 Apply "instanceof pattern matching" in spring-webflux
Closes gh-29635
2022-12-06 10:03:26 -05:00
rstoyanchev 918edaba2e Add convenience methods for binding error messages
Closes gh-29574
2022-12-06 13:37:08 +00:00
rstoyanchev 5214bd3093 Fix issue with getHeaders in NoHandlerFoundException
Closes gh-29626
2022-12-06 13:37:08 +00:00
Moritz Halbritter 752ef6f456 Fall back to JdkClientHttpConnector as ClientHttpConnector 2022-12-06 14:33:03 +01:00
rstoyanchev bea1980e22 Correct (again) permissions key in backport bot config 2022-12-06 09:41:05 +00:00
rstoyanchev f3360e4ee2 Correct permissions key in backport bot config 2022-12-06 09:38:13 +00:00
rstoyanchev 8330bd424b Add write permission in backport bot config 2022-12-06 09:34:07 +00:00
rstoyanchev 507c9697fb Correct event name in backport bot config 2022-12-06 09:27:03 +00:00
rstoyanchev 52c073724d Enable backport bot for pull requests 2022-12-06 09:13:29 +00:00
Sam Brannen de07ad47f1 Polishing, suppression of deprecation warnings, copyright headers, etc. 2022-12-05 14:16:22 -05:00
rstoyanchev 93ea2e1df9 Push canWrite down into MultipartHttpMessageWriter
The implementation in the base class only matches the
MultipartHttpMessageWriter subclass. The other two override it anyway.

Closes gh-29631
2022-12-05 15:37:48 +00:00
CoderYellow a7bf14b364 Fix canWrite of PartHttpMessageWriter
See gh-29631
2022-12-05 15:37:48 +00:00
rstoyanchev 7899fa3b0a Polishing contribution
Closes gh-29622
2022-12-05 15:37:48 +00:00
Marten Deinum c1da2a4e73 Improve Netty code sample
See gh-29622
2022-12-05 15:37:48 +00:00
rstoyanchev db53b618c1 Simplify form data handling in HttpRequestValues
Closes gh-29615
2022-12-05 15:37:48 +00:00
rstoyanchev 913163884a Improve invalid Content-Type handling in WebFlux
Closes gh-29565
2022-12-05 15:37:48 +00:00
Brian Clozel 4a555aaef1 Reduce heap memory usage in ConcurrentLruCache
Prior to this commit, the `ConcurrentLruCache` implementation would use
arrays of `AtomicReference` as operation buffers, and the buffer count
would be calculated with the nearest power of two for the CPU count.

This can result in significant heap memory usage as each
`AtomicReference` buffer entry adds to the memory pressure. As seen in
FasterXML/jackson-databind#3665, this can add a significant overhead for
no real added benefit for the current use case.

This commit changes the current implementation to use
`AtomicReferenceArray` as buffers and reduce the number of buffers.
JMH benchmarks results are within the error margin so we can assume that
this does not change the performance characteristics for the typical use
case in Spring Framework.

Fixes gh-29520
2022-12-05 13:02:11 +01:00
Brian Clozel e9ada8d15c Upgrade JMH build plugins
This commit upgrades the Gradle JMH plugin to 0.6.8 and the companion
JMH version to 1.36.
2022-12-05 13:02:11 +01:00
Sam Brannen 63d841664c Polish ref docs build 2022-12-04 22:35:04 -05:00
Sam Brannen 9779d25d98 Revise PDF ref docs to include TOC, authors, and legal sections 2022-12-04 22:13:20 -05:00
Sam Brannen 89d0c6b962 Do not refer to HTML ref docs from HTML ref docs 2022-12-04 22:11:41 -05:00
Sam Brannen 20da0835b3 Polish overview for consistency 2022-12-04 12:33:44 -05:00
Sam Brannen 4f232a9003 Update copyright headers 2022-12-03 18:24:44 -05:00
Sam Brannen c24a51323d Reinstate test for JmxUtils.locateMBeanServer() 2022-12-03 18:23:41 -05:00
Sam Brannen 69d022712b Polish Javadoc for ErrorResponse etc. 2022-12-03 16:19:33 -05:00
Sam Brannen aa1f3d1681 Apply "instanceof pattern matching" 2022-12-03 16:06:58 -05:00
Spark61 b366cd352e Fix ErrorResponse#type documentation
Closes gh-29632
2022-12-03 22:06:16 +01:00
Juergen Hoeller ac667a1e2b Upgrade to Apache HttpClient 5.2
Includes JRuby 9.4, Groovy 4.0.6, Hibernate ORM 5.6.14, HSQLDB 2.7.1, SLF4J 2.0.5, Caffeine 3.1.2, Gson 2.10, POI 5.2.3, Protobuf 3.21.10, WebJars Locator 0.52, HtmlUnit 2.67, Mockito 4.9, Checkstyle 10.5

Closes gh-29627
2022-12-02 20:57:35 +01:00
rstoyanchev a09f93768a Fix URI override for HttpExchange
Closes gh-29624
2022-12-02 17:02:05 +00:00
Brian Clozel 0ccd2f8b87 Deprecate GraphQL media type in favor of new one
This commit deprecates the `"application/graphql+json"` media type in
favor of the new `"application/graphql-response+json"`, since the former
has been removed in graphql/graphql-over-http#215.

Closes gh-29617
2022-12-02 16:25:59 +01:00
Baljit Singh b1fdb148d0 ResponseStatusException delegates to protected constructor
This ensures that by default the reason is used to set the "detail"
field. It's a follow-up fix to a27f2e994b
which resolved the issue partially.

Closes gh-29608
2022-12-02 14:20:16 +00:00
Juergen Hoeller 955ca4d146 Revised support for Jetty 12 (tested against 12.0.0.alpha2)
Avoids HttpFields optimization completely, relying on Servlet header access instead.
ServletServerHttpResponse provides applyHeaders/adaptHeaders split for better reuse.

See gh-29575
2022-12-01 19:45:40 +01:00
Juergen Hoeller d5732fed45 Polishing 2022-12-01 17:46:31 +01:00
Juergen Hoeller 4c7b04e32a Use resolved factory method return type for supplier code generation
Closes gh-29598
2022-12-01 17:46:23 +01:00
Johnny Lim 74ec10bf3a Polish
Closes gh-29619
2022-12-01 17:34:33 +01:00
Juergen Hoeller dd6cb1b728 Polishing 2022-12-01 15:48:24 +01:00
Juergen Hoeller 1e4c10cef1 Add equals/hashCode methods to ProblemDetail
Closes gh-29606
2022-12-01 15:47:40 +01:00
Juergen Hoeller e47978e168 Avoid unnecessary parameter name inspection for constructor-arg resolution
Closes gh-29612
2022-12-01 15:47:12 +01:00
Sam Brannen 52e967a525 Apply update_copyright_headers.sh to staged files as well 2022-11-30 15:18:11 +01:00
Sam Brannen 1de9d123a5 Update Javadoc for MBeanTestUtils 2022-11-30 15:15:51 +01:00
Sam Brannen ad60164911 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-11-29 19:38:42 +01:00
Sam Brannen c49b0825f9 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-11-29 19:34:11 +01:00
Sam Brannen fdec9f0adc Apply "instanceof pattern matching" 2022-11-29 18:09:42 +01:00
Sam Brannen a88dbbec98 Apply project formatting rules for ternary operator
Discovered via RegEx: ^\s+\?
2022-11-29 17:51:13 +01:00
Sam Brannen 61d8774da0 Add missing callout 2022-11-29 13:54:46 +01:00
Sam Brannen c2b16f1ffb Fix code example callouts in reference manual 2022-11-29 13:54:10 +01:00
Sam Brannen 6af94dffe5 Add "missing" callout for parity 2022-11-29 13:52:26 +01:00
Sam Brannen 2147175898 Polishing 2022-11-29 13:51:34 +01:00
Sam Brannen 052542254a Polishing 2022-11-28 17:51:18 +01:00
Sam Brannen 1bb723b9e0 Rename to AbstractReactiveWebSocketIntegrationTests to avoid duplicate class names 2022-11-28 17:43:39 +01:00
Sam Brannen db02c96c55 Avoid deprecation warnings in tests 2022-11-28 17:40:46 +01:00
Sam Brannen 164141a63e Fix broken tests in SockJsServiceTests
See gh-29594
2022-11-28 16:52:15 +01:00
Sam Brannen 0a731413de Polishing 2022-11-28 16:45:38 +01:00
Sam Brannen 6e5dd64025 Polish contribution
See gh-29594
2022-11-28 16:42:22 +01:00
Aashay Chapatwala 650875468c Add title to SockJS iFrames for accessibility compliance
Closes gh-29594
2022-11-28 16:33:41 +01:00
Yanming Zhou 6d2a25b877 Fix typo in observability documentation
Closes gh-29590
2022-11-28 15:13:03 +01:00
Sam Brannen 2847621928 Fix errors in Testing chapter
- group code example callouts to ensure callouts are displayed for the
  correct examples

- add missing callouts

- fix syntax, annotation attribute names, etc.
2022-11-28 14:47:56 +01:00
Sam Brannen 3afc6a5079 Polish Testing chapter 2022-11-28 14:45:46 +01:00
rstoyanchev 6c8fb6c204 Add MessageSource getters
See gh-29574
2022-11-28 10:59:57 +00:00
Sam Brannen 8e9a553517 Update Javadoc regarding JUnit versions 2022-11-26 16:48:03 +01:00
Sam Brannen 537d539b1d Use JUnit Jupiter annotations as examples in TestContextManager JavaDoc 2022-11-26 16:17:01 +01:00
Sam Brannen 476b9cfc99 Polish TestContextManager internals 2022-11-26 16:17:01 +01:00
Sam Brannen 352087a637 Forbid loading of test ApplicationContext in AOT mode if AOT processing failed
Prior to this commit, if AOT processing of a test's ApplicationContext
failed, the TestContext Framework (TCF) still attempted to load the
context via standard (JVM) mechanisms when running in AOT mode.

For example, if a test class uses Spring Boot's @MockBean, AOT
processing of that test's context will fail with a WARN log message,
and there will no mapping from that test class to an AOT-generated
ApplicationContextInitializer (ACI). Consequently, when the test suite
is run in AOT mode that particular test class will currently fail with
a confusing stack trace due to the fact that Spring Boot's
SpringApplication attempts to locate a "main" ACI instead of the
missing "test" ACI (missing because it was not generated during AOT
processing).

In general, the TCF should not attempt to load an ApplicationContext in
"JVM mode" while running in "AOT mode".

This commit therefore reworks the logic in
DefaultCacheAwareContextLoaderDelegate to fail fast (with a meaningful
error message) if an AOT-generated ACI cannot be found while running in
AOT mode. This avoids the aforementioned confusion when @MockBean tests
fail in AOT mode (on the JVM or within a native image), and it also
helps to diagnose build problems if AOT processing has not yet been
performed for the project's test suite.

Closes gh-29579
2022-11-26 15:32:16 +01:00
Sam Brannen 33d33802a8 Improve logging in TestContextManager 2022-11-26 15:30:50 +01:00
Sam Brannen 9ec937c843 Remove erroneous Javadoc link 2022-11-26 14:40:49 +01:00
Juergen Hoeller 8e5eb84da1 Consistently register CGLIB hints for lazy resolution proxy classes
Core JDK/CGLIB proxy registration code extracted to ClassHintUtils.

Closes gh-29584
2022-11-26 13:38:34 +01:00
Sam Brannen 902f8dd1d8 Upgrade Gradle wrapper
See gh-29583
2022-11-25 23:12:08 +01:00
Juergen Hoeller 22f8ea61fb Upgrade to Gradle 7.6
Closes gh-29583
2022-11-25 22:33:09 +01:00
Brian Clozel 8ce1f14554 Document Observability support in reference docs
Closes gh-29524
2022-11-25 17:33:11 +01:00
Brian Clozel 9a3cb628af Split integration chapter in smaller documents
This commit splits the integration chapter of the reference
documentation in smaller documents for easier maintenance.
2022-11-25 17:33:07 +01:00
Brian Clozel b0a4c5d72c Fix unrendered titles in websocket section
This commit fixes the rendering of titles in the websocket section of
the reference documentation.

Fixes gh-29569
2022-11-25 17:33:03 +01:00
Brian Clozel 8b110c9971 Reinstate checkstyle for reference docs code snippets
This commit also ensures that checks are performed before the
application is rendered to get early feedback on errors.
2022-11-25 17:32:59 +01:00
Juergen Hoeller 21d3a7529c Consistent documentation references to Jakarta WebSocket (2.1)
Closes gh-29581
2022-11-25 17:07:30 +01:00
Juergen Hoeller 9c7b471634 Deprecate JettyWebSocketClient in favor of StandardWebSocketClient
JettyWebSocketClient only supported on Jetty 11, to be phased out.

Closes gh-29576
2022-11-25 17:06:15 +01:00
Juergen Hoeller 45d45c2989 Early support for Jetty 12 (developed against 12.0.0.alpha2)
Reflective getHeaders calls to be revisited; see GitHub issue #8938 in Jetty project.
HttpOutput optimization commented out still in order to avoid alpha build dependency.

See gh-29575
2022-11-25 17:04:48 +01:00
Spring Builds 4ff18741fd Next development version (v6.0.3-SNAPSHOT) 2022-11-24 13:50:54 +00:00
Juergen Hoeller b7e99fbe30 Additional documentation notes on Java/Kotlin parameter name retention
See gh-29563
2022-11-24 14:08:53 +01:00
rstoyanchev a27f2e994b ResponseStatusException sets detail from reason again
Closes gh-29567
2022-11-24 12:40:25 +00:00
Juergen Hoeller 284cf3ecf2 Rely on standard parameter name resolution in Bean Validation 3.0
Just configuring additional Kotlin reflection if Kotlin is present.

Closes gh-29566
2022-11-24 12:01:51 +01:00
Juergen Hoeller cbf25b704d Reduce deprecation warn logging to one entry per introspected class
Closes gh-29563
2022-11-24 12:01:03 +01:00
Juergen Hoeller 8391897a94 Document removal of CommonsMultipartResolver in MVC setup documentation
Closes gh-29562
2022-11-24 12:00:19 +01:00
rstoyanchev a3c89092e1 Log connection info in StompBrokerRelayMessageHandler
See gh-29287
2022-11-23 13:58:37 +00:00
Spring Builds e77c426eeb Next development version (v6.0.2-SNAPSHOT) 2022-11-23 10:12:32 +00:00
Juergen Hoeller fe5bd6751f Retain default LocalVariableTableParameterNameDiscoverer with warn log entries
For a transition period, LocalVariableTableParameterNameDiscoverer logs a warning for each successful resolution attempt now, suggesting that -parameters was missed.

See gh-29531
See gh-29559
2022-11-23 10:31:43 +01:00
Juergen Hoeller ed5ab77397 Fix javadoc link in AOP extensibility documentation
Closes gh-29554
2022-11-22 22:00:57 +01:00
rstoyanchev 98c514ecbe Increase logging for spring-messaging tests
See gh-29287
2022-11-22 20:52:50 +00:00
Juergen Hoeller beb9fa2b8b Add since attribute to Deprecated annotation
Also retaining standard Java parameter names for Spring's AspectJ sources now.

See gh-29531
2022-11-22 21:18:34 +01:00
Juergen Hoeller 459e8a1ea5 Deprecate LocalVariableTableParameterNameDiscoverer completely
LocalVariableTableParameterNameDiscoverer is not registered by default anymore now.
Java sources should be compiled with `-parameters` instead (available since Java 8).
Also retaining standard Java parameter names for all of Spring's Kotlin sources now.

Closes gh-29531
2022-11-22 19:26:15 +01:00
rstoyanchev 7e52b803be Temporarily re-enable ReactorNetty2StompBrokerRelayIntegrationTests
To see if it still fails on the CI server as it doesn't fail locally
for me, and if it does to get details to investigate.

See gh-29287
2022-11-22 16:42:57 +00:00
Sam Brannen 7fcd1de8e3 Use AssertJ's isEmpty() instead of hasSize(0)
Achieved via global search-and-replace.
2022-11-22 17:11:50 +01:00
Sam Brannen d5b0b2b1a1 User AssertJ's hasSize() for arrays
Achieved via global search-and-replace.
2022-11-22 17:03:45 +01:00
Sam Brannen 36f7597f25 Use AssertJ's hasSize() for collections and maps
Achieved via a global search-and-replace.
2022-11-22 16:50:10 +01:00
Sam Brannen f9f8f2d89e Polishing 2022-11-22 16:27:45 +01:00
Sam Brannen 43f8d9e084 Apply 'instanceof pattern matching' 2022-11-22 16:27:34 +01:00
Juergen Hoeller 7816c9e411 Exclude LocalVariableTableParameterNameDiscoverer based on native image check
See gh-29531
2022-11-22 15:37:00 +01:00
Sam Brannen d32027df92 Apply 'instanceof pattern matching' 2022-11-22 15:11:37 +01:00
Sam Brannen a832c98ced Polish contribution
See gh-29460
2022-11-22 14:31:49 +01:00
divcon c12d93c5d1 Polish ServletWebRequest and DefaultServerWebExchange
- The return values of ServletWebRequest.validateIfUnmodifiedSince and
  DefaultServerWebExchange.validateIfUnmodifiedSince are not used. So I
  think that it is better to remove the return statements.

- Add missing @Nullable declarations to eTag method parameters.

- Simplify if statements

Closes gh-29460
2022-11-22 14:30:41 +01:00
Sam Brannen ca6acfee30 Polishing 2022-11-22 14:24:03 +01:00
jiangying b130ff36d9 Fix Javadoc link text in BindingResult
Closes gh-29551
2022-11-22 13:38:57 +01:00
Sébastien Deleuze 0b8000eeaa Refine LogAdapter#isPresent
Align LogAdapter#isPresent with ClassUtils#isPresent in order
to catch NoClassDefFoundError and other errors.

Closes gh-29506
2022-11-22 09:44:52 +01:00
Sébastien Deleuze 8350738929 Upgrade to Kotlin 1.7.21
Closes gh-29543
2022-11-22 08:53:10 +01:00
André Gasser b695687e13 Fix some typos in Kotlin WebClient example code
Closes gh-29538
2022-11-22 08:26:11 +01:00
Sébastien Deleuze 2ba7a553b3 Upgrade to Jackson 2.14.1
Fix an important memory consumption regression, see
https://github.com/FasterXML/jackson-databind/issues/3665
for more details.

Closes gh-29539
2022-11-22 07:30:38 +01:00
Sébastien Deleuze 1e98fb607a Make SourceHttpMessageConverter optional
As a follow-up to gh-29277, and since the JAXB support is now
triggered by the classpath presence of a JAXB implementation,
it makes sense to make SourceHttpMessageConverter, previously
configured unconditionally, optional.

That makes a big difference on native (1M of RSS reduction
with current typical Spring Boot 3 arrangement, 3.4M when
other usages of XML are not reachable).

It also brings more consistency between Spring MVC
and Spring WebFlux, and means that XML support for
Spring web applications now needs to be enabled explicitly.

As a consequence, Spring web applications using
javax.xml.transform.Source now needs to configure
SourceHttpMessageConverter explicitly in RestTemplate or
Spring MVC.

Closes gh-29535
2022-11-21 18:23:26 +01:00
Marten Deinum c1dfde5ba4 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
2022-11-21 16:59:30 +01:00
Sam Brannen 917c41fd52 Use Set.of() for constant sets where appropriate 2022-11-21 16:49:07 +01:00
Sam Brannen 0c878d2d06 Apply additional 'instanceof pattern matching' in spring-web
See gh-29530
2022-11-21 15:57:53 +01:00
Sam Brannen 50109dd86d Polish contribution
See gh-29530
2022-11-21 15:57:53 +01:00
divcon 99ae209c25 Apply 'instanceof pattern matching' in spring-web
Closes gh-29530
2022-11-21 14:29:24 +01:00
Sébastien Deleuze 64c6a97130 Make GeneratorStrategy.generate unreachable on native
This change provides also more information to the user
about the missing generated class when that happens.

Closes gh-29521
2022-11-21 13:04:20 +01:00
Sam Brannen 2112e86795 Revert "Ensure source code in framework-docs is compiled in the build"
This reverts commit c45f8b7072.
2022-11-21 12:55:49 +01:00
Sébastien Deleuze f4e23fe204 Do not use LocalVariableTableParameterNameDiscoverer in AOT mode
Closes gh-29531
2022-11-21 11:50:08 +01:00
Sébastien Deleuze 04366f4129 Update LogAdapter to allow build-time code removal
Allow for example to remove those classes and 90 related methods when Logback is used:
- org.apache.commons.logging.LogAdapter$JavaUtilAdapter
- org.apache.commons.logging.LogAdapter$JavaUtilLog
- org.apache.commons.logging.LogAdapter$LocationResolvingLogRecord
- org.apache.commons.logging.LogAdapter$Log4jAdapter
- org.apache.commons.logging.LogAdapter$Log4jLog
- org.apache.commons.logging.LogAdapter$LogApi
- org.apache.logging.log4j.message.ObjectMessage
- org.apache.logging.log4j.message.ReusableObjectMessage
- org.apache.logging.log4j.simple.SimpleLoggerContext
- org.apache.logging.log4j.simple.SimpleLoggerContextFactory

Closes gh-29506
2022-11-21 11:49:48 +01:00
David Costanzo 2a2c679f66 Fix a syntax error in an XML listing by adding a missing double-quote
Closes gh-29456
2022-11-20 19:21:53 +01:00
Sam Brannen 32a5830543 Ensure code listing callouts are displayed incorrectly in core-beans.adoc
Closes gh-29457
2022-11-20 19:17:34 +01:00
Sam Brannen 9378493d83 Polish ref docs 2022-11-20 19:16:27 +01:00
Sam Brannen da12481ef1 Polish ref docs
- stop referring to Java Config as new
- stop referring to Struts 2.x as if it were new
- polish AOT documentation
- etc.
2022-11-19 17:16:43 +01:00
Sam Brannen c45f8b7072 Ensure source code in framework-docs is compiled in the build
This also ensures that the source code can be properly imported into an
IDE.
2022-11-19 16:43:47 +01:00
Sam Brannen 60243dbbac Polish asciidoc attributes 2022-11-19 16:43:47 +01:00
Sam Brannen fb1f0eccfb Reinstate chapter asciidoc attribute for Web MVC 2022-11-19 16:43:47 +01:00
Sam Brannen c0602fd071 Introduce appendix in Testing chapter in the reference manual
This commit moves the Annotations and Further Resources sections to the
new Appendix.

See gh-29522
2022-11-19 14:59:34 +01:00
divcon 870e856554 Fix link to WebFlux section in reference manual
Closes gh-29525
2022-11-19 14:42:55 +01:00
Sam Brannen b9656ac6c0 Polishing 2022-11-19 14:38:39 +01:00
Sam Brannen de441b4751 Remove TODOs in WebFlux ref docs 2022-11-19 14:38:01 +01:00
Sam Brannen 9c3efdec32 Fix broken link to Web MVC Testing section 2022-11-19 14:37:29 +01:00
Brian Clozel af40a124bb Disable checkstyle for reference docs code snippets 2022-11-18 18:24:43 +01:00
Brian Clozel 44c583392e Document RuntimeHints testing strategies
Closes gh-29523
2022-11-18 18:11:35 +01:00
Sam Brannen 9249dc3d37 Reorganize and modularize the Testing chapter in the reference manual
Closes gh-29522
2022-11-18 17:33:40 +01:00
Sam Brannen 3458f293d4 Polish asciidoc attributes 2022-11-18 15:42:27 +01:00
Sam Brannen 796b8c1278 Polishing 2022-11-18 15:14:14 +01:00
Sam Brannen cefd74555a Polish contribution 2022-11-18 15:07:08 +01:00
wizard e9555d4825 Polish AbstractAutowireCapableBeanFactory and use instanceof pattern matching
Closes gh-29499
2022-11-18 15:00:05 +01:00
Brian Clozel 1960666765 Set error status in Observation Servlet filter
Prior to this commit, the Observation Servlet filter would record
unhandled exceptions on the observation context but would leave the
default HTTP response status as is.
Servlet containers do set the response status in that case to 500 by
default. Not doing that at the Servlet filter level results in invalid
observations, stating that the HTTP response status is 200 (because the
error status hasn't been set yet by the container) and as a result, the
outcome is SUCCESS.

This commit ensures that the error status is set in those cases,
aligning the behavior with Servlet containers.

Fixes gh-29512
2022-11-18 14:15:49 +01:00
Stephane Nicoll 45dc1d2602 Fix link to WebFlux section
Closes gh-29513
2022-11-18 10:47:27 +01:00
Sébastien Deleuze ef5796c3a9 Update documentation to mention Java 17+ baseline
Closes gh-29514
2022-11-18 09:43:41 +01:00
Sébastien Deleuze b52300eab8 Document GraalVM substitutions upcoming removal 2022-11-17 18:01:02 +01:00
Sam Brannen 031adfb8ec Use lambda expression for Callable example in ref docs 2022-11-17 17:13:50 +01:00
Arjen Poutsma 792371ac1f Generalize Jackson version numbers
This commit removes specific version info from Jackson codecs and
converters, in favor of generic info or removing the version information
all together.

See gh-29508
2022-11-17 16:56:38 +01:00
Brian Clozel 62bbebd4f4 Polishing 2022-11-17 16:55:53 +01:00
Sam Brannen ac7d428a62 Work around code example callout bug
This commit adds callouts to two sets of Java/Kotlin code examples in
the @ModelAttribute section for Web MVC in order to work around the
"Code example has callout from a different code example" bug.

This also aligns the Web MVC examples with the WebFlux examples.

As a side note, the bug can also be seen in the WebFlux documentation
if the callouts are removed from the first Java/Kotlin examples in the
@ModelAttribute section for WebFlux. Thus it appears to be a general
issue related to examples within a given section of the documentation
when some examples have callouts and others do not, likely due to a bug
in the Javascript that provides this feature.

See gh-29505
2022-11-17 16:37:08 +01:00
Sam Brannen f6eaa8e63c Add missing callouts 2022-11-17 16:36:40 +01:00
Sam Brannen cd27fbe550 Add callouts to Kotlin examples for parity 2022-11-17 16:36:40 +01:00
Sam Brannen bbfc39efc9 Polishing 2022-11-17 16:36:40 +01:00
Brian Clozel 1a8a69d289 Refactor Asciidoctor attributes in reference docs
This commit reorganizes the asciidoctor attributes for the reference
documentation. Instead of being contributed partially by the build and
individual documents, attributes are now shared in common files that are
included in top sections.
2022-11-17 15:35:28 +01:00
Stephane Nicoll e16cdfede0 Merge pull request #29508 from wilkinsona
* pr/29508:
  Update Jackson-based decoders to reflect 2.14 baseline

Closes gh-29508
2022-11-17 11:34:19 +01:00
Andy Wilkinson 26df6fbada Update Jackson-based decoders to reflect 2.14 baseline
See gh-29508
2022-11-17 11:22:15 +01:00
Sam Brannen 508d2c7a77 Fix Javadoc formatting issues for headings
Headings in method-level Javadoc must be h4 or higher in recent versions
of Java.
2022-11-16 14:09:42 +01:00
Sam Brannen 428539f30d Polishing 2022-11-16 13:52:10 +01:00
Sam Brannen d0d5730f7f Suppress "removal" warnings in CronSequenceGeneratorTests 2022-11-16 12:30:10 +01:00
Spring Builds befa4b14cd Next development version (v6.0.1-SNAPSHOT) 2022-11-16 10:26:53 +00:00
Stephane Nicoll 42856bab16 Add milestone repo for optional Netty 5 support
Closes gh-29498
2022-11-16 11:03:14 +01:00
Arjen Poutsma 9be6cea012 Polishing deprecated methods
Added since and forRemoval to Deprecated methods.
2022-11-16 09:58:04 +01:00
Andy Wilkinson 37b439182e Align javadoc of DefaultParameterNameDiscoverer with its behavior 2022-11-16 08:16:57 +01:00
Stephane Nicoll 09a58a55bf Polish 2022-11-15 20:10:03 +01:00
Andriy 10f4ad1a44 Assert fixed in DefaultErrorResponseBuilder
Fixed assert on wrong constructor fields
2022-11-15 19:55:18 +02:00
Sam Brannen 9457ed342d Document AOT support in the TestContext framework
Closes gh-29482
2022-11-15 17:29:16 +01:00
Sam Brannen 074ec97655 Fix section formatting in the testing chapter 2022-11-15 17:25:27 +01:00
Sam Brannen 9ede4afc34 Revert "Ignore HttpComponents Javadoc"
This reverts commit f50b472ceb.

HttpComponents Javadoc is available again.

See gh-29479
See https://issues.apache.org/jira/browse/HTTPCLIENT-2227
2022-11-15 15:06:55 +01:00
Sam Brannen bfc125105f Merge branch '5.3.x' 2022-11-15 14:47:21 +01: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
Sam Brannen fe03654e83 Update testing chapter regarding Servlet 6.0 baseline for mocks 2022-11-15 14:31:43 +01:00
Sam Brannen da920bc488 Polish AOT ref docs 2022-11-15 14:25:13 +01:00
Juergen Hoeller 8937015993 Merge branch '5.3.x'
# Conflicts:
#	build.gradle
2022-11-15 13:13:29 +01:00
Juergen Hoeller c94025699f Upgrade to Reactor 2020.0.25
See gh-29464
2022-11-15 13:11:32 +01:00
Juergen Hoeller f8b4be3b82 Straight filename extraction for URI path (decoded and standard separators)
See gh-29486
2022-11-15 12:50:15 +01:00
Sam Brannen abf3400c07 Use Assert.state() where appropriate 2022-11-15 12:31:10 +01:00
Sam Brannen 2aa78889d2 Use consistent wording in precondition error messages 2022-11-15 12:31:01 +01:00
Stephane Nicoll 711a63adca Polish
See gh-29391
2022-11-15 11:53:01 +01:00
Juergen Hoeller 9235e3996f Equivalent code without java.net.URL constructor in comment blocks
See gh-29486
See gh-29481
2022-11-15 00:33:48 +01:00
Juergen Hoeller 7d2543ed82 Extract filename from cleaned path (for consistent separator handling)
See gh-29486
2022-11-14 23:53:39 +01:00
Juergen Hoeller 588a70218a Merge branch '5.3.x'
# Conflicts:
#	spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java
2022-11-14 23:38:10 +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
Juergen Hoeller 28cd39abf9 Remove unused AutowiredAnnotationBeanPostProcessor template methods
Closes gh-29487
2022-11-14 23:23:39 +01:00
Juergen Hoeller aaeb5eb0d2 Avoid direct URL construction and URL equality checks
Closes gh-29486
2022-11-14 23:23:12 +01:00
Sam Brannen 0b21c16fa8 Suppress unused warning in test code 2022-11-14 20:41:47 +01:00
Sam Brannen 7d731ee754 Merge branch '5.3.x'
# Conflicts:
#	spring-core/src/test/java/org/springframework/util/SocketUtilsTests.java
2022-11-14 20:31:26 +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
Sam Brannen 6efc3dadf1 Apply "instance pattern matching" 2022-11-14 17:12:20 +01:00
Sam Brannen 07ba13c9ca Remove superfluous method override 2022-11-14 17:11:58 +01:00
Stephane Nicoll 5421a36c8f Add section on runtime hints
See gh-29350
2022-11-14 14:54:27 +01:00
Brian Clozel 3573022b96 Fix version change in previous commit 2022-11-14 13:23:05 +01:00
Brian Clozel 1ad7cc3702 Reorganize server observability packages
Prior to this commit, the server observability support would create a
cycle in Java packages.

This commit refactors the current arrangement to solve this by:

* "flattening" the reactive HTTP instrumentation; this removes the
  dependency to the `ServerWebExchange` and `PathPattern` types
* moving the `observation` package under
  `org.springframework.http.server` and
  `org.springframework.http.server.reactive`

See gh-29477
2022-11-14 12:59:45 +01:00
Sébastien Deleuze 91c6fac18a Update outdated WebClientAdapter.createHttpServiceProxyFactory documentation 2022-11-14 11:16:16 +01:00
Brian Clozel f50b472ceb Ignore HttpComponents Javadoc
Closes gh-29479
2022-11-14 10:42:34 +01:00
Sébastien Deleuze 7a9bd3fed9 Merge branch '5.3.x' 2022-11-13 19:08:28 +01:00
Sébastien Deleuze b766a49a4d Support suspending functions returning Unit in WebFlux
Closes gh-27629
2022-11-13 19:05:29 +01:00
Sam Brannen eb91d21ada Polishing 2022-11-13 18:21:56 +01:00
Sam Brannen 1f0a35bacc Remove outdated documentation in @Reflective 2022-11-13 16:57:54 +01:00
Sam Brannen ae3bec5d57 Allow test classes to provide runtime hints via declarative mechanisms
Prior to this commit, it was possible to register hints for individual
test classes programmatically via the
org.springframework.test.context.aot.TestRuntimeHintsRegistrar SPI;
however, that requires that a custom TestRuntimeHintsRegistrar be
registered via "META-INF/spring/aot.factories". In addition,
implementing a TestRuntimeHintsRegistrar is more cumbersome than using
the core mechanisms such as @Reflective, @ImportRuntimeHints, and
@RegisterReflectionForBinding.

This commit address this by introducing support for @Reflective and
@ImportRuntimeHints on test classes. @RegisterReflectionForBinding
support is available automatically since it is an extension of the
@Reflective mechanism.

Closes gh-29455
2022-11-12 14:41:09 +01:00
Sam Brannen 1b61217705 Polishing 2022-11-12 14:40:55 +01:00
Juergen Hoeller ffd45c0e7b Move reflection hints for ObjectToObjectConverter conventions to aot.hint.support
Avoids an accidental package cycle between aot and core (only aot->core allowed).

See gh-29429
2022-11-12 11:23:40 +01:00
Sam Brannen 049eb98e00 Merge branch '5.3.x' 2022-11-11 17:12:28 +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 e0b405869f Merge branch '5.3.x' 2022-11-11 15:16:26 +00:00
rstoyanchev 479a53b132 Update docs on DispatcherHandler exception handling
See gh-22991
2022-11-11 13:51:21 +00:00
rstoyanchev 0348a7bf2e Improve API for RFC 7807 in functional endpoints
Closes gh-29462
2022-11-11 13:34:35 +00: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 9d1dfc733d Upgrade to R2DBC H2 1.0.0
See gh-28787
2022-11-11 09:39:05 +01:00
Juergen Hoeller ddbbe67361 Upgrade to Reactor 2022.0.0
Includes Netty 4.1.85, Jetty Reactive HttpClient 3.0.7, SmallRye Mutiny 1.8, SLF4J 2.0.3, OpenPDF 1.3.30, Mockito 4.8.1, HtmlUnit 2.66

Closes gh-29465
2022-11-10 18:55:00 +01:00
Juergen Hoeller 0e4ab2c63a Merge branch '5.3.x'
# Conflicts:
#	build.gradle
#	spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java
#	spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java
#	spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletRequest.java
#	spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletResponse.java
2022-11-10 18:29:05 +01: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
Sam Brannen 1443669091 Polishing 2022-11-10 17:25:20 +01:00
Johnny Lim 4c2072d20c Use unquoted value in assertion message in MediaType.checkParameters() 2022-11-10 15:48:39 +01:00
rstoyanchev fb22044c10 Polishing
See gh-22991
2022-11-09 11:34:32 +00:00
Stephane Nicoll da4b539f20 Stop generating generic type as Object for unresolved generics
Closes gh-29454
2022-11-09 12:00:34 +01:00
Juergen Hoeller 70bb785ed6 Turn nested generic FactoryBean type into resolved Class for fallback match
See gh-29385
2022-11-09 11:24:50 +01:00
Sam Brannen 69736af5fc Revise ContextLoadException constructor to accept a Throwable 2022-11-08 20:35:17 +01:00
Juergen Hoeller 0e9eab55ce Unwrap nested generic type within FactoryBean target type if necessary
Closes gh-29385
2022-11-08 20:22:12 +01:00
Sam Brannen f26a7dee97 Fix broken tests, update copyright dates, and polish
See gh-29414
2022-11-08 20:07:53 +01:00
Kulwant Singh b2c8546013 Rely on automatic boxing/unboxing in tests
Closes gh-29414
2022-11-08 19:38:03 +01:00
Sam Brannen 7d68d0625c Polishing 2022-11-08 19:32:46 +01:00
Kulwant Singh debe78b7f9 Minor improvements in spring-test
- Remove final modifier from private method
- Use StandardCharsets
- Remove unnecessary toString calls
- Remove unnecessary static modifiers
- Refactor to use enhanced switch
- Replace concatenated strings with text blocks
- Rely on auto-boxing where appropriate
- Remove unnecessary code
- Fix imports in Kotlin test classes

Closes gh-29413
2022-11-08 19:32:46 +01:00
rstoyanchev 307247b6a3 Use DispatchExceptionHandler in HandlerResult
Commit #2878ad added the DispatchExceptionHandler contract for
mapping an error before a handler is selected to a HandlerResult.
The same is also convenient for use in HandlerResult itself which
currently uses a java.util.Function essentially for the same.

See gh-22991
2022-11-08 18:31:35 +00:00
Sam Brannen a9a78686ed Merge branch '5.3.x'
# Conflicts:
#	spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java
2022-11-08 18:13:26 +01:00
Christoph Dreis 55b258f2de Avoid unnecessary allocations in StompDecoder#unescape
Closes gh-29443
2022-11-08 18:10:54 +01:00
Sam Brannen e058a6061a Move DataFieldMaxValueIncrementerTests to the appropriate package 2022-11-08 18:02:19 +01:00
Sam Brannen 8595493599 Polish contribution 2022-11-08 18:00:50 +01:00
Mahmoud Ben Hassine f9ed0721a8 Introduce DataFieldMaxValueIncrementer for SQL Server sequences
This commit introduces SqlServerSequenceMaxValueIncrementer to support
SQL Server sequences, complementing the existing
SqlServerMaxValueIncrementer for table-based support.

Closes gh-29447
2022-11-08 17:54:16 +01:00
Sébastien Deleuze ce9e2e4d89 Register reflection hints for date ObjectToObjectConverter conventions
Closes gh-29429
2022-11-08 17:39:37 +01:00
Sam Brannen af170f693a Deprecate obsolete Assert APIs for removal in 6.1
See gh-29449
2022-11-08 16:55:06 +01:00
Sam Brannen 727aa517d8 Merge branch '5.3.x' 2022-11-08 16:34:40 +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
Sébastien Deleuze 60c9f2f72f Add support for Jackson annotations in BindingReflectionHintsRegistrar
This commits registers reflection hints on field and methods
where Jackson annotations are detected.

Closes gh-29426
2022-11-08 16:19:27 +01:00
rstoyanchev 2878ade980 WebFlux support for handling of early exceptions
This change enables a WebFlux HandlerAdapter to handle not only the
success scenario when a handler is selected, but also any potential
error signal that may occur instead. This makes it possible to
extend ControllerAdvice support to exceptions from handler mapping
such as a 404, 406, 415, and/or even earlier exceptions from the
WebFilter chain.

Closes gh-22991
2022-11-08 15:13:18 +00:00
Sam Brannen 9d73f81e9c Avoid String allocations with Assert.notNull() 2022-11-08 14:23:22 +01:00
Sam Brannen 9e4cddf5db Fix precondition assertions 2022-11-08 14:21:58 +01:00
Sam Brannen d0b162a76c Polishing 2022-11-08 14:16:00 +01:00
Sam Brannen 95f3337bb5 Revise contribution
This commit reverts changes to AbstractCacheManager since iterating
over the caches in a for-loop and a stream is duplicated effort.

This commit reverts changes to DefaultRenderingResponseBuilder,
RouterFunctions, and OriginHandshakeInterceptor since order matters for
those use cases: they were originally based on the semantics of
LinkedHashSet or LinkedHashMap; whereas, Set.copyOf() and Map.copyOf()
do not provide any guarantees regarding ordering.

This commit also applies analogous changes to "sibling" implementations
across Servlet mocks as well as Web MVC and WebFlux.

See gh-29321
2022-11-08 14:14:29 +01:00
divcon ba136dcf40 Replace use of Collections.unmodifiable*() methods where appropriate
Closes gh-29321
2022-11-08 13:51:31 +01:00
Juergen Hoeller 86d45578d9 Introduce findAllAnnotationsOnBean variant on ListableBeanFactory
Closes gh-29446
2022-11-08 13:29:33 +01:00
Sam Brannen e1010a179f Merge branch '5.3.x'
# Conflicts:
#	spring-context/src/test/java/org/springframework/context/annotation/Gh29105Tests.java
2022-11-08 12:27:40 +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 3438c47744 Polishing 2022-11-08 11:48:13 +01:00
rstoyanchev aeb35663d4 Remove deprecated methods in HttpServiceProxyFactory 2022-11-07 16:57:17 +00:00
Juergen Hoeller a2ac764f9c Reuse StandardWebSocketUpgradeStrategy as a base class for Tomcat etc
Includes non-reflective instantiation of well-known strategy classes.

See gh-29436
2022-11-07 17:35:31 +01:00
Arjen Poutsma 465575f8f2 Upgrade to Woodstox 6.4.0 2022-11-07 15:40:19 +01:00
Johnny Lim 710cf1f486 Use ObservationThreadLocalAccessor.KEY where possible
Closes gh-29439
2022-11-07 15:39:28 +01:00
Brian Clozel 287d6dec8b Upgrade to Context Propagation 1.0.0
Closes gh-29442
2022-11-07 11:07:12 +01:00
Brian Clozel 19d68a42f8 Upgrade to Micrometer 1.10.0
Closes gh-29441
2022-11-07 11:07:12 +01:00
Juergen Hoeller 19cf503534 Align with Servlet 6.0 and introduce support for Jakarta WebSocket 2.1
Includes corresponding build upgrade to Tomcat 10.1.1 and Undertow 2.3.0
(while retaining runtime compatibility with Tomcat 10.0 and Undertow 2.2)

Closes gh-29435
Closes gh-29436
2022-11-06 16:08:30 +01:00
Brian Clozel 4b22a4a0d8 Merge PDF reference documentation into single file
This commit configures the documentation build to merge the entire
reference documentation into a single PDF file.

To achieve that, this commit also fixes duplicate anchors that were
introduced while factoring out common parts of the documentation for MVC
and WebFlux.

Closes gh-28451
2022-11-06 14:56:53 +01:00
Arjen Poutsma af8518ab1e Upgrade to Jackson 2.14.0
This commit upgrades Jackson to 2.14.0.

Closes gh-29351
2022-11-06 12:21:56 +01:00
Andy Wilkinson 95395b53d5 Make WebSocket upgrade strategies compatible with Tomcat 10.1 2022-11-06 00:30:35 +01:00
Sam Brannen ac5eb9bfd3 Avoid String allocations with Assert.isTrue() 2022-11-05 14:51:36 +01:00
Sam Brannen 82823517fa Merge branch '5.3.x'
# Conflicts:
#	build.gradle
#	spring-messaging/src/main/java/org/springframework/messaging/rsocket/DefaultRSocketRequesterBuilder.java
#	spring-messaging/src/main/java/org/springframework/messaging/rsocket/MetadataEncoder.java
#	spring-messaging/src/main/java/org/springframework/messaging/simp/broker/OrderedMessageChannelDecorator.java
#	spring-messaging/src/main/java/org/springframework/messaging/simp/user/DefaultUserDestinationResolver.java
#	spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java
#	spring-web/src/main/java/org/springframework/http/HttpRange.java
#	spring-webflux/src/main/java/org/springframework/web/reactive/result/view/RedirectView.java
#	spring-webflux/src/main/java/org/springframework/web/reactive/socket/CloseStatus.java
#	spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/RedirectViewControllerRegistration.java
2022-11-05 14:50:18 +01:00
Sam Brannen 4207c4d757 Suppress warnings in tests 2022-11-05 14:44:36 +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 2afcf60566 Avoid String allocations with Assert.state() 2022-11-04 16:44:59 +01:00
Sam Brannen fff999f416 Polishing 2022-11-04 16:44:33 +01:00
Sam Brannen d849f9816a Merge branch '5.3.x'
# Conflicts:
#	build.gradle
#	spring-webflux/src/test/java/org/springframework/web/reactive/result/view/script/ScriptTemplateViewTests.java
#	spring-webmvc/src/main/java/org/springframework/web/servlet/view/script/ScriptTemplateView.java
#	spring-webmvc/src/test/java/org/springframework/web/servlet/view/script/ScriptTemplateViewTests.java
2022-11-04 16:29:54 +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 34b1857236 Avoid String allocations with Assert.state() 2022-11-04 15:51:32 +01:00
Brian Clozel 6022065ad3 Rename web observation documentation
Prior to this commit, several variants of observation documentation
would share the same name; for example HTTP client observations for both
blocking and reactive clients would have the same name.

While it is required that they have the same metric name for dashboards,
the observation documentation names should be different so that they can
be documented without confusing developers.

This commit renames the observation documentation names to avoid that.

Closes gh-29431
2022-11-04 15:38:32 +01:00
Sam Brannen d492086c76 Polishing 2022-11-03 16:02:19 +01:00
Brian Clozel 151977259c Revert "Upgrade CI image to Ubuntu Jammy"
This reverts commit 05c997802b.

It seems we need to update our docker infrastructure on the host first
before upgrading to Ubuntu Jammy.
2022-11-03 12:54:52 +01:00
Brian Clozel a94b0e51e2 Align server contextual names with OTel conventions
This commit ensures that the matching path pattern for the request being
observed is used in the conytextual name, as advised in the OTel HTTP
server semantic conventions.

If the path pattern is not available, no additional value is provided
and the "http {method}" baseline is being used.

Fixes gh-29424
2022-11-02 20:57:41 +01:00
Brian Clozel db79d1d2b9 Set matching pattern in reactive server observation context
This commit fixes the observation instrumentation for the reactive HTTP
server by setting the best matching pattern determined by the web
framework into the `ServerRequestObservationContext`.

This information is required by the observation convention for creating
the expected `KeyValue` for the matching pattern. Prior to this commit,
the information was missing and resulted in an UNKNOWN key value.

Fixes gh-29422
2022-11-02 19:02:31 +01:00
Brian Clozel 05c997802b Upgrade CI image to Ubuntu Jammy 2022-11-02 16:38:03 +01:00
Brian Clozel 38e84a76f9 Upgrade JDK versions in CI image 2022-11-02 16:37:46 +01:00
Brian Clozel c35cd80b84 Upgrade to GitHub Changelog Generator 0.0.8 2022-11-02 16:28:47 +01:00
Brian Clozel 3c049a2bd0 Polish
See gh-29388
2022-11-02 16:26:01 +01:00
Marcin Grzejszczak c03ccb2e6c Propagate context in reactive HTTP server and client
Prior to this commit, the ServerHttpObservationFilter would not add
the current observation as a key in the Reactor context, preventing
from being used or propagated during the HTTP exchange handling.

Also, the client instrumentation in `DefaultWebClient` would start
the observation once the request is fully formed and immutable,
preventing the context from being propagated through HTTP request
headers.

This commit fixes both uses cases now by:

* adding the current observation as a key in the reactor context
  on the server side
* using the `ClientRequest.Builder` as a Carrier on the client side

Closes gh-29388
2022-11-02 16:25:50 +01:00
Sam Brannen 396336fdcc Merge branch '5.3.x' 2022-11-02 15:32:55 +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
Arjen Poutsma 2042cb68a5 Merge two DispatcherHandlerIntegrationTests 2022-11-02 14:48:58 +01:00
Arjen Poutsma 9e306151c7 Use case-insensitive check for request conditions
This commit ensures that the ConsumesRequestCondition and
ProducesRequestCondition use a case insensitive check when comparing
parameters.

Closes gh-29416
2022-11-02 14:29:50 +01:00
rstoyanchev 481389f761 Support @RequestPart for @HttpExchange methods
Closes gh-29420
2022-11-02 13:26:49 +00:00
rstoyanchev 4b647a1801 Minor refactoring in AbstractNamedValueArgumentResolver
Expose MethodParameter information in abstract protected method that
adds the HTTP request value.

See gh-29420
2022-11-02 13:26:49 +00:00
Sam Brannen 723e09c164 Polishing
See gh-29408
2022-11-02 12:46:44 +01:00
Kulwant Singh 5245327962 Fix tests and checkstyle violations
See gh-29408
2022-11-02 12:46:44 +01:00
Kulwant Singh 20d0becbc6 Fix Javadoc links
See gh-29408
2022-11-02 12:46:44 +01:00
Kulwant Singh 5f2a6fd7f1 Use List.of() instead of Arrays.asList() where appropriate
See gh-29408
2022-11-02 12:46:44 +01:00
Kulwant Singh eec3c6f7bb Replace concatenated strings with text blocks
See gh-29408
2022-11-02 12:46:44 +01:00
Kulwant Singh 19955c5b77 Remove unnecessary calls to toString()
See gh-29408
2022-11-02 12:46:44 +01:00
Kulwant Singh bd57d860d2 Use StandardCharsets
See gh-29408
2022-11-02 12:46:44 +01:00
Sébastien Deleuze c091bbdeaa Merge branch '5.3.x' 2022-11-02 12:18:15 +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
Brian Clozel 676f163546 Fix Artifactory configuration for docs deployment
This commit aligns the Artifactory configuration with the changes
applied in gh-29417.
In order to be deployed, docs artifacts must have specific properties
attached to them.

See gh-29417
2022-11-02 11:42:49 +01:00
Sébastien Deleuze aa2d7dba5b Merge branch '5.3.x' 2022-11-02 11:16:35 +01:00
Christoph Dreis 58bb6e7181 Reduce allocations caused by producible media types
Closes gh-29412
2022-11-02 11:15:26 +01:00
Brian Clozel 21414bc265 Move Kotlin Gradle build config to convention
This commit moves the Kotlin build configuration from the Gradle DSL
to a dedicated convention in buildSrc.
2022-11-02 10:59:39 +01:00
Brian Clozel acd9016fc3 Create framework-docs module
This commit creates a new "framework-docs" module, which is dedicated to
documentation generation (reference and API docs).
This commit refactors the build configuration and moves the asciidoc
files to a separate location, but does not change the name nor the
nature of published artifacts.

Closes gh-29417
2022-11-02 10:59:12 +01:00
Sébastien Deleuze 403cfefc28 Add AOT processing of bean aliases
This commit adds AOT processing of bean aliases.

Closes gh-29391
2022-11-02 10:07:21 +01:00
Sébastien Deleuze bfe37c290e Refine PreComputeFieldFeature logging
Closes gh-29406
2022-11-02 07:57:49 +01:00
Arjen Poutsma 6e9fbcc243 Improve PartEvent documentation
Add note about the necessity of consuming the PartEvent content.

See gh-29400
2022-11-01 17:20:01 +01:00
Arjen Poutsma 0ef96b893b Filter out empty PartEvents in PartEventHttpMessageWriter
This commit makes sure that PartEvents with empty data buffer are
filtered out before written. Empty buffers caused issues with the
JdkClientHttpConnector.

Closes gh-29400
2022-11-01 16:24:35 +01:00
Johnny Lim 85d029f7c3 Polishing
Closes gh-29410
2022-11-01 15:22:49 +01:00
rstoyanchev 5ef3aab3fe Warn about ResponseEntity-ProblemDetail status mismatch
Closes gh-29378
2022-11-01 14:10:39 +00:00
rstoyanchev 921eeadff4 Minor refactoring after recent commits
See gh-29384
2022-11-01 13:56:40 +00:00
rstoyanchev e71057dca9 Support i8n of ProblemDetail "title" field
Closes gh-29407
2022-11-01 12:42:34 +00:00
rstoyanchev 506fbe5243 Improve mapping any Exception to ErrorResponse
Add protected, convenience method in ResponseEntityExceptionHandler
to create a ProblemDetail for any exception, along with a
MessageSource lookup for the "detail" field.

Closes gh-29384
2022-11-01 12:42:34 +00:00
Sam Brannen 210019cad1 Polish contribution
See gh-29379
2022-11-01 11:41:41 +01:00
Mahmoud Ben Hassine 39f24f0244 Introduce DataFieldMaxValueIncrementer for MariaDB
Closes gh-29379
2022-11-01 11:27:34 +01:00
Sam Brannen c3fca0a826 Always register root directory for registered resource hints
See gh-29403
2022-10-31 14:21:07 +01:00
Arjen Poutsma ca33752267 Upgrade to Jackson 2.14.0-rc3
This commit upgrades Jackson to 2.14.0-rc3, which resolves two
outstanding issues Spring Framework had with rc2. This commit reverts
the changes made due to those issues, see
https://github.com/FasterXML/jackson-core/issues/824, and
https://github.com/FasterXML/jackson-module-kotlin/issues/582.

Closes gh-29405
2022-10-31 10:35:10 +01:00
Sébastien Deleuze bf3b7b82c1 Merge branch '5.3.x' 2022-10-31 09:07:52 +01:00
David Costanzo e1df056059 Fix typo: "as describe in" -> "as described in" 2022-10-31 09:07:39 +01:00
Sam Brannen 29f085bd1a Automatically register directories for registered resource hints
When a hint such as `graphql/*.*` is registered for resources that are
looked up via classpath scanning using a pattern such as
`classpath*:graphql/**/*.graphqls`, an appropriate pattern is in fact
registered in the generated `resource-config.json` file for GraalVM
native images; however, classpath scanning fails since GraalVM
currently does not make the `graphql` directory automatically available
as a classpath resource.

This can be very confusing and cumbersome for users since a file such
as `graphql/schema.graphqls` will not be discovered via classpath
scanning even though the file is present in the native image filesystem.

To address this, this commit automatically registers resource hints for
enclosing directories for a registered pattern.

If the GraalVM team later decides to perform automatic directory
registration, we can then remove the code introduced in conjunction
with this issue.

Closes gh-29403
2022-10-30 19:02:39 +01:00
Sam Brannen d03102edc3 Allow registration of resource hint for root directory
Prior to this commit, it was not possible to register the root
directory as a native image resource; however, it is necessary to be
able to register the root directory to enable classpath scanning of the
root directory within a native image -- for example, to support
resource patterns such as `classpath*:/*.properties`.

This commit therefore relaxes the precondition check in the
ResourcePatternHint constructor to allow explicit registration of the
root directory.

Closes gh-29402
2022-10-30 18:18:07 +01:00
Sam Brannen 3c42363ba4 Do not close GraalVM Native image FileSystem after classpath scanning
As can be seen in a modified version of the following example project,
attempting to access a resource discovered via classpath scanning
within a GraalVM native image -- for example via the Files.exists(...)
invocation in FileSystemResource -- currently results in a
ClosedFileSystemException since PathMatchingResourcePatternResolver
explicitly closes the native image FileSystem that backs `resource:`
resources.

Sample project: https://github.com/joshlong/spring-boot-3-aot-graphql

To address this issue, this commit removes the explicit close()
invocation for custom FileSystems after classpath scanning in
PathMatchingResourcePatternResolver.

See https://github.com/spring-projects/spring-graphql/issues/495
Closes gh-29397
2022-10-28 21:23:03 +02:00
Arjen Poutsma 2ccfc7068e Merge branch '5.3.x' 2022-10-28 11:33:57 +02:00
Sam Brannen c21bd6659d Introduce TestContextSpringFactoriesUtils to reduce code duplication 2022-10-27 15:19:44 +02:00
Sam Brannen a4d36a8b83 Polish ApplicationContextFailureProcessor support
See gh-29387
2022-10-27 14:29:04 +02: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 86ff0371c2 Merge branch '5.3.x' 2022-10-27 12:12:09 +02:00
Arjen Poutsma 51d109de30 Updated sdkmanrc 2022-10-27 12:03:34 +02:00
Sam Brannen a13cb01b99 Load ApplicationContextFailureProcessors from spring.factories
At the request of the Spring Boot team, ApplicationContextFailureProcessor
implementations are now loaded via the spring.factories mechanism
instead of supporting a single processor registered via subclasses of
AbstractTestContextBootstrapper.

This makes the retrieval and handling of processors internal to
DefaultCacheAwareContextLoaderDelegate, while simultaneously supporting
multiple processors that can be registered by anyone (i.e., not
limited to projects that implement custom TestContextBootstrappers).

See gh-28826
Closes gh-29387
2022-10-26 19:00:32 +02:00
Sam Brannen 273e38c2b4 Make TestAotProcessor more easily extensible 2022-10-26 14:20:46 +02:00
Sam Brannen 997dd3ee65 Revise logging in the TestContext framework
For a Spring Boot test, Logback logs at DEBUG level by default until
Spring Boot's logging infrastructure has a chance to take control, and
this can result in a considerable amount of INFO and DEBUG output.

It's not the number of lines that causes an issue. Rather, it's the
amount of information in each line that can become overwhelming,
especially when the MergedContextConfiguration is complex.

The main reason for lengthy DEBUG logging in a Spring Boot test is that
Spring Boot's ImportsContextCustomizer implements toString() which
results in logging of the fully qualified class names of all imported
configuration classes. In an example using @WebMvcTest, this resulted
in logging of 27 imported classes twice. However, the lists of
registered TestExecutionListener, ContextCustomizerFactory, and
ContextCustomizer implementations are also logged separately, and that
adds quite a bit of noise at DEBUG level.

This commit addresses these issues and simultaneously completely
revises logging within the Spring TestContext Framework (TCF).

- Numerous log statements are now logged at TRACE level instead of
  DEBUG.

- Numerous log statements now have two modes. When logging at TRACE
  level, fully qualified class names (or the results of invoking
  toString() on related components) are included. When logging at DEBUG
  level, simple names of classes are logged and the results of invoking
  toString() on related components are omitted.

- toString() implementations in TCF components are now based on the
  newly introduced SimpleValueStyler for ToStringCreator.

The combination of the above changes greatly reduces the amount of
DEBUG logging output in the TCF, but users can still access complete
details by switching to TRACE level logging.

Closes gh-29229
2022-10-25 17:43:07 +02:00
Sam Brannen f16366e161 Introduce SimpleValueStyler for use with ToStringCreator
DefaultValueStyler hard codes conventions for styling that are verbose
and do not align well with standard toString() implementations in the
JDK for arrays, collections, and maps. Furthermore, the default styling
for classes and methods may not be suitable or desirable for certain
use cases.

To address these shortcomings, this commit introduces a
SimpleValueStyler for use with ToStringCreator. The default behavior of
SimpleValueStyler aligns with toString() implementations for arrays,
collections, and maps in the JDK, and styling for classes and methods
is configurable via a dedicated constructor.

Closes gh-29381
2022-10-25 17:42:19 +02:00
Sam Brannen 388f7bffcb Make DefaultValueStyler extensible
The `style(Object)` method in DefaultValueStyler delegates to several
internal methods. Prior to this commit those methods were private,
which prevented users from extending DefaultValueStyler without
rewriting most of the functionality.

This commit addresses this by making those methods protected so that
DefaultValueStyler can be extended. In addition, this commit introduces
protected methods for styling null, strings, classes, methods, and
objects that are not covered by any of the other style*() methods.

Closes gh-29380
2022-10-25 17:40:09 +02:00
Sam Brannen 7f4dbdb280 Polish DefaultValueStylerTests 2022-10-25 17:35:39 +02:00
Sam Brannen 5070604d4e Polish ToStringCreatorTests 2022-10-25 15:25:11 +02:00
rstoyanchev 5aeafc0761 Fix ISE in [Http|RSocket]ServiceProxyFactory
Closes gh-29376
2022-10-25 12:27:53 +01:00
Sébastien Deleuze 386d83545d Register proxy hints for HttpExchange annotations
Close gh-29271
2022-10-25 10:44:16 +02:00
Sébastien Deleuze e5b05586a3 Register reflection hints for HttpExchange annotations
See gh-29271
2022-10-25 10:44:16 +02:00
rstoyanchev d76953c166 Merge branch '5.3.x' 2022-10-24 11:11:59 +01: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
Sébastien Deleuze a1bc539d80 Support multiple @ImportRuntimeHints in the type hierarchy
This commit copies and adapts the logic from
DefaultListableBeanFactory#findMergedAnnotationOnBean
private method to make it suitable for returning multiple
annotations found in the type hierarchy in order
to support this use case with @ImportRuntimeHints.

Closes gh-29361
2022-10-24 10:56:30 +02:00
Brian Clozel 13c0c242b3 Revert "Revisit resource cleanup in ClientHttpRequestFactory"
Closes gh-29370
2022-10-24 10:52:07 +02:00
Brian Clozel 5e808ad018 Merge branch '5.3.x' 2022-10-21 15:24:08 +02: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
Sébastien Deleuze 6dd3fb1411 Merge branch '5.3.x' 2022-10-21 09:38:03 +02:00
Mikk Raudvere 12cc8a9f07 Fix typos
Closes gh-29364
2022-10-21 09:35:38 +02:00
Sam Brannen 53f513f90c Suppress deprecation warnings in tests 2022-10-20 16:57:40 +02:00
Brian Clozel fcbd5ec80a Avoid NPEs in DefaultServerRequestObservationConvention
In some cases, the default response status of a `ServerWebExchange` can
be `null`, especially when the response is not available or the server
implementation does not set a default response status.
This commit ensures that the status code is available when deriving
`KeyValue` information from it, or uses a fallback value for the key
value.

Fixes gh-29359
2022-10-20 14:31:41 +02:00
Stephane Nicoll e749cd1ef1 Add constructor introspection hint on Configuration class target
See gh-29358
2022-10-20 12:33:05 +02:00
Brian Clozel 7e0a039291 Add ServerWebExchange getter in WebFlux Observation context
The observation context relies on request and response for propagation,
but the exchange itself holds attributes and locale context so this is
needed for keyvalues extraction in general.

This commit adds a getter to expose the exchange from the context.
2022-10-20 11:13:36 +02:00
Stephane Nicoll 68246dc72c Initiate Ahead of Time chapter
See gh-29350
2022-10-20 10:13:05 +02:00
Juergen Hoeller 5ff5553878 Adapted test for reflection hints on proxied user classes
See gh-29335
2022-10-20 09:35:57 +02:00
Juergen Hoeller f6708d194c Expose all public user class methods (including inherited methods) for reflection
Also removes declared constructors hint for user classes which should not be necessary.

See gh-29335
2022-10-20 09:32:55 +02:00
Phillip Webb f93fda2a95 Guard against no-op observation
Update `ServerHttpObservationFilter` to check if the `Observation`
is a no-op before adding the `ServerRequestObservationContext`.

Prior to this commit, if the `Observation` is a no-op then the
context type added with the `CURRENT_OBSERVATION_CONTEXT_ATTRIBUTE`
would not be a `ServerRequestObservationContext`. This would mean
that `findObservationContext` would throw a `ClassCastException`.

Fixes gh-29356
2022-10-19 16:01:09 -07:00
Sébastien Deleuze 0889e47608 Upgrade to GraalVM 22.3 and introduce PreComputeFieldFeature
This new GraalVM feature replaces ConstantFieldFeature and
introduces various enhancements:
 - Leverage the new FieldValueTransformer API
 - Use GraalVM 22.3 graal-sdk dependency instead of svm one
 - Avoid using internal GraalVM APIs
 - No need to configure JPMS exports
 - Directly integrated in spring-core module
 - Simplified build configuration

Closes gh-29081
Closes gh-29080
Closes gh-29089
2022-10-19 20:35:54 +02:00
Johnny Lim ba99672fd6 Suppress removal warnings
Closes gh-29325
2022-10-19 18:44:59 +02:00
Juergen Hoeller aaa22ad07d Remove square brackets with index/key expressions from generated SQL
See gh-27925
2022-10-19 18:23:49 +02:00
Stephane Nicoll affccba8f1 Simplify AOT contribution for scoped proxies
This commit makes sure that a `ScopedProxyFactoryBean` is exposed in the
container, rather than its underlying proxy. Previously, any lifecycle
method that the proxy target exposed were invoked in the container.

This is a complementary fix to gh-29335
2022-10-19 17:25:35 +02:00
Juergen Hoeller 7f1990e64e Merge branch '5.3.x' 2022-10-19 16:27:03 +02:00
rstoyanchev d4f7484252 Add Builder to RSocketServiceProxyFactory
RSocketServiceProxyFactory now support programmatic initialization
through a builder, while bean-style initialization is deprecated.

Closes gh-29296
2022-10-19 14:36:45 +01:00
Juergen Hoeller 4c38777064 Explain logger name semantics (see AbstractTraceInterceptor.setLoggerName)
See gh-28678
2022-10-19 14:49:27 +02:00
rstoyanchev bd59c7a691 Polishing contribution
Closes gh-29310
2022-10-19 13:22:38 +01: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
Violeta Georgieva 997d1b3d7e Enable leak detection in Netty 5 tests
See gh-29310
2022-10-19 12:07:40 +01:00
Brian Clozel 57bbc09fca Do not set response status in ServerHttpObservationFilter
Prior to this commit, the `ServerHttpObservationFilter` would set the
response status (and possibly overwrite it) in case an exception is
found as an attribute.
While the exception itself should be used in the observation, the filter
should have no side effect on the response.

Fixes gh-29353
2022-10-19 12:11:00 +02:00
Arjen Poutsma f99c02fc94 Upgrade to Jackson 2.14.0-rc2
This commit upgrades Jackson to 2.14.0-rc2, and uses the new
ByteBufferFeeder in Jackson2Tokenizer.

Unfortunately, because of https://github.com/FasterXML/jackson-core/issues/478,
we had to change the CompilerConventions to suppress class file warnings.

Closes gh-29343
2022-10-19 11:05:40 +02:00
Sébastien Deleuze aa776e40f9 Ensure classpath checks can be evaluated at build-time
Closes gh-29352
2022-10-19 10:49:11 +02:00
Juergen Hoeller 6b6cf1b4a2 Avoid decorated definition bypass for scoped proxy determination
GenericApplicationContext registers proxy hints without any SmartInstantiationAwareBeanPostProcessor involved as well.

Closes gh-29335
2022-10-19 09:55:47 +02:00
Johnny Lim 5dca43ebd6 Use KeyValue.NONE_VALUE where possible
See https://github.com/micrometer-metrics/micrometer/issues/3458

Closes gh-29342
2022-10-19 09:32:57 +02:00
Juergen Hoeller b7ee7975dc Merge branch '5.3.x'
# Conflicts:
#	build.gradle
#	spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java
#	spring-jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterUtilsTests.java
#	spring-r2dbc/src/main/java/org/springframework/r2dbc/core/NamedParameterUtils.java
#	spring-r2dbc/src/test/java/org/springframework/r2dbc/core/NamedParameterUtilsUnitTests.java
2022-10-18 23:11:06 +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
Sébastien Deleuze e0129a3631 Register reflection hints for JPA persistence callbacks
Closes gh-29348
2022-10-18 22:52:47 +02:00
Juergen Hoeller d4fac82d68 Preserve square brackets for index/key expressions
Closes gh-27925
2022-10-18 22:39:53 +02:00
Phillip Webb 327eec09ae Allow TestCompiler DynamicClassLoader to resolve '.class' resources
Update `DynamicClassLoader` so that `findResource(...)` also considered
compiled class bytecode.

Closes gh-29347
2022-10-18 11:14:57 -07:00
Juergen Hoeller d17cdf98bb Restore directory matching (explicitly excluding root path itself)
Closes gh-29333
2022-10-18 19:29:29 +02:00
Sébastien Deleuze d89865ad67 Check @RegisterReflectionForBinding specifies at least one class
Closes gh-29346
2022-10-18 19:07:54 +02:00
Sébastien Deleuze 03039fcc00 Refine @RegisterReflectionForBinding Javadoc
Provide a better Javadoc to clarify that @RegisterReflectionForBinding
should annotate a bean and that the types where reflection is needed
should be specified in the annotation attributes.

Closes gh-29345
2022-10-18 19:07:54 +02:00
Juergen Hoeller a3a48a241c Disable array allocation in case of no constructor resolution
Closes gh-28808
2022-10-18 18:59:37 +02:00
Juergen Hoeller 311048726e Upgrade to Derby 10.16
Closes gh-29344
2022-10-18 18:29:15 +02:00
Stephane Nicoll 82a0154bd1 Expose a system property when AOT processing is running
This commit exposes a "spring.aot.processing" system property when the
AOT engine is running. This can be used by code that need to react
differently when the application is being refreshed for AOT processing.

Closes gh-29340
2022-10-18 18:18:43 +02:00
Sam Brannen 004875670b Merge branch '5.3.x'
# Conflicts:
#	spring-core/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java
2022-10-18 18:00:44 +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
Sam Brannen eadb003a8d Introduce builder API for AOT processor Settings
Closes gh-29341
2022-10-18 16:33:16 +02:00
Juergen Hoeller cb44e09694 Merge branch '5.3.x' 2022-10-18 16:24:35 +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
Stephane Nicoll 6d688e196d Restore support of list of inner bean definitions
This commit restores the support of multiple bean definitions being
specified in a `List` as a property value or constructor argument.

Rather than handling inner bean definitions externally, there are now
supported by BeanDefinitionPropertiesCodeGenerator, and list of such
type is handled transparently.

Closes gh-29075
2022-10-18 15:28:18 +02:00
Sam Brannen 6bdf0bcc4a Introduce ApplicationContextFailureProcessor SPI in the TCF
This commit introduces an ApplicationContextFailureProcessor SPI in the
Spring TestContext Framework that allows third parties to process
failures that occur while a SmartContextLoader attempts to load an
ApplicationContext.

SmartContextLoader implementations must introduce a try-catch block
around the loading code and throw a ContextLoadException that wraps
the failed ApplicationContext and the cause of the failure.

Extensions of AbstractTestContextBootstrapper can configure an
ApplicationContextFailureProcessor by overriding the new protected
getApplicationContextFailureProcessor() method.

DefaultCacheAwareContextLoaderDelegate unwraps any ContextLoadException
and delegates to the configured ApplicationContextFailureProcessor for
processing.

Closes gh-28826
2022-10-18 14:40:35 +02:00
Sam Brannen 19f795a75a Suppress deprecation warnings in tests 2022-10-18 14:31:57 +02:00
Sam Brannen bfdf070232 Suppress deprecation warnings in tests 2022-10-18 14:21:57 +02:00
Sam Brannen b2cf2b9d48 Remove unused logger field 2022-10-18 14:19:45 +02:00
Sam Brannen 9dfa46f690 Remove GraalVM workaround in PathMatchingResourcePatternResolver
Tested successfully using the following locally built GraalVM dev build.

OpenJDK Runtime Environment GraalVM 22.3.0-dev (build 17.0.5+5-jvmci-22.3-b07)

Closes gh-29214
2022-10-18 14:18:05 +02:00
Stephane Nicoll ca5e453f87 Merge pull request #29313 from izeye
* pr/29313:
  Make RestTemplate.createResourceAccessException() private

Closes gh-29313
2022-10-18 13:06:25 +02:00
Johnny Lim d0a99c15c4 Make RestTemplate.createResourceAccessException() private
See gh-29313
2022-10-18 13:05:25 +02:00
Stephane Nicoll d19f63fc2b Merge pull request #29326 from izeye
* pr/29326:
  Add missing since on setCurrentlyInvokedFactoryMethod()

Closes gh-29326
2022-10-18 13:03:40 +02:00
Johnny Lim 1ea3f49eba Add missing since on setCurrentlyInvokedFactoryMethod()
See gh-29326
2022-10-18 13:03:13 +02:00
Juergen Hoeller f4dfe94702 Fallback to ISO-based default java.time type parsing
Closes gh-26985
2022-10-18 12:49:14 +02:00
Sébastien Deleuze 3d83db6abb Mention @ImportRuntimeHints in RuntimeHintsRegistrar Javadoc
Closes gh-29337
2022-10-18 12:24:46 +02:00
Johnny Lim 7df8b59a7f Polish "Reorganize HTTP Observation types"
See gh-29334
2022-10-18 09:11:07 +09:00
Brian Clozel 001b2636d6 Reorganize HTTP Observation types
Closes gh-29334
2022-10-17 21:54:53 +02:00
Sam Brannen 4d44aaf81b Omit deprecation warning for Bean Validation constraint annotations
Prior to this commit, AnnotationTypeMapping logged a warning for the use
of convention-based annotation attribute overrides in composed Bean
Validation constraint annotations, even though those attribute overrides
are not related to Spring.

For example, Hibernate's @URL constraint annotation is meta-annotated
with Bean Validation's @Pattern constraint annotation, and we should not
log a warning in such scenarios.

This commit addresses that by not logging a warning if convention-based
annotation attribute overrides are detected for a composed @Constraint
annotation.

Closes gh-29206
2022-10-17 19:39:02 +02:00
Sam Brannen 0e861af050 Log warning for convention-based attribute overrides once per annotation type
See gh-28760, gh-29206
2022-10-17 16:52:17 +02:00
rstoyanchev 5cb3af708c Add Builder to HttpServiceProxyFactory
HttpServiceProxyFactory now support programmatic initialization through
a builder, while bean-style initialization is deprecated.

See gh-29296
2022-10-17 12:23:58 +01:00
Juergen Hoeller e03abc94ff Merge branch '5.3.x'
# Conflicts:
#	spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java
#	spring-beans/src/main/java/org/springframework/beans/PropertyDescriptorUtils.java
#	spring-beans/src/main/java/org/springframework/beans/SimpleBeanInfoFactory.java
#	spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
2022-10-17 12:56:19 +02:00
Sébastien Deleuze 69cb68f7d6 Add Kotlin data class components support to BindingReflectionHintsRegistrar
Closes gh-29316
2022-10-17 12:26:45 +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 581fa1419f Merge branch '5.3.x' 2022-10-16 20:32:52 +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
Johnny Lim eeebea1da3 Replace StringBuffer with StringBuilder in CGLIB fork 2022-10-14 18:45:08 +02:00
Juergen Hoeller b796b52d4e Extract SimpleBeanInfo adaptation into internal SimpleBeanInfoFactory
See gh-29320
2022-10-14 12:34:43 +02:00
Juergen Hoeller bba313c2f5 Perform basic property determination without java.beans.Introspector
Closes gh-29320
2022-10-13 19:02:45 +02:00
rstoyanchev 113db2fb2f Fix regression in AbstractJackson2Decoder
Closes gh-29307
2022-10-13 15:45:25 +01:00
Yanming Zhou 19cbba6b34 Use correct RFC number for ProblemDetail support in Javadoc
Closes gh-29302
2022-10-13 16:16:41 +02:00
Stephane Nicoll ba0a835880 Merge branch '5.3.x' 2022-10-13 11:29:49 +02:00
Stephane Nicoll 3f42d4de43 Upgrade Ubuntu version in CI image 2022-10-13 11:29:31 +02:00
Arjen Poutsma ce03980fb4 Mark HttpRequest::getMethodValue and ClientHttpResponse::getRawStatusCode for removal 2022-10-12 16:29:14 +02:00
Arjen Poutsma 2c58eea781 Mark HttpMethod::resolve for removal 2022-10-12 15:32:51 +02:00
Stephane Nicoll fadf69fb68 Merge pull request #29308 from izeye
* pr/29308:
  Upgrade to Dokka 1.7.20

Closes gh-29308
2022-10-12 14:45:29 +02:00
Johnny Lim 8d3a1b4c9c Upgrade to Dokka 1.7.20
See gh-29308
2022-10-12 14:39:05 +02:00
Juergen Hoeller 02979efb2c Upgrade to Netty 4.1.84 2022-10-12 09:38:51 +02:00
Juergen Hoeller 7025c3bbd4 Upgrade to ASM 9.4
Closes gh-29305
2022-10-12 08:32:42 +02:00
Sam Brannen 313b53a62a Merge branch '5.3.x' 2022-10-11 20:50:33 +02:00
Sam Brannen 5ac687f4aa Add warning to AnnotatedElementUtils.getMergedRepeatableAnnotations()
See gh-20279
2022-10-11 20:49:19 +02:00
Sam Brannen 0ed3a46a2a Merge branch '5.3.x' 2022-10-11 19:39:20 +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 48a9fd815f Merge branch '5.3.x' 2022-10-11 18:11:29 +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
rstoyanchev 141e735b18 Upgrade to Reactor 2022.0.0-RC1
Closes gh-29268
2022-10-11 16:55:13 +01:00
Sam Brannen 65ab67ef2b Merge branch '5.3.x' 2022-10-11 17:36:08 +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
rstoyanchev 6c3a7192b7 Add classpath check for context-propagation
See gh-29056
2022-10-11 15:53:46 +01:00
Sam Brannen 965dd66f8c Improve Javadoc for RepeatableContainers 2022-10-11 16:41:19 +02:00
Arjen Poutsma dedcb19f44 Document PartEvent API
Closes #29170
2022-10-11 16:28:41 +02:00
rstoyanchev cf2b1020f4 Update table of supported controller method return types
Closes gh-28814
2022-10-11 15:10:30 +01:00
rstoyanchev 04f0f1ddb0 Update table of supported controller method return types
See gh-27052
2022-10-11 14:38:38 +01:00
Juergen Hoeller bba66429fb Polishing 2022-10-11 15:35:25 +02:00
Juergen Hoeller 0f8ca805e1 Move hints to dedicated top-level package (avoiding aot<->support cycle)
See gh-29026, gh-29069
2022-10-11 15:34:30 +02:00
Juergen Hoeller 4bb2e23239 Resolve CGLIB core<->transform package cycle
See gh-28955
2022-10-11 15:34:07 +02:00
Stephane Nicoll 45939720f2 Add native support for @ExceptionHandler
This commit makes sure that `@ExceptionHandler`-annotated methods can be
invoked via reflection in a native image. As most of the handling of
the parameter and the return type is shared with our generic
RequestMapping handling, the ReflectiveProcessor extends from it.

An `@ExceptionHandler`-annotated method can return a `ProblemDetail`. If
that's the case, reflection entries are contributed.

Closes gh-29297
2022-10-11 10:18:23 +02:00
Juergen Hoeller c94b676576 Specifically handle "java."/"javax." packages in SpringNamingPolicy
Closes gh-27622
2022-10-10 21:50:26 +02:00
Brian Clozel fbb8cdb948 Upgrade to Context Propagation 1.0.0-RC1
Closs gh-29273
2022-10-10 21:34:09 +02:00
Brian Clozel ac8c36a5c8 Upgrade to Micrometer 1.10.0-RC1
Closes gh-29241
2022-10-10 21:32:53 +02:00
Johnny Lim d4a08dae43 Fix typos in CorsConfiguration[Tests]
Closes gh-29292
2022-10-10 19:27:41 +02:00
Sam Brannen f00e4b230f Support method chaining in AbstractAotProcessor.Settings
See gh-29266
2022-10-10 19:09:41 +02:00
Sam Brannen 7ed42ca4ca Polish ContextAotProcessor 2022-10-10 18:58:27 +02:00
Sam Brannen cad7444afa Introduce Settings container in AbstractAotProcessor
See gh-29266
2022-10-10 18:58:27 +02:00
Sébastien Deleuze 7b4ff5ea74 Make BindingReflectionHintsRegistrar protected methods private
In order to keep the maximum of flexibility, this commit makes
shouldSkipType and shouldSkipMembers methods private.

That will allow for example to refactor
BindingReflectionHintsRegistrar in order to support skipping
custom classes specified via @RegisterReflectionForBinding
without having to subclass it.

See gh-29279
2022-10-10 18:18:36 +02:00
Stephane Nicoll 4eca87baa3 Handle hints for CGLIB proxies consistently
This commit makes sure that hints are registered for CGLIB proxies even
if the proxy itself is not created. This typically happens when AOT runs
on an existing classpath, and a previous run already created the proxy.

Closes gh-29295
2022-10-10 17:39:26 +02:00
Stephane Nicoll e8ce86a6f0 Relocate testfixtures 2022-10-10 17:36:11 +02:00
Juergen Hoeller a1daaf0c19 Revise CGLIB naming policy to only contain SpringCGLIB label once
See gh-29295
2022-10-10 17:34:31 +02:00
Sam Brannen de609e5d45 Polishing 2022-10-10 16:52:22 +02:00
Juergen Hoeller 26c6a742d9 Introduce setLoadedClassHandler method on CGLIB ReflectUtils
See gh-29295
2022-10-10 16:49:55 +02:00
Sam Brannen b2b3163fae Redesign AOT processors for consistency and simplification
There's currently a considerable amount of overlap between the
implementations of AotProcessor and TestAotProcessor. In addition
AotProcessor is abstract and does not include a main() method; whereas,
TestAotProcessor is concrete and does include a main() method.

To address these issues, this commit:

- Introduces an AbstractAotProcessor base class that AotProcessor and
  TestAotProcessor now both extend

- Moves common properties/functionality to AbstractAotProcessor

- Renames AotProcessor to ContextAotProcessor

- Makes TestAotProcessor abstract like ContextAotProcessor

- Removes the main() method from TestAotProcessor

Closes gh-29266
2022-10-10 16:27:04 +02:00
Stephane Nicoll 061fa475ee Avoid generated code in the javax package
This commit updates the existing logic to also exclude code generation
in the javax package.

Closes gh-29123
2022-10-10 15:09:00 +02:00
Stephane Nicoll 76e87ad475 Polish 2022-10-10 15:09:00 +02:00
Sam Brannen 34e5aac0f5 Reintroduce factory method name in exception thrown from SimpleInstantiationStrategy 2022-10-10 14:28:35 +02:00
Arjen Poutsma 8227032a0f Improve exception message if MultipartParser can not find end of body
This commit improves the exception message thrown by MultipartParser
when it cannot find the end of the multipart body, by showing in the
message what the parser is looking for (CRLF--<boundary>).

Closes gh-28067
2022-10-10 13:26:46 +02:00
Sébastien Deleuze 8ed1906f43 Refine SQLErrorCodesFactory reachability on native images
SQLErrorCodeSQLExceptionTranslator#USER_PROVIDED_ERROR_CODES_FILE_PRESENT
evaluation at build time combined with the lazy
SQLErrorCodesFactory#instance initialization allow to
avoid making SQLErrorCodesFactory constructor reachable
when no custom sql-error-codes.xml is provided.

Closes gh-29294
2022-10-10 12:11:19 +02:00
Sébastien Deleuze 42c3ac64ff Remove spring.spel.ignore and spring.xml.ignore flags
This commit also removes ResourcePropertiesPersister which
was introduced in 5.3 specifically for spring.xml.ignore
flag and which is expected to be used only internally by
Spring Framework. DefaultPropertiesPersister should be used
instead.

Closes gh-29277
2022-10-10 12:11:19 +02:00
Sam Brannen bca35dc0a2 Generate direct mappings from AOT initializers to test classes
See gh-29289
2022-10-10 12:09:17 +02:00
Arjen Poutsma 3e33912624 Deprecate streaming mode in DefaultPartHttpMessageReader
This commit deprecates the streaming mode of
DefaultPartHttpMessageReader, in favor of PartEvent and
PartEventHttpMessageReader.

Closes gh-29293
2022-10-10 11:49:30 +02:00
Sam Brannen be70b675c6 Polishing 2022-10-10 11:01:04 +02:00
Sam Brannen 69e4cc5576 Ensure context caching works properly during AOT runtime in the TCF
Prior to this commit, the AOT runtime support in the Spring TestContext
Framework (TCF) relied on the MergedContextConfiguration for a given
test class being the same as during the AOT processing phase. However,
this is not always the case. For example, Spring Boot "disables"
selected `ContextCustomizer` implementations during AOT runtime
execution.

See https://github.com/spring-projects/spring-boot/commit/0f325f98b5f0ad07d404a41cc172ad33879a8ecf

To address that, this commit ensures that context caching works
properly during AOT runtime execution even if the
MergedContextConfiguration differs from what was produced during the
AOT processing phase. Specifically, this commit introduces
AotMergedContextConfiguration which is a MergedContextConfiguration
implementation based on an AOT-generated ApplicationContextInitializer.

AotMergedContextConfiguration wraps the MergedContextConfiguration
built during AOT runtime execution.

Interactions with the ContextCache are performed using the
AotMergedContextConfiguration; whereas, the ApplicationContext is
loaded using the original MergedContextConfiguration.

This commit also introduces a ContextCustomizerFactory that emulates
the ImportsContextCustomizerFactory in Spring Boot's testing support.
BasicSpringJupiterImportedConfigTests uses @Import to verify that the
context customizer works, and AotIntegrationTests has been updated to
execute BasicSpringJupiterImportedConfigTests after test classes whose
MergedContextConfiguration is identical during AOT runtime execution.
Without the fix in this commit, BasicSpringJupiterImportedConfigTests
would fail in AOT runtime mode since its ApplicationContext would be
pulled from the cache using an inappropriate cache key.

Closes gh-29289
2022-10-09 16:17:43 +02:00
Sam Brannen cfa95c793b Ensure MergedContextConfigurationRuntimeHints is invoked once per config 2022-10-09 15:16:42 +02:00
Sam Brannen d4a5565340 Enable default TestExecutionListeners in JUnit 4 and TestNG base test classes
Prior to this commit, the abstract base test classes for JUnit 4 and
TestNG registered explicit sets of TestExecutionListeners. This
configuration was useful in the early years of the Spring TestContext
Framework. However, since the introduction of support for automatic
registration of "default" listeners in Spring Framework 4.1, these
predefined sets of TestExecutionListeners have become a hindrance to
using Spring's testing support with default listeners from Spring
portfolio projects (such as Spring Boot and Spring Security) as well as
third-party or project-specific default listeners.

To address this issue, the four abstract base test classes for JUnit 4
and TestNG no longer declare listeners via @TestExecutionListeners and
instead now rely on registration of default listeners.

Closes gh-29149
2022-10-08 16:30:07 +02:00
Sam Brannen 3061a81b0f Merge branch '5.3.x' 2022-10-08 16:21:30 +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 afd0443204 Merge branch '5.3.x'
# Conflicts:
#	spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeResult.java
2022-10-08 16:03:52 +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 371fd06ae2 Use AssertJ static imports consistently in main
Closes gh-29282
2022-10-08 14:07:27 +02:00
Sam Brannen ae368a20b8 Merge branch '5.3.x'
# Conflicts:
#	spring-web/src/test/kotlin/org/springframework/http/codec/json/KotlinSerializationJsonDecoderTests.kt
#	spring-web/src/test/kotlin/org/springframework/http/codec/json/KotlinSerializationJsonEncoderTests.kt
2022-10-08 14:06:41 +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 c98ed17728 Polishing 2022-10-08 13:43:09 +02:00
Johnny Lim ced37d53b4 Polishing
Closes gh-29284
2022-10-08 13:43:09 +02:00
Sam Brannen c1ff812d84 Disable flaky ReactorNetty2StompBrokerRelayIntegrationTests
See gh-29287
2022-10-08 13:43:09 +02:00
rstoyanchev 16ea4692ba Drop Servlet 4 classpath check 2022-10-07 18:14:41 +01:00
rstoyanchev 1afc1fc90d Fix regression in AbstractJackson2Encoder
Closes gh-29274
2022-10-07 18:14:41 +01:00
Sam Brannen b3afafbf5a Merge branch '5.3.x' 2022-10-07 18:02:25 +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
Sébastien Deleuze a9cd45e7f2 Improve BindingReflectionHintsRegistrar extensibility
This commit introduces a shouldSkipType(Class<?> type) method
and changes shouldRegisterMembers(Class<?> type) to
shouldSkipMembers(Class<?> type).

Closes gh-29279
2022-10-07 17:50:15 +02:00
Sébastien Deleuze bbe285dd42 Polish RegisterReflectionForBinding support
Implementation and Javadoc refinements.

See gh-29279
2022-10-07 17:50:15 +02:00
Sam Brannen 1d052742d1 Throw IOException in FileSystemResource.getURI() for consistency
See gh-29275
2022-10-07 17:06:54 +02:00
Sam Brannen 72307bbb20 Polish contribution
See gh-28549
2022-10-07 16:35:55 +02:00
hebo 2434470457 Optimize SpEL and property placeholder support for @Async qualifiers
See gh-27818
Closes gh-28549
2022-10-07 16:22:18 +02:00
Sam Brannen 64412907f7 Merge branch '5.3.x'
# Conflicts:
#	spring-test/src/main/java/org/springframework/test/util/AopTestUtils.java
2022-10-07 16:12:21 +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 0985da23f9 Fix WebMvcConfigurationSupportTests due to change in previous commit 2022-10-07 14:15:41 +02:00
Sam Brannen 3138001391 Allow spring-webmvc to be imported into Eclipse IDE again 2022-10-07 14:12:45 +02:00
Sam Brannen ba42deb7db Remove obsolete code 2022-10-07 14:12:04 +02:00
Sam Brannen 66989434b4 Introduce unit tests for gh-29275 2022-10-07 14:02:11 +02:00
Sam Brannen 23b3fc7f3c Polish FileSystemResource 2022-10-07 14:01:07 +02:00
Sam Brannen 7175c4ca9a Normalize URIs returned from FileSystemResource.getURI()
Prior to this commit, if a FileSystemResource was created from a
java.nio.file.Path or java.nio.file.FileSystem, the URI returned from
getURI() was based on the semantics of Path#toUri() which always
includes the "authority component" (i.e., "//") after the scheme (e.g.,
"file://..."). In contrast, if a FileSystemResource is created from a
java.io.File or String, the URI returned from getURI() never includes
the "authority component" due to the semantics of File#toURI().

Consequently, invoking myFileSystemResource.getURI().toString() could
result in "file:/my/path" or "file:///my/path", depending on how the
FileSystemResource was created.

This behavior is not new; however, recent changes in
PathMatchingResourcePatternResolver -- which result in a
FileSystemResource being created from a java.nio.file.Path instead of
from a java.io.File -- make this difference more noticeable to users
and may in fact surface as a breaking change.

To address that issue, this commit revises the implementation of
FileSystemResource.getURI() by normalizing any `file:` URIs that it
returns. Effectively, URIs like "file:///my/path" will now take the
form "file:/my/path".

See gh-29163
Closes gh-29275
2022-10-07 13:27:08 +02:00
Sam Brannen af617c7da9 Disable failing test until gh-29275 is addressed 2022-10-07 12:40:55 +02:00
Sam Brannen c405e742f4 Merge branch '5.3.x'
# Conflicts:
#	spring-core/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java
2022-10-07 12:39:24 +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
Stephane Nicoll 635534c1ad Describe naming conventions of GeneratedMethods#add
Closes gh-28997
2022-10-07 12:05:57 +02:00
Stephane Nicoll c74760540d Polish 2022-10-07 11:42:55 +02:00
Sam Brannen 3dc60f1627 Backport changes to PathMatchingResourcePatternResolverTests 2022-10-07 11:01:02 +02:00
Brian Clozel ca88eeb1ae Start building against Context Propagation 1.0.0 SNAPSHOTs 2022-10-07 08:38:14 +02:00
Stephane Nicoll a16afe8e10 Describe the replacement use case for BeanRegistrationAotProcessor
Closes gh-29126
2022-10-06 16:42:17 +02:00
Juergen Hoeller 6027be5a39 Ignore overridden factory methods for unique candidate resolution
See gh-27920
2022-10-06 15:06:53 +02:00
Brian Clozel 455a736a01 Switch to Micrometer 1.10.0-SNAPSHOT
See gh-29241
2022-10-06 14:08:07 +02:00
Brian Clozel 6b0f6e9f27 Apply Gradle Test Retry plugin
The plugin is configured to detect flaky tests and retry them 3 times
when running on the CI, but still reports failures. This will provide a
standard way to detect flaky tests as failures and successful attempts
are shown in the tests report.
2022-10-06 13:54:28 +02:00
Iain Henderson b8243e6f84 Support CBOR and Protobuf with Kotlin Serialization
This commit introduces support for CBOR and Protobuf using Kotlin
serialization. Support comes in the form of Encoder/Decoder as well
as HttpMessageConverters. Seperate abstract base classes supply support
for binary and string (de)serialization.

The exising JSON codecs and message converters have been migrated to
use the new base classes.

Closes gh-27628
2022-10-06 13:51:50 +02:00
rstoyanchev b6c2e8de23 Support context propagation for Spring MVC controllers
Closes gh-29056
2022-10-06 12:43:54 +01:00
rstoyanchev d581d48d24 Polishing ResponseBodyEmitterReturnValueHandlerTests 2022-10-06 12:43:54 +01:00
Stephane Nicoll 0d5c78d992 Polish 2022-10-06 13:33:58 +02:00
Juergen Hoeller 2a1807895e Upgrade to Tomcat 10.1 in web tests
Adapting to FileUpload API change: no FileItemFactory constructor argument anymore.
2022-10-06 12:33:56 +02:00
Juergen Hoeller 326335f903 Upgrade to Tomcat 10.1
Includes Jetty 11.0.12, Hibernate ORM 5.6.12, HtmlUnit 2.65
2022-10-06 12:09:05 +02:00
Juergen Hoeller b45a48461f Polishing 2022-10-06 12:03:25 +02:00
Juergen Hoeller aedef9321a Merge AOT constructor and factory method resolution into ConstructorResolver
This moves related code into the same class, unifies candidate determination for constructors and factory methods, and gets rid of the package cycle around the hard-coded Autowired annotation check (which is implicitly coming from AutowiredAnnotationBeanPostProcessor via the determineCandidateConstructors SPI now). The API entry point for AOT pre-resolution purposes is in RegisteredBean.

Closes gh-27920
2022-10-06 11:59:11 +02:00
Juergen Hoeller 3af0c232b7 ProxyFactoryBean determines actual proxy class in getObjectType()
AopProxy implementations accept empty Advisor chains for early proxy class creation.

Closes gh-29097
2022-10-06 11:54:06 +02:00
Stephane Nicoll efaee61f31 Harmonize accessors of RuntimeHints API
Closes gh-29269
2022-10-06 09:36:17 +02:00
rstoyanchev ffe2ba4c7b Undo constructor deprecation + polishing 2022-10-05 20:04:39 +01:00
Sam Brannen 30f1eee4d0 Polish Javadoc and implementation of ClassPathResource 2022-10-05 20:24:17 +02:00
Sam Brannen 61cc7c0a93 Prepare TestAotProcessor to make it abstract and remove the main() method
See gh-29266
2022-10-05 20:03:52 +02:00
Sam Brannen 05d6c4c9b2 Polishing 2022-10-05 20:02:44 +02:00
Sam Brannen 647e811e47 Restructure AopTestUtilsTests 2022-10-05 19:13:51 +02:00
Sam Brannen 66395502db Polishing 2022-10-05 19:06:15 +02:00
Sam Brannen 26e485ce40 Make TestClassScanner package private again
TestClassScanner was made public with the assumption that Spring Boot's
AOT testing support might need to work directly with that class; however,
it turns out that Spring Boot does not currently have such a need.

In light of that, this commit restores TestClassScanner's visibility to
package private.
2022-10-05 19:06:15 +02:00
Sam Brannen 98801f8a5b Consistently declare RuntimeHints parameter 1st in test AOT APIs 2022-10-05 19:06:15 +02:00
Sam Brannen 935265048a Simplify TestRuntimeHintsRegistrar API
Prior to this commit, the TestRuntimeHintsRegistrar API combined
processing of MergedContextConfiguration and test classes. However, it
appears that only spring-test internals have a need for registering
hints based on the MergedContextConfiguration. For example, Spring
Boot's AOT testing support has not had such a need, and it is assumed
that third parties likely will not have such a need.

In light of that, this commit simplifies the TestRuntimeHintsRegistrar
API so that it focuses on processing of a single test class.

In addition, this commit moves the hint registration code specific to
MergedContextConfiguration to an internal mechanism.

Closes gh-29264
2022-10-05 18:37:06 +02:00
Sam Brannen 7ad65b8dff Allocate more memory to Checkstyle tasks 2022-10-05 17:06:12 +02:00
Sam Brannen 8869ca27b1 Ensure ClassPathResources with same path have same hash code
This commit aligns the hashCode() implementation in ClassPathResource
with the recent change to the logic in equals().

See gh-29263
2022-10-05 16:58:08 +02:00
Sam Brannen 1082119c50 Polishing 2022-10-05 16:49:38 +02:00
Sam Brannen a380ca2750 Ensure ClassPathResources with same path and ClassLoader are equal
Prior to this commit, if two ClassPathResource instances were
constructed differently (one from an absolute path and one from a path
relative to a Class) but had the same absolute path and the same
ClassLoader, they were effectively equal, but ClassPathResource#equals
returned false.

This commit addresses this by revising the logic in
ClassPathResource#equals accordingly.

Closes gh-29263
2022-10-05 16:27:02 +02:00
Sam Brannen 0aa9d9d535 Return URL-decoded file name from UrlResource#getFilename()
Prior to this commit, UrlResource#getFilename() returned the filename
of the resource URL-encoded which is in contrast to what
FileSystemResource#getFilename() returns for an equivalent resource.

In addition, users most likely expect that a filename returned from a
method defined in the Resource interface is unencoded.

This commit therefore revises UrlResource#getFilename() so that it
always returns the filename URL-decoded.

Closes gh-29261
2022-10-05 15:52:22 +02:00
Sam Brannen 084d7d1bdc Remove duplicate ClassPathResourceTests class 2022-10-05 15:52:22 +02:00
Sam Brannen 2e05137ff9 Polish PathResourceTests 2022-10-05 15:52:22 +02:00
Sam Brannen f0556b6004 Undeprecate PathResourceTests 2022-10-05 15:52:22 +02:00
rstoyanchev b08f185a0b Use MethodArgumentNotValidException for model attributes
Closes gh-29251
2022-10-05 14:02:42 +01:00
rstoyanchev 6b0f29a065 Document i8n for RFC 7807 problem details
Expand the documentation for error responses and add details on
using a MessageSource to customize and internationalize error details.

See gh-28814
2022-10-05 14:02:42 +01:00
rstoyanchev 75dea98811 Revise docs on RFC 7807
See gh-28814
2022-10-05 14:02:42 +01:00
rstoyanchev a4210854fb MessageSource support for Spring MVC and WebFlux exceptions
See gh-28814
2022-10-05 14:02:42 +01:00
Sébastien Deleuze ff81d64fb5 Add reflection hint for EmbeddedDataSourceProxy#shutdown
This commit adds a reflection hint on
EmbeddedDatabaseFactory$EmbeddedDataSourceProxy#shutdown when
EmbeddedDatabaseFactory is reachable in order to allow its usage
as bean destroy method.

Closes gh-29259
2022-10-05 14:08:09 +02:00
Brian Clozel 681cf0dae7 Provide full request URL for "http.url" keyvalue
Prior to this commit, the Observation filter for Servlet applications
would only use the request pathInfo as an "http.url" high cardinality
keyvalue. This commit ensures that we're using the full request URL as a
value there.

This also polishes gh-29254.

Fixes gh-29257
See gh-29254
2022-10-05 11:40:28 +02:00
Brian Clozel 7dd6afc263 Temporarily disable kotlin scripts tests with Java 19
See gh-29249
2022-10-05 10:04:24 +02:00
Brian Clozel 486a1b6024 Change keyvalue name to http.url in server observations
This commit changes the new high cardinality key value from
"uri.expanded" to "http.url" in order to align with the OTel
specification, since there is no need for backwards compatibility on
this new metadata.

Closes gh-29254
2022-10-05 09:55:42 +02:00
Stephane Nicoll 2f20d6322b Enable cglib proxy for configuration classes if necessary
This commit updates code generation to customize the instantiation of
a configuration class that requires a proxy. Rather than instantiating
the raw class, the proxy is used.

Closes gh-29107
2022-10-04 16:54:44 +02:00
Stephane Nicoll f2e9d112b1 Fix TypeReference#getName for CGLIB proxies
This commit makes sure that the double '$' sign typically used by
generated cglib proxies are not used as an inner class separator.

Closes gh-29252
2022-10-04 16:49:13 +02:00
Stephane Nicoll 9820e3341d Fix handling of protected visibility
Previously, InstanceSupplierCodeGenerator used reflection if the target
visibility is either protected or private, and use direct access if the
target visibility is public or package private.

The previous arrangement already assumed that the code is generateed in
the same package as the target type. This means that protected can be
used as well so this commit only use reflection if the target visibility
is private.

Closes gh-29253
2022-10-04 16:49:13 +02:00
Sam Brannen 1224be84ba Remove incorrect [@]since tags 2022-10-04 16:24:13 +02:00
Sam Brannen e284405e9a Delete unused code 2022-10-04 16:19:53 +02:00
Sam Brannen 5bff2c7341 Clean up warnings in tests 2022-10-04 16:19:37 +02:00
Sam Brannen 31d98bfd95 Ensure PathMatchingResourcePatternResolverTests run in native image
See inline comments in commit for details.

See gh-29243
2022-10-04 16:13:46 +02:00
Sam Brannen dd814b6d30 Test sub-paths in PathMatchingResourcePatternResolverTests
This commit introduces assertions that verify that the sub-path is
properly URL-decoded when a path contains `#`. The additional assertions
are necessary since the existing assertions use Resource#getFilename
which already implicitly decodes the path.

See gh-29243
2022-10-04 15:50:33 +02:00
Sébastien Deleuze 5c447bb7a4 Make ConstantFieldSubstitutionProcessor thread-safe
See gh-29250
2022-10-04 15:23:18 +02:00
Sam Brannen ddc7aef51b Merge branch '5.3.x'
# Conflicts:
#	spring-core/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java
2022-10-04 14:31:43 +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 2ce314d4dd Modify PathMatchingResourcePatternResolverTests so that it passes on main
See gh-29243
2022-10-04 13:22:44 +02:00
Sam Brannen 5b08bc29b1 Merge branch '5.3.x' 2022-10-04 13:21:30 +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 892b605460 Merge branch '5.3.x' 2022-10-04 13:09:44 +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
Juergen Hoeller 4a2b058b0a Enforce static initialization of CGLIB method proxies on attemptLoad
This propagates current Enhancer settings (naming strategy etc) to the method proxies.

See gh-29107
2022-10-04 12:24:09 +02:00
Sam Brannen 01025c8551 Merge branch '5.3.x'
# Conflicts:
#	spring-core/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java
2022-10-04 12:08:16 +02:00
Sam Brannen 7241c30141 Backport changes to PathMatchingResourcePatternResolverTests 2022-10-04 11:48:29 +02:00
Sébastien Deleuze 619b7bff17 Add ConstantReadableJavaField caching in ConstantFieldSubstitutionProcessor
Closes gh-29250
2022-10-04 11:03:48 +02:00
Brian Clozel 5613922fba Polish test
This test should not rely on a particular content-type as none is
defined on the producing end, not on the requesting end.
2022-10-04 10:09:07 +02:00
Brian Clozel 3b91eea0b7 Support parsing locales without country, with variant
Prior to this commit, the parsing algorithm in
`StringUtils#parseLocaleString` would skip empty tokens, turning
`en__VARIANT` into `en_VARIANT` when parsed.

This commit ensures that such cases are now supported and that more
invalid formats are rejected by the parser.

Fixes gh-29248
2022-10-03 22:44:09 +02:00
rstoyanchev 4d5b0c91a3 Polishing contribution
Closes gh-29247
2022-10-03 18:20:52 +01:00
Violeta Georgieva b5adae2086 Switch to Reactor Netty 2 snapshots
Update to Reactor BOM 2022.0.0-SNAPSHOT.
Process package changes.
Adapt to new `HttpHeaders` API.
Adapt to new cookies API.

See gh-29247
2022-10-03 18:20:52 +01:00
Juergen Hoeller 1b1682eacd Narrow early initialization of CGLIB method proxies (for AOT processing)
Do not trigger early initialization on Factory classes (e.g. AOP proxies)

See gh-29107
2022-10-03 18:00:57 +02:00
Stephane Nicoll 3b2b36d0b8 Allow AccessControl to determine visibility from a given type
This commit adapts AccessVisibility so that it can determine if the
member or type signature is accessible from a given package. This lets
implementers figure out if reflection is necessary without assuming that
package private visibility is OK.

Closes gh-29245
2022-10-03 17:56:19 +02:00
Sam Brannen df58c00bf5 Restore GraalVM native image resource scanning support
This commit restores support for the GraalVM native image file system
in PathMatchingResourcePatternResolver.

Closes gh-29226
2022-10-03 17:38:30 +02:00
Juergen Hoeller 51875cdf5f Defensive early initialization of CGLIB method proxies (for AOT processing)
Method proxies might not actually be used later on, so failure is not fatal.

See gh-29107
2022-10-03 16:43:43 +02:00
Juergen Hoeller 740d3d931a Restore Windows compatibility through streamlined Path API interaction
In addition to consistent use of cleaned file paths, this revision avoids FileSystem SPI interaction, resolving NIO Path instances from URI (and FileSystemResource from Path).

See gh-29226
2022-10-03 16:08:46 +02:00
Sam Brannen d79d2fc573 Ensure ClassPathResourceTests can pass on MS Windows 2022-10-03 15:34:45 +02:00
Brian Clozel 31a84fb38e Temporarily ignore tests until gh-29246 is re-applied
See gh-29246
2022-10-03 14:29:45 +02:00
Brian Clozel 054579a892 Temporarily revert gh-29246
This new hint contribution triggers a GraalVM bug and breaks native
compilation for several samples, we need to temporarily revert this
change until a fix is available in GraalVM.

See gh-29246
2022-10-03 14:14:57 +02:00
Brian Clozel ff9792bae0 Polish
See gh-29246
2022-10-03 14:14:01 +02:00
Juergen Hoeller d873f60fef Enforce early initialization of CGLIB method proxies (for AOT processing)
For non-required method proxies, prefer regular reflective invocation instead.

See gh-29107
2022-10-03 13:22:49 +02:00
Brian Clozel 332961f833 Contribute introspection hints on registered beans
As a follow up of #29205, we now need to contribute an "introspection on
declared method" reflection hint for all registered beans.

Closes gh-29246
2022-10-03 11:31:24 +02:00
Brian Clozel 43d39d4e8a Enforce need for type reflection in RuntimeHintsAgent
Prior to this commit, the AOT infrastructure would rely on the fact that
native runtime reflection on a type would only consider
methods/fields/constructors that had specific hints contributed. When
listing them through the reflection API on the type, the native image
would only return those for which we had hints contributed.
This behavior will soon change in GraalVM and will better align with the
JVM behavior: when asking for all declared methods on a type in a native
image, we should get all existing methods, not just the ones registered
previously in the native image.

This commit aligns the behavior of the `RuntimeHintsAgent` and removes
the now misleading predicates as a consequence.

Closes gh-29205
2022-10-03 11:31:24 +02:00
Stephane Nicoll ce46170a04 Avoid using org.springframework.boot 2022-10-03 10:15:38 +02:00
Stephane Nicoll 0b5c3ec267 Polish javadoc 2022-10-03 10:05:27 +02:00
Brian Clozel 3d795ab986 Add Java 19 daily build to CI pipeline 2022-10-02 16:24:10 +02:00
Brian Clozel 94da3609af Ignore Blockhound tests on Java 19 2022-10-02 16:23:42 +02:00
Brian Clozel ee1afb864c Add Java 19 to CI image 2022-10-02 16:23:22 +02:00
Brian Clozel a18c692b53 Start RestTemplate observation wtih available request
Prior to this commit, the `RestTemplate` `ClientHttpObservation` would
be started before the request object is available. While this would also
measure the connection estalishment for some HTTP client libraries, this
arrangement is incompatible with a tracing approach where the request
must be available to propagate information through the request headers.

This commit ensures that the observation only starts when the request is
available.

Fixes gh-29234
2022-09-30 23:12:53 +02:00
Johnny Lim 380795e5b8 Polish observability changes
Closes gh-29235
2022-09-30 23:12:26 +02:00
Phillip Webb afac8dd8af Refine SourceFile record to class conversion
Update conversion logic to deal with annotations.

See gh-29236
2022-09-30 11:58:14 -07:00
Phillip Webb 7fd8e081bb Allow TestCompiler SourceFile to work with records
Update `SourceFile` to try a regex replace to make `record` files look
like regular classes.

Closes gh-29236
2022-09-30 11:18:43 -07:00
Brian Clozel 8c24e8c034 Add HttpOutcome for HTTP observations
Prior to this commit, the HTTP Observations would use
`HttpStatus.Series` as a value source for the "outcome" key value in
recorded observations. This would work for most cases, but would not
align in the 2xx HTTP status cases: the series would provide a
"SUCESSFUL" value whereas the heritage metrics support in Spring Boot
would give "SUCESS".

This commit introduces a dedicated `HttpOutcome` concept for this and
applies it to all HTTP observations.

Fixes gh-29232
2022-09-30 18:17:23 +02:00
Brian Clozel b9070ae752 Add contextualName to HTTP Observations
This commit ensures that all HTTP `ObservationConvention`
implementations provide a consistent contextual name for observations.
This name should be like "http get" where only the HTTP verb changes
depending on the request.

Fixes gh-29231
2022-09-30 18:17:23 +02:00
Stephane Nicoll 0cc3c6b5d1 Add entry point for processing an application ahead-of-time
This commit adds the necessary infrastructure to process an application
using the AOT engine, similar to the existing TestAotProcessor for
processing tests.

This can be used by frameworks built on top of Spring Framework, for
instance by providing a main method that can be triggered by build
tools.

Close gh-29181
2022-09-30 16:18:27 +02:00
Arjen Poutsma 0293e22910 Trying to fix flaky CoroutinesIntegrationTests 2022-09-30 15:54:01 +02:00
Stephane Nicoll 7e7e4efb01 Merge pull request #29230 from izeye
* pr/29230:
  Polish ReflectionHintsPredicates

Closes gh-29230
2022-09-30 15:30:49 +02:00
Johnny Lim 89db4efb67 Polish ReflectionHintsPredicates
See gh-29230
2022-09-30 15:23:35 +02:00
Brian Clozel 377d719b5f Add opens for Gradle test workers
After our upgrade to Gradle 7.5.1, our test suite requires changes to
our test configuration. See:

https://docs.gradle.org/7.5/userguide/upgrading_version_7.html#removes_implicit_add_opens_for_test_workers
2022-09-30 15:13:46 +02:00
Brian Clozel 8e24797d37 Merge branch '5.3.x' 2022-09-30 14:42:00 +02:00
Brian Clozel 777caef4f7 Upgrade to Gradle 7.5.1 2022-09-30 14:35:31 +02:00
rstoyanchev 5d2c9d946a Clean up conditional use of ChannelOperationsId
Closes gh-29224
2022-09-30 13:04:02 +01:00
Violeta Georgieva e81d30160c Remove useless constant reactorNettyRequestChannelOperationsIdPresent
`reactor.netty.ChannelOperationsId` is available in Reactor Netty 1.1.x from the very beginning.
2022-09-30 13:04:02 +01:00
rstoyanchev bc13d2b558 Remove unnecessary suppressing of deprecation
Closes gh-28870
2022-09-30 13:04:02 +01:00
Sam Brannen 2606557483 Polishing 2022-09-30 13:32:33 +02:00
Sam Brannen d21eea7de4 Fix recent regression in PathMatchingResourcePatternResolver
Commit 0eb66789ed which introduced generic FileSystem support in
PathMatchingResourcePatternResolver also introduced a regression in that
a matching folder is now returned in the results.

This commit address this by additionally using Files#isRegularFile() in
the predicate used to filter candidates.

Closes gh-29163
2022-09-30 13:05:31 +02:00
Sébastien Deleuze 7a2110d8a5 Refine Kotlin bean DSL for AOT use case
Before this commit, beans registered with the Kotlin bean DSL
typically added via SpringApplication#addInitializers
were registered 2 times: by the code generated AOT and by
the listener executed at runtime.

After this commit, such beans are only registered 1 time when
AOT generation is involved, and does not require specific
reflection hints on native execution anymore.

Closes gh-29211
2022-09-30 12:25:43 +02:00
Brian Clozel d98e27cf79 Upgrade to Kotlin 1.7.20
This commit also temporarily changes a test assertion for the Jackson
Kotlin module.
As of https://youtrack.jetbrains.com/issue/KT-52932, Kotlin enhanced the
`IntRange` and this change is not supported yet by the Jackson Kotlin
module. An issue has been reported here:
FasterXML/jackson-module-kotlin#582

Closes gh-29225
2022-09-30 11:24:55 +02:00
Stephane Nicoll e4940149d9 Polish "Replace AotApplicationContextInitializer with interface"
Closes gh-29157
2022-09-30 07:46:00 +02:00
Phillip Webb f2568f2dda Remove unused import
See gh-29157
2022-09-29 16:50:15 -07:00
Phillip Webb 86ad29a7d6 Drop getAotInitializers method
See gh-29157
2022-09-29 15:43:13 -07:00
Phillip Webb 192bc1eb13 Fix factory method return type
See gh-29157
2022-09-29 15:38:37 -07:00
Phillip Webb ac13d26077 Replace AotApplicationContextInitializer with interface
Replace the `ApplicationContextAotInitializer` class with an
`AotApplicationContextInitializer` interface so that its use can be
detected using a simple `instanceof` check. The existing functionality
has been moved to a factory method on the interface allowing:

	`new ApplicationContextAotInitializer()
		.initialize(context, names);`

To now be written as:

	`AotApplicationContextInitializer.forInitializerClasses(names)
		.initialize(context);`

See gh-29157
2022-09-29 14:43:25 -07:00
Sébastien Deleuze 3eaf326997 Refine ConstantFieldSubstitutionProcessor error handling
The upgrade to SLF4J 2 via gh-29152 has broken
ConstantFieldSubstitutionProcessor when the class processed
has both a static boolean field to make constant at build
time and a static logger.

This issue is about catching and logging those errors,
skipping the processing of such fields which will be
then evaluated at runtime.

Closes gh-29219
2022-09-29 12:52:30 +02:00
Sébastien Deleuze 9b577a8955 Upgrade to SLF4J 2.0.2 and Log4j 2.19.0
Closes gh-29152
Closes gh-29217
2022-09-29 10:27:40 +02:00
rstoyanchev 9eaae0fe04 Polishing contribution and Theme deprecation notices
Closes gh-28870
2022-09-28 16:22:45 +01:00
Vedran Pavic cde92f5e1d Deprecate CookieGenerator
This commit deprecates CookieGenerator in favor of the more modern
alternative, ResponseCookie.

See gh-28870
2022-09-28 16:04:38 +01:00
rstoyanchev e6c2d44646 Better integrate ResponseCookie in CookieLocaleResolver
Improve ResponseCookie to allow an existing instance to be mutated
and also to set the cookie value through the builder. This allows
CookieLocaleResolver to avoid duplicating all the fields of
ResponseCookie and to have only a ResponseCookie field instead.

Closes gh-28779
2022-09-28 16:00:33 +01:00
rstoyanchev 075fccca94 Polishing contribution
See gh-28779
2022-09-28 16:00:33 +01:00
Vedran Pavic 7ea49fa9f4 Refactor CookieLocaleResolver
At present, CookieLocaleResolver extends CookieGenerator instead of
AbstractLocale(Context)Resolver like other LocaleResolver
implementations. This means it duplicates some common aspects of
LocaleResolver hierarchy while also exposing some CookieGenerator
operations, such as #addCookie and #removeCookie.

Additionally, CookieGenerator's support for writing cookies is based
on Servlet support which at current baseline doesn't support SameSite
directive.

This commit refactors CookieLocaleResolver to make it extend
AbstractLocaleContextResolver and also replaces CookieGenerator's
cookie writing support with newer and more capable ResponseCookie.
Simplify creation of CookieLocaleResolver with custom cookie name

This commit introduces CookieLocaleResolver constructor that accepts
cookie name thus allowing for a simpler creation of an instance with
the desired cookie name.

See gh-28779
2022-09-28 16:00:33 +01:00
Sam Brannen f6d1806e30 Ensure DefaultListableBeanFactoryTests compiles in Eclipse IDE 2022-09-28 15:44:45 +02:00
Sam Brannen 6cb131ac76 Polishing 2022-09-28 14:27:36 +02:00
Sam Brannen 0eb66789ed Introduce generic FileSystem support in PathMatchingResourcePatternResolver
This commit introduces support in PathMatchingResourcePatternResolver
for resolving files in a generic fashion using the
java.nio.file.FileSystem API, including preliminary support for class
path scanning within a GraalVM native image.

See included commits for details.

Closes gh-29163
2022-09-28 13:53:31 +02:00
Sam Brannen ccff526454 Reintroduce logging and exception handling for file system resource scanning
See gh-29163
2022-09-28 13:47:55 +02:00
Sam Brannen 7cb54de985 Apply root dir cleanup only for GraalVM native image resource scheme
See gh-29163
2022-09-28 13:47:44 +02:00
Sam Brannen 7a15805f6c Polish contribution
See gh-29163
2022-09-28 13:47:44 +02:00
Sam Brannen 0e22c3d89d Convert file: URL to FileSystemResource for backward compatibility
See gh-29163
2022-09-28 13:47:44 +02:00
Sam Brannen 508be4e0fa Update Javadoc to reflect changes
See gh-29163
2022-09-28 13:47:44 +02:00
Sam Brannen 385292dc41 Fix Checkstyle violations
See gh-29163
2022-09-28 13:47:44 +02:00
Dave Syer f751b38795 Use java.nio and FileSystems to resolve files in PathMatchingResourcePatternResolver
The JDK has decent support for walking a file system (via the
FileSystem API in java.nio.file), but prior to this commit Spring still
used hand-rolled pre-Java 7 code. Also, in principle, FileSystem can be
an abstraction used to express any hierarchy of resources through their
URIs. This is a good fit with the Spring Resource abstraction, and for
instance would mean that GraalVM native images could potentially do
classpath scanning through a custom URI and FileSystem already provided
by GraalVM.

In light of the above, this commit overhauls the implementation of
PathMatchingResourcePatternResolver to use a java.nio.file.FileSystem
to find matching resources within a file system.

As a side effect, several obsolete `protected` methods have been
removed from PathMatchingResourcePatternResolver.

See gh-29163
2022-09-28 13:39:48 +02:00
Stephane Nicoll c5fc0a5ef3 Add shortcut in TestGenerationContext 2022-09-28 11:20:35 +02:00
Stephane Nicoll 737967f924 Polish 2022-09-28 11:16:07 +02:00
Stephane Nicoll 38d91bafce Generate matching structure for configuration classes
This commit improves GeneratedClass to support inner classes, allowing
them to be registered by name with a type customizer, as
GeneratedClasses does for top level classes.

BeanDefinitionMethodGenerator leverages this feature to create a
matching structure for configuration classes that contain inner classes.

Closes gh-29213
2022-09-28 11:13:52 +02:00
rstoyanchev b1ee44f12e Polishing contribution
Closes gh-27280
2022-09-27 17:08:52 +01:00
Ashley Scopes d14477eb84 Add methods to DefaultResponseCreator & MockRestResponseCreators
New methods in DefaultResponseCreator for adding headers and cookies,
for specifying the character encoding when setting a string body on
a response, which is useful when working in environments that do not
automatically assume UTF-8, such as integrating with legacy
applications from a new Spring one.

New methods in MockRestResponseCreators support extra commonly used
HTTP status codes, including some that occur when working in AWS,
CloudFlare, or when using gateways such as Kong, where resilient
applications should be able to respond to ratelimits, gateway errors,
and gateway timeouts that may occur if a remote service is down.

Added test cases for any changes made.

See gh-27280
2022-09-27 15:58:44 +01:00
rstoyanchev badba7c3e9 Support coma-delimited format for origin values
Closes gh-27606
2022-09-27 14:49:18 +01:00
Arjen Poutsma d516667f37 Polish "Allow for CoroutineContext in invokeSuspendingFunction"
See gh-27193
2022-09-27 13:26:49 +02:00
Lukáš Křečan ff844ed99f Allow overriding invokeSuspendingFunction
This commit isolates the invocation of Kotlin coroutines into a separate
template method, so that it can be overridden in subclasses of
RequestMappingHandlerAdapter.

Closes gh-27195
2022-09-27 13:26:28 +02:00
rstoyanchev ac3ebc37dc Remove requestCompleted from RequestMappingHandlerAdapter
Closes gh-29002
2022-09-27 11:48:31 +01:00
rstoyanchev c135549a4e Conditional initialization of messageConverters
Closes gh-27854
2022-09-27 11:37:25 +01:00
Arjen Poutsma f80fbe30cc Allow for CoroutineContext in invokeSuspendingFunction
This commit adds an overloaded version of invokeSuspendingFunction
that specifies a CoroutineContext, instead of using
Dispatchers.Unconfined.

Closes gh-27193
2022-09-27 11:54:44 +02:00
Stephane Nicoll dd3e3b2989 Merge branch 'gh-29207'
Closes gh-29207
2022-09-27 10:33:27 +02:00
Stephane Nicoll e6aef11b09 Allow target to be a ClassName rather than an existing Class
See gh-29207
2022-09-27 10:33:14 +02:00
Stephane Nicoll 8ef850ff91 Update ClassNameGenerator to work with a ClassName target
This commit updates ClassNameGenerator so that it uses a ClassName for
its default target. This makes sure that a target that has been
generated can be used.

See gh-29027
2022-09-27 10:33:13 +02:00
Brian Clozel 1707a22c18 Merge branch '5.3.x' 2022-09-26 22:27:53 +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
Brian Clozel 9c400ed384 Polish Stream#toList() consistent usage
In general, `Stream#toList()` is not a transparent replacement for
`.collect(Collectors.toList()))`, as the former returns an immutable
list.

This commit reverts some of those changes, where the returned `List`
instance was expected to be mutable.

See gh-29203
2022-09-26 20:25:13 +02:00
Adam Ostrožlík 641303baff Remove unnecessary sync block in ControllerMethodResolver
Closes gh-29208
2022-09-26 18:32:01 +02:00
Adam Ostrožlík 0ccb64fe10 Replace Collectors.toList with Stream.toList
Closes gh-29203
2022-09-26 18:32:01 +02:00
ijonathanc 9d263668d5 Pass current request to filter in RouterFunction extensions
This commit ensures that the proper request is passed in the
Kotlin RouterFunction extension DSL.

Closes gh-27086
2022-09-26 14:55:14 +02:00
Sam Brannen a975b9d5da Suppress "unused" warnings in tests 2022-09-26 14:27:32 +02:00
Sam Brannen 2872282d75 Ensure Kotlin JMH folder is imported as test folder in Eclipse
Commit 9a180d1811 introduced Kotlin-based
JMH benchmarks which prevent spring-beans from being imported into the
Eclipse IDE.

This commit ensures that src/jmh/kotlin is imported in Eclipse with the
"test" attribute set.

See gh-24104
2022-09-26 14:21:49 +02:00
Сергей Цыпанов 8a87e118e1 Remove redundant assignment of default values to volatile/atomic fields
Closes gh-27477
2022-09-26 13:43:04 +02:00
Brian Clozel e8d24ae693 Fix HTTP interface section title in ref docs 2022-09-26 13:39:51 +02:00
Stephane Nicoll 2c0a9e0e30 Merge pull request #23418 from Syquel
* pr/23418:
  Polish "Improve resolution of generic type variables"
  Improve resolution of generic type variables

Closes gh-23418
2022-09-26 13:13:24 +02:00
Stephane Nicoll b11e885e00 Polish "Improve resolution of generic type variables"
See gh-23418
2022-09-26 13:07:43 +02:00
Frederik Boster 124a76b1ad Improve resolution of generic type variables
See gh-23418
2022-09-26 13:04:26 +02:00
Stephane Nicoll 267908a118 Polish 2022-09-26 11:15:43 +02:00
Sébastien Deleuze 9a180d1811 Add JMH benchmarks
Closes gh-24104
2022-09-26 10:23:06 +02:00
Sébastien Deleuze 8e73b57329 Refine Kotlin changes
This refinement ensures the constructor is properly
accessible, avoid duplicating current logic and
provide a slightly faster implementation of the
Kotlin codepath.

See gh-24104
2022-09-26 10:22:46 +02:00
stsypanov edcc559b4a Add fast-path in BeanUtils#instantiateClass
For no-args constructor.

See gh-24104
2022-09-26 10:21:28 +02:00
Sébastien Deleuze 42ab1b75e7 Fix a regression in Kotlin serialization support
After gh-29068, some Type instances can throw an
IllegalArgumentException. This commit catches them
properly to just return a null serializer in that
case.

Closes gh-29192
2022-09-26 09:55:44 +02:00
Lars Grefer 94e5eb3eb6 Consider empty jar entries as readable
Prior to this commit, resource handling would not serve empty files and
return instead HTTP 404 responses. This would only happen for files
contained by JARs, but not on the filesystem.

This can be tracked to changes done in `AbstractFileResolvingResource`
where we avoid serving empty files for directories, see gh-21372.
This commit improves the `checkReadable` method to align this behavior
between file system and JAR files.

Closes gh-28850
2022-09-26 09:51:11 +02:00
Stephane Nicoll dfd1a31435 Merge branch '5.3.x' 2022-09-26 09:07:27 +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 82ae2a0326 Merge branch '5.3.x' 2022-09-26 08:53:14 +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 5275be3adf Merge branch '5.3.x' 2022-09-26 08:50:58 +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
Stephane Nicoll 86578e10f1 Merge pull request #29202 from izeye
* pr/29202:
  Polish "Deprecate support for theme" changes

Closes gh-29202
2022-09-26 08:47:09 +02:00
Johnny Lim 907c96b21e Polish "Deprecate support for theme" changes
See gh-29202
2022-09-26 08:46:19 +02:00
Sam Brannen f31eb2dcf9 Skip scanning the module path when running in a native image
Prior to this commit, the following exception was thrown when using the
PathMatchingResourcePatternResolver to scan for class path resources
using the `classpath*:` prefix within a native image.

com.oracle.svm.core.jdk.UnsupportedFeatureError: JRT file system is disabled
com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89)
jdk.internal.module.SystemModuleFinders$SystemImage.reader(SystemModuleFinders.java:139)
jdk.internal.module.SystemModuleFinders$ModuleContentSpliterator.<init>(SystemModuleFinders.java:527)
jdk.internal.module.SystemModuleFinders$SystemModuleReader.list(SystemModuleFinders.java:502)
org.springframework.core.io.support.PathMatchingResourcePatternResolver.lambda$findAllModulePathResources$6(PathMatchingResourcePatternResolver.java:819)

This commit addresses this by not attempting to scan the module path
when running in a GraalVM native image.

Closes gh-29183
2022-09-25 19:31:06 +02:00
Sam Brannen 6affae4120 Polish resourceArrayPropertyEditor() test 2022-09-25 19:31:06 +02:00
Sam Brannen 29442d4b7a Revamp PathMatchingResourcePatternResolverTests
In preparation for gh-29163, this commit revamps
PathMatchingResourcePatternResolverTests as follows.

- organizes tests into @Nested test classes

- reintroduces the @Disabled classpathStarWithPatternOnFileSystem() test

- stops asserting the protocol of Resource URLs, since the protocol is
  dependent on the environment -- for example, file: and jar: URLs are
  actually resource: URLs within a GraalVM native image

- simplifies implementation of test methods and assertFilenames()
2022-09-25 16:12:46 +02:00
rstoyanchev 57067f58e1 Polishing contribution
Closes gh-28401
2022-09-23 16:54:15 +01:00
rstoyanchev c2f1ddcee9 Consistent Nullable input in Hints 2022-09-23 16:54:15 +01:00
Laber, Jason M 27b5d141e2 Allow customization for ObjectReader and ObjectWriter
Allows customization from subclasses of
AbstractJackson2HttpMessageConverter, AbstractJackson2Decoder, and
AbstractJackson2Encoder

See gh-28401
2022-09-23 16:54:15 +01:00
rstoyanchev 74df50c906 Polishing ProblemDetail Javadoc 2022-09-23 16:54:02 +01:00
Andy Wilkinson a409e0fd2c Consider all processors when processing @Reflective
Previously, only the first occurance of `@Reflective` and its
processor was considered. When `@Reflective` appeared twice on a type
due to meta-annotations or inheritance, this resulted in other
processors being ignored and hints were missing as a result.

This commit updates ReflectiveRuntimeHintsRegistrar to consider
every occurance of `@Reflective` found in the type hierarchy,
and to then use the processors from each of them.

Fixes gh-29193
2022-09-23 16:31:35 +02:00
Stephane Nicoll c19cedede1 Revisit BeanRegistrationCodeFragments
This commit revisit BeanRegistrationCodeFragments to separate the
responsibility between the default implementation and the delegates. It
also reviews how customization are applied by improving the Javadoc and
the method name.

Closes gh-28865
2022-09-22 15:32:28 +02:00
Arjen Poutsma ef5b64dc00 Minor Javadoc correction 2022-09-22 12:26:16 +02:00
Stephane Nicoll 84fd942712 Add support for Charset for property value code generation
Closes gh-29186
2022-09-21 19:27:05 +02:00
rstoyanchev 5192d99fa4 Support formatting annotations on HTTP service interface
Closes gh-29095
2022-09-21 16:18:39 +01:00
Sébastien Deleuze 157c28bcec Enable HTTP and HTTPS on native in spring-web module
Closes gh-29185
2022-09-21 16:47:57 +02:00
Sébastien Deleuze 23a58e6bab Skip ModuleFinder#ofSystem usage on native
gh-28506 introduces a big footprint regression on
native, so it should for now be skipped when
compiling to native images. Such support could
potentially be re-introduced via gh-29081.

Closes gh-29183
2022-09-21 16:47:57 +02:00
Sam Brannen 39208eaccd Upgrade to JUnit 5.9.1
Closes gh-29179
2022-09-20 22:04:15 +02:00
Phillip Webb 6802665177 Refactor GeneratedFilesTestCompilerUtils to CompilerFiles
See gh-29175
2022-09-20 11:00:56 -07:00
Sébastien Deleuze 77fdd69cd1 Skip Javadoc generation for the GraalVM feature module
It is currently broken due to missing modules/exports
configuration and it is not a public API we want to document.

Closes gh-29178
2022-09-20 16:38:48 +02:00
Stephane Nicoll 4625e92eb8 Break dependency between TestCompiler and AOT
This commit improves `TestCompiler` with a `with` function that allows
to customize a test compiler instance. Rather than `TestCompiler`
knowing about `TestGenerationContext`, the latter implements the
function so that it can be passed as is.

See gh-29175
2022-09-20 15:07:51 +02:00
Stephane Nicoll 2f84096af1 Polish 2022-09-20 15:07:50 +02:00
Sam Brannen 321092ce6f Consistent use of @Deprecated(since = "6.0") 2022-09-20 14:34:24 +02:00
Sam Brannen 91bca55cbf Fix broken links to ThemeResolver in Javadoc 2022-09-20 14:33:55 +02:00
Sam Brannen f140464c12 Remove unused variable in test
See gh-28324
2022-09-20 13:51:39 +02:00
Sam Brannen 1263226928 Remove unused EMPTY_BUFFER constant
See gh-29038
2022-09-20 13:51:35 +02:00
Arjen Poutsma 990a34074a Upgrade RestTemplate to HttpClient 5
This commit upgrades the HttpComponentClientHttpRequestFactory and
related types from HttpClient version 4.5 to 5.

Closes gh-28925
2022-09-20 12:04:51 +02:00
Stephane Nicoll cc3616da66 Remove unnecessary import 2022-09-20 08:58:23 +02:00
Phillip Webb df9990f66b Relocate MockSpringFactoriesLoader
Closes gh-29176
2022-09-19 22:29:40 -07:00
Phillip Webb 52bffbff76 Move TestCompiler and related classes to core.test.tools package
Closes gh-29175
2022-09-19 22:29:40 -07:00
Scott FrederickandPhillip Webb c9009453c9 Allow TestCompiler to access and generate resources
Update `TestCompiler` so that it can access and generate resources.
This change will allow the `TestCompiler` to be used with annotation
processor tests that generate resources.

Closes gh-29174

Co-authored-by: Phillip Webb <pwebb@vmware.com>
2022-09-19 22:29:40 -07:00
Phillip Webb cc7552ec61 Rename @CompileWithTargetClassAccess
Rename `@CompileWithTargetClassAccess` to
`@CompileWithForkedClassLoaderClassLoader`.

Closes gh-29173
2022-09-19 22:29:40 -07:00
Andy WilkinsonandPhillip Webb 7168141504 Allow TestCompiler to load cglib generated classes
Update `TestCompiler` so that it can now load cglib generated classes.
This commit adds support to `DynamicJavaFileManager` so that it can
reference generated classes and adds a new lookup function to
`CompileWithTargetClassAccessClassLoader` to that it can load the
bytecode of generated classes directly.

See gh-29141

Co-authored-by: Phillip Webb <pwebb@vmware.com>
2022-09-19 22:29:36 -07:00
Alex 5277b1dbf0 Harden GitHub Workflows security settings
Closes gh-29171
Signed-off-by: sashashura <93376818+sashashura@users.noreply.github.com>
2022-09-19 14:24:57 +02:00
Brian Clozel 3e41d7f23e Remove extra asciidoctor configuration
See gh-29162
2022-09-19 13:00:42 +02:00
Arjen Poutsma fa5998ebd4 Trying to fix flaky CoroutinesIntegrationTests 2022-09-19 12:22:18 +02:00
Jay Bryant 2bf8eeb120 Switch to spring-asciidoctor-backends
This commit uses the new AsciiDoctor backend.

Closes gh-29162
2022-09-19 11:02:21 +02:00
Brian Clozel 4c45387805 Polish Observability instrumentation
This commit removes the scoping of `RestTemplate` requests, since no
user code is meant to run during HTTP client exchanges.

This also polishes the reactive `WebFilter` to directly use the
specific enum when creating the observation.
2022-09-19 10:05:42 +02:00
Sam Brannen d55bd6d28d Merge branch '5.3.x' 2022-09-18 15:04:44 +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
Sam Brannen d7a2737732 Merge branch '5.3.x' 2022-09-16 18:01:21 +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 39cf11e21d Merge branch '5.3.x' 2022-09-15 17:16:08 +02:00
Sam Brannen f0f633d187 Limit exclude to core Spring Framework committers 2022-09-15 17:15:50 +02:00
Stephane Nicoll 671f843d34 Remove deprecated code
Closes gh-29160
2022-09-15 16:29:38 +02:00
Sam Brannen c2c324be9b Merge branch '5.3.x' 2022-09-15 16:26:19 +02:00
Sam Brannen 4b7aa6bb39 Exclude core committers from generated changelog 2022-09-15 16:25:57 +02:00
Stephane NicollandAndy Wilkinson e59da2de1e Allow test compilation to reference existing generated classes
Previously, the generated classes from an InMemoryGeneratedFiles were
not taken into account and if generated code refers to any of them,
compilation failed.

This commit introduces a ClasFile abstraction, similar to ResourceFile
for resources that represents an existing generated class.

Closes gh-29141

Co-authored-by: Andy Wilkinson <wilkinsona@vmware.com>
2022-09-15 16:01:55 +02:00
Stephane Nicoll aa5d7398d5 Polish 2022-09-15 16:01:49 +02:00
Stephane Nicoll b44eb63d29 Workaround LinkageError with TestCompiler
See gh-29159
2022-09-15 16:00:25 +02:00
Stephane Nicoll 97e946698b Merge branch '5.3.x' 2022-09-15 11:00:17 +02:00
Spring Builds 13933ee2c6 Next development version (v5.3.24-SNAPSHOT) 2022-09-15 07:59:36 +00:00
rstoyanchev 8f617780f7 Merge branch '5.3.x' 2022-09-14 19:28:45 +01:00
rstoyanchev ae8b7973b4 Improve Javadoc on RequestEntity#getUrl
Closes gh-28930
2022-09-14 19:25:55 +01:00
Juergen Hoeller 8a37dc23e2 Upgrade to EclipseLink 3.0.3, JRuby 9.3.8, Woodstox 6.3.1 2022-09-14 19:42:43 +02:00
Juergen Hoeller 5e162881a6 Merge branch '5.3.x'
# Conflicts:
#	build.gradle
2022-09-14 19:29:57 +02: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
rstoyanchev f3c082abac Deprecate ignoreDefaultModelOnRedirect property
Closes gh-28324
2022-09-14 18:14:04 +01:00
Juergen Hoeller 250880bf90 Upgrade to RSocket 1.1.3, RxJava 3.1.5, SmallRye Mutiny 1.7, Groovy 4.0.5, Gson 2.9.1, Protobuf 3.21.5, Mockito 4.8, JsonPath 2.7 2022-09-14 19:10:46 +02:00
Juergen Hoeller 462ffa778b Merge branch '5.3.x'
# Conflicts:
#	build.gradle
2022-09-14 18:43:25 +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
rstoyanchev 02f61e3aae Fix failing test in CancelWithoutDemandCodecTests
The test started failing after recent commit
e370c15bc6.

See gh-29038
2022-09-14 16:43:35 +01:00
Sam Brannen 6d5fa89efe Remove Caucho exclusion for main
See gh-28876
2022-09-14 17:18:40 +02:00
Sam Brannen b87d48b99b Merge branch '5.3.x' 2022-09-14 17:18:00 +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 8d92c57777 Merge branch '5.3.x'
# Conflicts:
#	spring-tx/src/main/java/org/springframework/jca/cci/core/support/CciDaoSupport.java
2022-09-14 16:52:55 +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 992a81ab68 Merge branch '5.3.x'
# Conflicts:
#	spring-web/src/main/java/org/springframework/web/util/WebUtils.java
2022-09-14 16:12:04 +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
Sam Brannen af2481f6da Merge branch '5.3.x' 2022-09-14 15:54:34 +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 a2445dcb8a Polishing 2022-09-14 15:27:11 +02:00
Sam Brannen 911d1f2dea Suppress warnings 2022-09-14 15:27:11 +02:00
Stephane Nicoll e9997d4004 Polish 2022-09-14 14:40:02 +02:00
Sam Brannen 354117da7f Merge branch '5.3.x' 2022-09-14 14:38:10 +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
rstoyanchev e370c15bc6 Fix error handling regression for non-streaming Flux
Closes gh-29038
2022-09-14 12:00:31 +01:00
Juergen Hoeller 3307630a95 Upgrade to Jackson 2.13.4, Netty 4.1.82, Tomcat 10.0.23, Undertow 2.2.19, Hibernate ORM 5.6.11, Hibernate Validator 7.0.5 2022-09-14 12:56:16 +02:00
Juergen Hoeller 50d34366bc Polishing 2022-09-14 12:55:53 +02:00
Stephane Nicoll 6feeeec70e Upgrade to Micrometer 1.10.0-M6
Closes gh-29151
2022-09-14 11:53:24 +02:00
Brian Clozel d3d91d4d22 Merge branch '5.3.x' 2022-09-13 21:41:10 +02:00
Brian Clozel c871758a51 Upgrade to Reactor 2020.0.23
Closes gh-29129
2022-09-13 21:35:11 +02:00
Brian Clozel 9c48dda4f3 Upgrade to Reactor 2022.0.0-M6 2022-09-13 21:29:47 +02:00
Brian Clozel 19d991a67b Revisit resource cleanup in ClientHttpRequestFactory
Prior to this commit, resource management around
`ClientHttpRequestFactory` and `RestTemplate` was unclear. Some
factories implementation were implementing a `DisposableBean` and other
contracts were not managing request factory resources.

In the meantime, neither `ClientHttpRequestFactory` nor `RestTemplate`
are typically meant to be contributed as beans to the application
context. Most often, they're instantiated within beans and their
lifecycle should be managed by those.

This commit makes all `ClientHttpRequestFactory` `Closeable` and ensures
that all existing implementations have a similar behavior between
`dispose()` and `close()`. Since `RestTemplate` (actually
`HttpAccessor`) can instantiate factories on its own, they also now
extend `Closeable` to properly close those resources, if not externally
managed.

Closes gh-29010
2022-09-13 15:53:01 +02:00
Arjen Poutsma 71f9a84d22 Fix releasing bug in StringDecoder
This commit fixes an issue in StringDecoder, where, if the buffer did
not contain any delimiters, it was released before it was relayed to
any subscribers.

Closes gh-29119
2022-09-13 15:46:24 +02:00
Sébastien Deleuze 2687de0fe8 Add HandshakeWebSocketService runtime hints
Closes gh-29146
2022-09-13 15:37:06 +02:00
Brian Clozel 241261b6b6 Polish
See gh-28341
2022-09-13 14:00:55 +02:00
Brian Clozel 5f62d1dc8e Add className variants in ReflectionHintsPredicates
This commit adds predicates variants that accept `String className`
instead of actual `Class<?>` when checking for fields and method hints.
This is useful when the type under test is not visible from the current
test class.

Closes gh-29143
2022-09-13 14:00:55 +02:00
Sébastien Deleuze 198e17f659 Add AbstractEntityManagerFactoryBean proxy hints for Hibernate
Closes gh-29138
2022-09-13 13:52:27 +02:00
Sam Brannen 948c9b85a0 Revise internals of AOT testing support 2022-09-13 13:06:33 +02:00
Sam Brannen e7a297a948 Rename TestAotMappings to AotTestContextInitializers
- for consistency with AotTestAttributes and similar classes

See gh-28205, gh-28204
2022-09-13 12:07:30 +02:00
Sam Brannen a3b6b41bd7 Polish BootstrapUtils 2022-09-13 11:28:57 +02:00
Sam Brannen 1e2541a0a3 Remove support for setting default CacheAwareContextLoaderDelegate
The ability to set a system property to change the default
CacheAwareContextLoaderDelegate was only needed by the Spring Native
project in the Spring Framework 5.3.x line and should not be used by
other projects.

This commit therefore reverts the changes made in conjunction with
gh-27540.

Closes gh-29061
2022-09-13 11:14:51 +02:00
Sébastien Deleuze a711ed59f6 Set hibernate.bytecode.provider to none on native image
Closes gh-29140
2022-09-13 10:18:40 +02:00
Sébastien Deleuze 6fed342543 Refine DefaultPersistenceUnitManager#determineDefaultPersistenceUnitRootUrl
This commit refines the implementation to be more
lenient when defaultPersistenceUnitRootLocation is equals
to ORIGINAL_DEFAULT_PERSISTENCE_UNIT_ROOT_LOCATION and an
IOException is thrown, which happens when running on
native image.

Closes gh-29137
2022-09-13 10:18:40 +02:00
Stephane Nicoll 6cfbf391ec Merge branch '5.3.x' 2022-09-13 08:42:56 +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
Sam Brannen b0ee513db6 Introduce AotTestAttributes mechanism in the TestContext framework
For certain use cases it is beneficial to be able to compute something
during AOT build-time processing and then retrieve the result of that
computation during AOT run-time execution, without having to deal with
code generation on your own.

To support such use cases, this commit introduces an AotTestAttributes
mechanism in the Spring TestContext Framework with the following
feature set.

- conceptually similar to org.springframework.core.AttributeAccessor in
  the sense that attributes are generic metadata

- allows an AOT-aware test component to contribute a key-value pair
  during the AOT build-time processing phase, where the key is a String
  and the value is a String

- provides convenience methods for storing and retrieving attributes as
  boolean values

- generates the necessary source code during the AOT build-time
  processing phase in the TestContext framework to create a persistent
  map of the attributes

- provides a mechanism for accessing the stored attributes during AOT
  run-time execution

Closes gh-29100
2022-09-12 20:32:36 +02:00
Sam Brannen d3822a2eb9 Revert workaround for Java 8 compiler bug 2022-09-12 18:24:00 +02:00
Brian Clozel bfac042301 Polish
See gh-28341
2022-09-12 18:02:56 +02:00
Sam Brannen 349bcb4364 Suppress warnings 2022-09-12 17:46:03 +02:00
Sam Brannen e653ee60a0 Polish ClassPathResourceTests 2022-09-12 17:40:43 +02:00
Sam Brannen 138f9c64be Consistently return absolute path from ClassPathResource#getPath
Prior to this commit, the Javadoc for the getPath() method in
ClassPathResource stated the following.

> Return the path for this resource (as resource path within the class path).

That implied the returned path was an "absolute path" within the class
path; however, that was not always true.

If the resource was created using ClassPathResource(String) or
ClassPathResource(String, ClassLoader), the returned path was a cleaned
version of the ABSOLUTE PATH supplied to the constructor, WITHOUT a
leading slash.

If the resource was created using ClassPathResource(String, Class) with
an absolute path, the returned path was a cleaned version of the
ABSOLUTE PATH supplied to the constructor, WITH a leading slash.

If the resource was created using ClassPathResource(String, Class) with
a relative path, the returned path was a cleaned version of the
RELATIVE PATH supplied to the constructor.

In addition, ClassPathResource does not provide public access the Class
passed to the ClassPathResource(String, Class) constructor.

Consequently, the path returned by getPath() could not be reliably used
with ClassLoader.getResource(String) or with the recently introduced
registerResource(Resource) method in ResourceHints.

This commit addresses this issue by ensuring that getPath()
consistently returns the absolute path within the class path without a
leading slash.

See gh-29083
Reverts gh-29094
Closes gh-29099
2022-09-12 17:40:43 +02:00
Stephane Nicoll 0dba729823 Polish "Allow MethodReference to support a more flexible signature"
See gh-29005
2022-09-12 16:25:10 +02:00
rstoyanchev bbe5e91ebc Minor change in ReactorNetty2TcpClient
A follow-up on recent addition of ReactorNetty2TcpClient and switch to
Netty 5 Buffer.
2022-09-12 14:23:15 +01:00
Stephane Nicoll 58a2b79699 Harmonize hint registration
Previously, a shortcut method for the default ExecutableMode was
provided, but we found out that the shortcut makes it harder to
determine the intent.

This commit harmonizes hints registration for types, methods, and
fields. An ExecutableMode is now mandatory to register a method or
constructor. Previous methods that infer a mode or provided a
customizer of the builder are deprecated.

Closes gh-29135
2022-09-12 14:51:04 +02:00
Stephane Nicoll c8f7a76659 Merge pull request #29130 from sreenath-tm
* pr/29130:
  Polish "Adapt FieldHint to recent GraalVM versions"
  Adapt FieldHint to recent GraalVM versions

Closes gh-29130
2022-09-12 14:50:44 +02:00
Stephane Nicoll 042a4f3518 Polish "Adapt FieldHint to recent GraalVM versions"
See gh-29130
2022-09-12 14:50:28 +02:00
SreenathTM 1cb5f00723 Adapt FieldHint to recent GraalVM versions
In recent GraalVM versions, allowWrite and allowUnsafeAccess have been
deprecated and are no longer use. This commit updates FieldHint to
remove the irrelevant properties.

See gh-29130
2022-09-12 14:50:28 +02:00
rstoyanchev c854e35c9d Merge branch '5.3.x' 2022-09-12 12:27:31 +01:00
rstoyanchev 4e97776969 Polishing contribution
Closes gh-28715
2022-09-12 11:47:55 +01:00
Sam Brannen a085a1b6b6 Polishing 2022-09-12 12:37:46 +02: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
Brian Clozel 82e47db28f Instrument reactive servers for Observability
This commit introduces a `HttpRequestsObservationWebFilter` which
instruments web frameworks using Spring's reactive `ServerHttpRequest`
and `ServerHttpResponse` interfaces.

This replaces Spring Boot's `MetricsWebFilter`.

See gh-28880
2022-09-12 11:38:20 +02:00
Brian Clozel 6eded96740 Instrument Servlet server apps for Observability
This commit introduces the new `HttpRequestsObservationFilter`
This `Filter` can be used to instrument Servlet-based web frameworks for
Micrometer Observations. While the Servlet request and responses are
automatically used for extracting KeyValues for observations, web
frameworks still need to provide the matching URL pattern, if supported.

This can be done by fetching the observation context from the request
attributes and contributing to it.

This commit instruments Spring MVC (annotation and functional variants),
effectively replacing Spring Boot's `WebMvcMetricsFilter`.

See gh-28880
2022-09-12 11:37:47 +02:00
Brian Clozel ac9360b624 Instrument WebClient for Observability
This commit introduces Micrometer as an API dependency to the
spring-webflux module. Micrometer is used here to instrument `WebClient`
and record `Observation` for HTTP client exchanges.

This replaces Spring Boot's `MetricsWebClientFilterFunction` which
instruments `WebClient` via an `ExchangeFilterFunction`. Here, a direct
instrumentation is more efficient and less prone to metrics errors.

See gh-28341
2022-09-12 11:37:47 +02:00
Brian Clozel a0ddcd07c8 Instrument RestTemplate for Observability
This commit introduces Micrometer as an API dependency to the spring-web
module. Micrometer is used here to instrument `RestTemplate` and record
`Observation` for HTTP client exchanges.

This will replace Spring Boot's `MetricsClientHttpRequestInterceptor`
which uses the request interceptor contract for instrumentation.
This approach is limited as measurements and tags aren't always precise
and overhead is more important than a direct instrumentation.

See gh-28341
2022-09-12 11:37:41 +02:00
Brian Clozel a68b46a2b6 Add Micrometer BOM 1.10 dependency management
This new BOM dependency is necessary, as Spring Framework will implement
direct instrumentation with Micrometer as a mandatory or optional
dependency in several modules.
2022-09-12 11:36:29 +02:00
Brian Clozel f9dcd428ae Extract Mock HTTP client requests and responses
This commit extracts Mock HTTP client request and response for the
imperative variant. These are made available in the testFixtures
configuration for shared usage.
2022-09-12 11:36:26 +02: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
rstoyanchev 3c5888c43f Polishing
See gh-28847
2022-09-12 09:37:11 +01:00
rstoyanchev 3a5f550a30 Support Reactor Netty 2 / Netty 5 in spring-messaging
Closes gh-28847
2022-09-12 09:37:11 +01:00
rstoyanchev 2f4c39ba2a Add classpath detection for Reactor Netty 2
See gh-28847
2022-09-12 09:37:11 +01:00
유예본(Yebon You)/Platform Engineering팀/11ST fa1f7f6dc7 Use InputStream's contracts instead of StreamUtils
Since Spring Framework 6.0 requires Java 17, we can now use
`InputStream` new contracts when manipulating streams.

Closes gh-27702
2022-09-12 10:21:50 +02:00
Brian Clozel 0770d86936 Deprecate StreamUtils.emptyInput()
Closes gh-29125
2022-09-12 10:21:50 +02:00
Patrick Strawderman d4a74c8f9d Update StreamUtils drain and emptyInput to use JDK builtins
Update StreamUtils.drain to use InputStream.transferTo with a null
OutputStream. This avoids allocating buffers for cases where the
supplied InputStream has an optimized transferTo method (e.g.,
ByteArrayInputStream and FileInputStream).

Additionally, update StreamUtils.emptyInput to simply call
InputStream.nullInputStream.

Closes gh-28961
2022-09-12 10:21:50 +02:00
Stephane Nicoll 7642ac82f6 Apply @PropertySource in AOT-generated context
This commit records `@PropertySource` declarations defined on
configuration classes so that these are contributed to the environment
of a context that is initialized by generated code.

Closes gh-28976
2022-09-12 10:09:37 +02:00
Stephane Nicoll fcb6baf2e9 All MethodReference to support a more flexible signature
Closes gh-29005
2022-09-12 10:09:01 +02:00
Stephane Nicoll 2b45fd4388 Allow bean factory initialization to have a more flexible signature
This commit allows bean factory initialization to use a more flexible
signature than just consuming the DefaultListableBeanFactory. The
environment and the resource loader can now be specified if necessary.

See gh-29005
2022-09-12 10:07:35 +02:00
Stephane Nicoll ae706f3954 Allow MethodReference to define a more flexible signature
This commit moves MethodReference to an interface with a default
implementation that relies on a MethodSpec. Such an arrangement avoid
the need of specifying attributes of the method such as whether it is
static or not.

The resolution of the invocation block now takes an
ArgumentCodeGenerator rather than the raw arguments. Doing so gives
the opportunity to create more flexible signatures.

See gh-29005
2022-09-12 10:07:31 +02:00
Stephane Nicoll 8a4a89b9d9 Allow a MethodReference to be produced from a GeneratedMethod
This commit updates GeneratedMethod and its underlying infrastructure
to be able to produce a MethodReference. This simplifies the need when
such a reference needs to be created manually and reuses more of what
MethodReference has to offer.

See gh-29005
2022-09-12 10:07:13 +02:00
Sam Brannen 649c2f56fd Accept only ClassPathResource in ResourceHints#registerResource()
This commit throws an exception in registerResource() if the supplied
resource is not a ClassPathResource.

See gh-29083
2022-09-11 23:33:39 +02:00
Sam Brannen 7605ed7862 Improve tips for using endToEndTestsForEntireSpringTestModule()
See gh-29122
2022-09-10 20:09:47 +02:00
Sam Brannen 6d83a959fb Rename registerResourceIfNecessary to registerResource
This commit renames registerResourceIfNecessary() to registerResource()
and throws an exception if the class path resource does not exist.

Closes gh-29083
2022-09-10 19:49:56 +02:00
Sam Brannen d883c8fbb3 Polishing 2022-09-10 19:24:34 +02:00
Sam Brannen b429d6b5a6 Filter AOT end-to-end tests like in the actual build 2022-09-10 19:24:34 +02:00
Stephane Nicoll 70db83ac3a Merge branch '5.3.x' 2022-09-10 09:53:41 +02: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 6927482b9c Start building against Reactor 2022.0.0-M6 snapshots
See gh-29128
2022-09-10 09:42:04 +02:00
Patrick Strawderman cdb38e8482 Increase StreamUtils.BUFFER_SIZE to 8192
This aligns the buffer size used in StreamUtils with the buffer sizes
used throughout the JDK (see InputStream, BufferedInputStream, Files).

Closes gh-28965
2022-09-09 22:04:10 +02:00
Brian Clozel c8ef2b2202 Upgrade Java versions in CI image 2022-09-09 20:45:27 +02:00
Brian Clozel 2b5ca63339 Fix serialization compiler warnings with Java 18
As of Java 18, the serial lint warning in javac has been expanded to
check for class fields that are not marked as `Serializable`.
See https://www.oracle.com/java/technologies/javase/18all-relnotes.html#JDK-8202056

In the Spring Framework codebase, this can happen with `Map`, `Set` or
`List` attributes which are often assigned with an unmodifiable
implementation variant. Such implementations are `Serializable` but
cannot be used as field types.

This commit ensures that the following changes are applied:
* fields are marked as transient if they can't be serialized
* classes are marked as `Serializable` if this was missing
* `@SuppressWarnings("serial")` is applied where relevant
2022-09-09 20:24:26 +02:00
Brian Clozel 82a4e374a1 Temporarily disable ORM tests on Java 18
This commit disables some ORM tests based on
`AbstractEntityManagerFactoryBeanTests` as those fail when the main
source set is built with Java 17 and tests are executed with Java 18.
2022-09-09 20:23:05 +02:00
Brian Clozel 21612eba19 Disable BlockHound tests on Java 18+
BlockHound is not currently compatible with Java 18.
2022-09-09 20:22:16 +02:00
Brian Clozel 1051fe7bee Improve InvocableHandlerMethod error handling
This commit improves the fix for gh-18491 for Java 18 as in this case
the exception message might not be null.
2022-09-09 20:20:29 +02:00
Brian Clozel 1dc3d5d2d6 Make HttpStatusCode extend Serializable
`HttpStatusCode` instance only hold an int value and are held by
`Serializable` classes, so this commit enforces this.

Without this change, Java 19+ will emit a compiler warning as
`Serializable` classes use `HttpStatusCode` as a field.
2022-09-09 19:56:00 +02:00
Brian Clozel a09811e73a Upgrade to HSQLDB 2.7.0 2022-09-09 19:55:26 +02:00
Phillip Webb 665deb4d82 Add examples to Javadoc for Throwing*.of factory methods
Closes gh-28969
2022-09-09 09:33:50 -07:00
Sam Brannen 1228f1cb58 Polishing 2022-09-09 18:32:38 +02:00
Sam Brannen ae864eb642 Introduce @Disabled end-to-end AOT tests for the spring-test module
This commit introduces endToEndTestsForEntireSpringTestModule() in
AotIntegrationTests to allow us to periodically check on our AOT
support.

Status quo:

- several test classes cannot be processed for AOT due to exceptions
  thrown during processing
- some generated classes fail to compile
- some tests fail

See gh-29122
2022-09-09 17:42:18 +02:00
Sam Brannen 94ff519072 Test JUnit 4, JUnit Jupiter, & TestNG in AotIntegrationTests
With this commit we also now assert the number of successfully
executed tests.
2022-09-09 17:15:54 +02:00
Sam Brannen 93049f98ee Support TestNG with @CompileWithTargetClassAccess 2022-09-09 17:04:52 +02:00
Sam Brannen 4e9fad7514 Revise TestAotProcessorTests to rely on Path APIs
Instead of String comparisons, assertions are now based on Path
comparisons.

See gh-29103
2022-09-09 16:57:01 +02:00
Sam Brannen d21d7fd6d0 Polishing 2022-09-09 16:08:19 +02:00
Stephane Nicoll 6f5344ab5c Polish 2022-09-09 11:40:09 +02:00
Stephane Nicoll 2d4f308cc1 Provide more context when the code of a value cannot be generated
Closes gh-29118
2022-09-09 11:40:09 +02:00
Brian Clozel c72c2ffc26 Polish
See gh-29114
2022-09-09 11:22:21 +02:00
Nheyll 058109315d Deprecate support for theme
As seen in gh-28868, the support for Themes is now deprecated as of
Spring Framework 6.0 and will be removed in a future release.

Closes gh-29114
2022-09-09 11:22:21 +02:00
Sébastien Deleuze 5e1b5af0e0 Register hints for types exposed via PersistenceManagedTypes
Add binding hints for managed types and hints for
@EntityListeners, @IdClass and @Converter.

Closes gh-29096
2022-09-09 11:12:12 +02:00
rstoyanchev d373435856 Support for WebFlux on Reactor Netty 2 with Netty 5
See gh-28847
2022-09-08 21:54:46 +01:00
Sébastien Deleuze d6c49eec5a Polish WebUtilRuntimeHints
See gh-29112
2022-09-08 18:24:02 +02:00
Sébastien Deleuze bfa803baa4 Add resource hints for HtmlCharacterEntityReferences.properties
Closes gh-29112
2022-09-08 18:00:58 +02:00
Sam Brannen b1654266a5 Get rid of warnings in tests 2022-09-08 13:20:29 +02:00
Sam Brannen 261124f497 Remove flaky executesHugeScriptInReasonableTime() tests
These tests often fail on the CI server and do not provide any
meaningful information when they fail, since only a proper benchmark
would suffice. Furthermore, the test method was introduced 10 years
ago to address deficiencies in JDK 7 which no longer exist.

See gh-14415
2022-09-08 13:18:05 +02:00
Sam Brannen f5bc182ba7 Rename AotTestMappings to TestAotMappings
This provides consistency with other classes in the aot package,
leaving only extended core interfaces starting with the `Aot` prefix.
2022-09-08 13:04:29 +02:00
Sam Brannen d46a816745 Remove deprecated SynthesizedAnnotation interface
The SynthesizedAnnotation interface is no longer used in the core
Spring Framework and should not be used by external parties either.

Closes gh-29092
2022-09-08 12:12:51 +02:00
Sam Brannen 8a0e1969b0 Revert "Introduce isSynthesizable in MergedAnnotation"
This reverts commit 32346b8382.

Closes gh-29093
2022-09-08 12:12:51 +02:00
Sam Brannen 75dfd47826 Delete unused code in ReflectionHintsPredicatesTests 2022-09-08 12:12:51 +02:00
Sam Brannen 3f288eea17 Fix TestAotProcessorTests on MS Windows
Closes gh-29103
2022-09-08 11:50:25 +02:00
Stephane Nicoll b88695a36e Merge branch '5.3.x' 2022-09-08 10:58:01 +02:00
Stephane Nicoll d9c2ccb4b3 Upgrade Ubuntu version in CI image
Closes gh-29106
2022-09-08 10:57:36 +02:00
Sébastien Deleuze e1c94d7e6b Remove obsolete RuntimeHintsUtils
Closes gh-29058
2022-09-08 09:25:09 +02:00
Stephane Nicoll 52a190f96f Merge branch '5.3.x' 2022-09-08 09:04:23 +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
rstoyanchev f669e957a9 Polishing 2022-09-07 17:38:31 +01:00
Brian Clozel 616161f054 Merge branch '5.3.x' 2022-09-07 16:58:56 +02:00
Sam Brannen 26d2f7d12b Delete unused import 2022-09-07 16:55:20 +02:00
rstoyanchev fdfa7cbae6 Add docs for RSocket interface client
Closes gh-24456
2022-09-07 15:01:40 +01:00
rstoyanchev 8423b2cab7 Add support for RSocket interface client
See gh-24456
2022-09-07 15:01:40 +01:00
Sam Brannen ae861a2b3e Document leading slash semantics for ClassPathResource.getPath()
See gh-29094
2022-09-07 15:28:35 +02:00
Sam Brannen 0395fb4f5f Polish tests 2022-09-07 15:12:15 +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
Sam Brannen 1688becd73 Avoid questionable use of ClassPathResource#getPath() in tests
Prior to this commit, several tests used ClassPathResource#getPath()
based on the knowledge that the ClassPathResource had been created
using the ClassPathResource(String,Class) constructor. However, making
such an assumption seems ill advised in light of the abstraction that
ClassPathResource provides.

In light of that, this commit avoids questionable use of
ClassPathResource#getPath() in tests by refactoring those tests to use
the proper abstractions provided by ClassPathResource.
2022-09-07 14:59:05 +02:00
Arjen Poutsma 4cc91e46b2 Decode quoted pairs in ContentDisposition
This commit makes sure that quoted pairs, as used in Content-Disposition
header file names (i.e. \" and \\), are properly decoded, whereas before
they were stored as is.

Closes gh-28837
2022-09-07 10:22:19 +02:00
Sébastien Deleuze 9cfe79186d Stop using RuntimeHintsUtils
Due to gh-29053, we can stop using RuntimeHintsUtils to
register SynthesizedAnnotation proxies.

Closes gh-29059
2022-09-07 10:10:07 +02:00
Stephane Nicoll 1e8017107a Remove unnecessary workaround
See gh-29091
2022-09-07 07:50:49 +02:00
Brian Clozel 323d1907c1 Do not require full type reflection when listing methods/fields
Prior to this commit, the `RuntimeHintsAgent` and its testing
infrastructure would assume that calling `MyClass.class.getMethods()`
requires a reflection hint on the class for introspecting public/private
methods.

GraalVM does not require this, in fact this call only returns methods
that have reflection hints in the native image.

This commit refines the agent behavior for `Class.getMethods()`,
`Class.getDeclaredMethods()`, `Class.getFields()` and
`Class.getDeclaredFields()`. With this change, registering at least one
method/field for reflection is enough to match.

During the execution of Java tests, all methods and fields will be
provided, regardless of hints being registered or not. This could cause
false negatives where we're missing reflection hints on methods or
fields.
This risk is mitigated thanks to additional instrumentation on
`Method.getAnnotations()`, `Method.getParameterTypes()` and
`Method.invoke()`. If a method is found reflectively, chances are it
will be used for further reflection.

Closes gh-29091
2022-09-06 22:14:10 +02:00
Sam Brannen 6cce47176a Further clarify the semantics of ClassPathResource.getPath()
See gh-29094
2022-09-06 20:34:12 +02:00
Sam Brannen 018122f684 Update Javadoc for ResourceHints.registerResourceIfNecessary()
See gh-29094
2022-09-06 20:18:24 +02:00
Sam Brannen d57e061d3f Introduce getAbsolutePath() in ClassPathResource
Since getPath() returns a relative path if the resource was created
using the ClassPathResource(String,Class) constructor, there was
previously no way to consistently obtain the absolute path to the
resource within the class path.

This commit addresses this shortcoming by introducing a new
getAbsolutePath() for consistently obtaining the absolute path to the
resource within the class path.

See gh-29083
Closes gh-29094
2022-09-06 20:09:24 +02:00
Sam Brannen 1052f48eb6 Clarify semantics of ClassPathResource.getPath()
This commit also improves the overall Javadoc in ClassPathResource.

See gh-29094
2022-09-06 20:08:21 +02:00
Sébastien Deleuze b8c1fc9202 Revert "Remove RuntimeHintsUtils"
This reverts commit 3e327f5641.
2022-09-06 18:21:34 +02:00
Sébastien Deleuze 3e327f5641 Remove RuntimeHintsUtils
Due to gh-29053, we can stop using RuntimeHintsUtils to
register SynthesizedAnnotation proxies.

Closes gh-29058
Closes gh-29059
2022-09-06 15:31:02 +02:00
Stephane Nicoll 903078a5b2 Do not silently return null when no constructor candidate is found
This commit updates ConstructorOrFactoryMethodResolver to throw an
exception if no constructor or factory method can be found for a given
bean definition.

This prevents code generation to happen on an incomplete view of the
bean to instantiate.

Closes gh-29052
2022-09-06 15:26:39 +02:00
Sam Brannen 8fbd2141b7 Move registerResourceIfNecessary() to ResourceHints
See gh-29083
2022-09-06 15:22:18 +02:00
Sam Brannen 5c2859ffa7 Make fields in ClassPathResource final 2022-09-06 14:47:19 +02:00
Sam Brannen 28c492cbdd Introduce RuntimeHintsUtils.registerResourceIfNecessary
This commit introduces a new registerResourceIfNecessary() method in
RuntimeHintsUtils that simplifies the registration of hints for
`classpath:` resources.

Closes gh-29083
2022-09-06 14:36:28 +02:00
Brian Clozel dd1e6b9412 Revisit request parameters access with HtmlUnit
Prior to this commit, the `HtmlUnitRequestBuilder` would "translate"
HtmlUnit web requests into Servlet requests using APIs that were not
clearly defined and meant for internal usage.

HtmlUnit 2.64.0 introduced a new `.getParameters()` API for collecting
`NameValuePair` parsed from the request URI or request body, depending
on the nature of the request. This arrangement is much more stable and
in line with HtmlUnit's expectations.

This commit uses this new API and makes HtmlUnit 2.64.0 a new minimum
requirement for using HtmlUnit integration with Spring Framework.
This also removes tests that were previously testing HtmlUnit's behavior
and using the API now marked as internal.

Closes gh-28240
2022-09-06 13:40:28 +02:00
Sam Brannen 10ade235e3 Prevent resource hint registration for pattern with leading slash
Prior to this commit, if a ResourcePatternHint was created with a
resource pattern with a leading slash, the hint was registered and
eventually converted to configuration for the GraalVM native image
compiler.

However, such a resource pattern is invalid for GraalVM. Consequently,
the registered resources were not available within the compiled native
image.

This commit ensures that registered patterns are applicable in a native
image by preventing creation of a ResourcePatternHint with a pattern
with a leading slash.

Closes gh-29088
2022-09-06 12:53:31 +02:00
Sam Brannen 04bb336b0b Polish ResourcePatternHints Javadoc 2022-09-06 12:53:31 +02:00
Sam Brannen dc07ca1d36 Polish AsyncExecutionTests 2022-09-06 12:53:31 +02:00
Sam Brannen 97b98c3378 Support default package for TypeReference in ResourceHintsPredicates
Prior to this commit, if the TypeReference supplied to
ResourceHintsPredicates.forResource(TypeReference,String) was for a
class declared in the default package (i.e., without a package), the
resolveAbsoluteResourceName() method incorrectly prepended two leading
slashes (//) to the absolute resource name, causing correct matches to
fail.

This commit fixes this by adding special handling for a TypeReference
without a package name. In addition, this commit introduces lenient
handling of resource names by consistently removing a leading slash in
ResourceHintsPredicates.forResource(*) methods. The latter aligns with
absolute resource path handling in other places in the framework, such
as ClassPathResource.

Closes gh-29086
2022-09-06 12:53:31 +02:00
Janne Valkealahti 135f9070c5 Add jni-config generation
This commit adds support generating graalvm `jni-config.json` file.

Configuration format for jni/reflection in graalvm is documented
to be exactly same so we can re-use facilities for reflection hints
which should be relatively clean for a user as also graalvm uses same
classes for both jni/reflection.

Closes gh-29007
2022-09-06 12:22:13 +02:00
Sam Brannen 6902ff77d9 Fix resource registration hints in the TestContext framework
Resource patterns registered for inclusion in a GraalVM native image
must not start with a leading slash.
2022-09-05 18:38:38 +02:00
Stephane Nicoll 6e93f1187c Move TestCompiler from generator to generate
This commit harmonizes the package space by moving the TestCompiler
infrastructure from the now outdated "generator" package to "generate".

Closes gh-29082
2022-09-05 16:30:19 +02:00
Stephane Nicoll 58b0251af1 Relocate TestGenerationContext to spring-core-test
This commit moves the test implementation for GenerationContext in
spring-core-test. This also removes the copy we had in testfixtures

See gh-28877
2022-09-05 16:21:17 +02:00
Sam Brannen e57b5f1dfc Register runtime hints for @Sql scripts
SqlScriptsTestExecutionListener now implements AotTestExecutionListener
in order to register run-time hints for SQL scripts used by test
classes and test methods annotated with @Sql if the configured or
detected SQL scripts are classpath resources.

Closes gh-29027
2022-09-05 14:15:19 +02:00
Sam Brannen e85e769f1c Introduce @Sql tests for AOT processing 2022-09-05 12:54:55 +02:00
Sam Brannen 35bbe9f99d Polishing 2022-09-05 12:51:14 +02:00
Sam Brannen ea132388c5 Introduce AotTestExecutionListener API in the TestContext framework
This commit introduces an AotTestExecutionListener API that extends
TestExecutionListener and allows a TestExecutionListener to opt in for
AOT processing support, analogous to what the AotContextLoader API does
for a SmartContextLoader.

Closes gh-29070
2022-09-05 12:10:29 +02:00
Sam Brannen c2dd6667f1 Revise method signature in TestRuntimeHintsRegistrar 2022-09-05 12:10:29 +02:00
Stephane Nicoll 16ff05ed86 Polish 2022-09-05 11:55:19 +02:00
Stephane Nicoll 3b36171926 Merge branch '5.3.x' 2022-09-05 07:24:07 +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 b0e723dbbb Delete obsolete test code
We no longer register reflection run-time hints for the SpringExtension
since that is covered by the JupiterConfigProvider in the GraalVM Native
Build Tools project.
2022-09-04 19:50:41 +02:00
Sam Brannen a68d4ae25c Register runtime hints for ActiveProfilesResolvers
This commit introduces automatic registration of runtime hints for
custom ActiveProfilesResolver implementations configured via the
`resolver` attribute in @ActiveProfiles.

Closes gh-29022
2022-09-04 18:59:12 +02:00
Sam Brannen 8d6d3f2698 Polishing 2022-09-04 17:51:48 +02:00
Sam Brannen afff849992 Add missing package-info.java file 2022-09-04 17:50:45 +02:00
Sam Brannen cbb30153fb Introduce StandardTestRuntimeHints in the TestContext framework
This commit introduces StandardTestRuntimeHints and migrates existing
hint registration from TestContextAotGenerator to this new class.

In addition, this commit removes a package cycle between context.aot and
context.web that was introduced in commit dc7c7ac22a.

See gh-29026, gh-29069
2022-09-04 17:44:19 +02:00
Sam Brannen bf0ac84a05 Introduce TestRuntimeHintsRegistrar in the TestContext framework
Although RuntimeHintsRegistrar can be implemented to register general
hints that should be applied for all testing infrastructure, certain
use cases require access to test classes and the
MergedContextConfiguration in order to register appropriate hints.

To address that, this commit introduces TestRuntimeHintsRegistrar as a
companion to the core RuntimeHintsRegistrar.

Closes gh-29069
2022-09-04 17:14:24 +02:00
Sam Brannen dc7c7ac22a Register runtime hint for @WebAppConfiguration's resource path
This commit introduces automatic registration of a runtime hint for
classpath resources configured via the `value` attribute in
@WebAppConfiguration.

Closes gh-29026
2022-09-04 16:45:06 +02:00
Sébastien Deleuze f6db2cc35f Use serializerOrNull in Kotlin Serialization support
Closes gh-29068
2022-09-04 16:05:37 +02:00
Sam Brannen ef7784f85e Register runtime hints for @TestPropertySource#locations
This commit introduces automatic registration of runtime hints for
classpath resources configured via the `locations` attribute in
@TestPropertySource as well as for detected default properties files.

Closes gh-29025
2022-09-04 15:19:56 +02:00
Sam Brannen dcf160e427 Consistently include leading slash for classpath: resources in the TCF 2022-09-04 15:19:56 +02:00
Sam Brannen 920fbb34c8 Register runtime hints for @ContextConfiguration#locations
This commit introduces automatic registration of runtime hints for
classpath resources configured via the `locations` attribute in
@ContextConfiguration.

Closes gh-29021
2022-09-03 17:25:46 +02:00
Sam Brannen c0040b9024 Polishing 2022-09-03 17:25:00 +02:00
Sam Brannen 36a2a62294 Polishing 2022-09-03 16:55:28 +02:00
Andy Wilkinson 0daaa1c38a Make QDox an implementation detail of spring-core-test
Previously, com.thoughtworks.qdox:qdox was declared as an api
dependency of spring-core-test despite it only being used in the
module's internals. This resulted in it unnecessarily appearing on the
compile classpath of consuming projects.

This commit moves qdox to be an implementation dependency, removing it
from the compile classpath of consuming projects but ensuring that it's
still available at runtime.

Closes gh-29066
2022-09-03 16:45:05 +02:00
Sébastien Deleuze f50c301387 Change BindingReflectionHintsRegistrar package
Move it to org.springframework.aot.hint.

See gh-28979
2022-09-02 19:31:26 +02:00
Brian Clozel 7ace1f9dc5 Align RuntimeHintsPredicates with new FieldMode
Closes gh-29063
2022-09-02 18:16:43 +02:00
Brian Clozel 4368e2563f Reinstate RuntimeHintsAgent tests
Closes gh-29062
2022-09-02 18:16:43 +02:00
Sébastien Deleuze 044f3728a3 Introduce @RegisterReflectionForBinding
This annotation and the related processor allows to
register reflection hints for data binding purpose
(class, fields, properties, record components for
the whole type hierarchy)

Closes gh-28979
2022-09-02 17:31:43 +02:00
Sébastien Deleuze aaffb8b27e Move BindingReflectionHintsRegistrar to spring-core
See gh-28979
2022-09-02 17:31:43 +02:00
Sam Brannen 6475523a53 Merge branch '5.3.x' 2022-09-02 16:42:07 +02:00
Sam Brannen 0389fcca7e Fix sporadically failing SpEL test 2022-09-02 16:41:44 +02:00
Sébastien Deleuze cc555d2ff4 Avoid shipping AWT classes in native images
This commit provides an alternative
java.beans.Introspector#findCustomizerClass implementation
via a GraalVM substitution that avoids to include thousands
of unused AWT classes in the native image.

Closes gh-29060
2022-09-02 15:06:50 +02:00
Sam Brannen cced3cba09 Register runtime hints for @TestExecutionListeners
Closes gh-29024
2022-09-02 14:53:49 +02:00
Sam Brannen 34635d7751 Register runtime hints for TestContextBootstrappers
This commit automatically registers runtime hints for
TestContextBootstrapper classes, including default bootstrappers as
well as any bootstrapper configured via @BootstrapWith.

Closes gh-29023
2022-09-02 14:40:09 +02:00
Sam Brannen 1cae054cf5 Polishing 2022-09-02 14:27:58 +02:00
Sam Brannen 549f4e7933 Register runtime hints for ApplicationContextInitializers in the TCF
This commit introduces automatic registration of runtime hints for
ApplicationContextInitializers configured via the `initializers`
attribute in @ContextConfiguration.

See gh-29021
2022-09-02 14:20:22 +02:00
Sam Brannen 51daeac86b Register runtime hints for ContextLoaders automatically in the TCF
This commit moves the registration of runtime hints for ContextLoaders
from TestContextRuntimeHints to TestContextAotGenerator.

This allows for automatic registration of any ContextLoader used,
including custom loaders declared via the `loader` attribute in
@ContextConfiguration.

See gh-29021
2022-09-02 14:20:11 +02:00
Sam Brannen 41b6f4e351 Commit changes to test 2022-09-02 13:17:48 +02:00
Sam Brannen 52712cecce Document reasons for hint registration in the TestContext framework 2022-09-02 13:15:32 +02:00
Sam Brannen dadfdb91d9 Stop registering SynthesizedAnnotation proxies in spring-test
See gh-29059
2022-09-02 13:10:18 +02:00
Sam Brannen 69f23095b8 Deprecate SynthesizedAnnotation and related methods
Since Spring no longer adds the SynthesizedAnnotation interface to the
JDK dynamic proxy used to synthesize an annotation, this commit
officially deprecates SynthesizedAnnotation and related methods in
RuntimeHintsUtils.

See gh-29041, gh-29054
Closes gh-29053
2022-09-02 12:04:17 +02:00
Sam Brannen 0ec03a8dd6 Stop implementing SynthesizedAnnotation in annotation proxies
SynthesizedAnnotation was originally introduced as a convenience for
easily detecting if an annotation had been synthesized by Spring via a
simple `if (myAnnotation instanceof SynthesizedAnnotation)` check.

However, the introduction of SynthesizedAnnotation in the JDK dynamic
proxy for a synthesized annotation results in a separate proxy class
for each annotation synthesized by Spring, and this causes issues with
GraalVM native images since users and framework developers must always
ensure that the additional proxy classes are registered.

This commit completely removes the use of SynthesizedAnnotation in
synthesized annotation proxies. This change allows the proxy class for
an annotation to be reused for a synthesized annotation of the same
annotation type.

Consequently:

- Extra proxy classes are not generated on the JVM or in a native image.
- Extra proxy classes are not required to be registered for a native image.

Closes gh-29041
2022-09-02 11:27:00 +02:00
Sébastien Deleuze 7214b1e03c Merge branch '5.3.x' 2022-09-02 11:19:55 +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
Brian Clozel fc47d25bc7 Polish
See gh-26320
2022-09-02 10:55:40 +02:00
Sam Brannen 73abd58202 Polishing 2022-09-02 10:23:53 +02:00
Phillip Webb 505da5c602 Migrate hint registration to shortcuts
Migrate code to make use of the `MemberCategory` and `FieldMode`
shortcuts.

See gh-29011
2022-09-01 17:26:06 -07:00
Phillip Webb bc0bf1fac3 Add additional shortcuts for hint registration
Add `MemberCategory` and `FieldMode` shortcuts for type registration.
Helper `builtWith` methods have also been extracted to the Hint types
to allow general reuse (for example with `registerTypes`).

See gh-29011
2022-09-01 17:25:46 -07:00
Phillip Webb da1005cd66 Add FieldMode for field hints and ensure that it cannot be downgraded
Add a `FieldMode` enum analogous to `ExecutableHint` and update
`FieldHint` to ensure that registration cannot downgrade `WRITE`
to `READ`.

Fixes gh-29055
2022-09-01 17:25:43 -07:00
Phillip Webb 0bd923b0a7 Polishing 2022-09-01 16:28:02 -07:00
Phillip Webb cea06e6a9e Polish ReflectionHints and TypeHint method order 2022-09-01 16:27:54 -07:00
Phillip Webb cfd37d948d Reduce visibility of hint factory methods
Reduce the visibility of hint factory methods that return a `Builder`.
Since the `build()` method of the `Builder` is package-private the
factory methods can also be package-private.
2022-09-01 13:37:08 -07:00
Sam Brannen a5584dcaa6 Merge branch '5.3.x'
# Conflicts:
#	spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java
2022-09-01 17:44:24 +02:00
Sam Brannen 66b9a52cec Suppress warning in test 2022-09-01 17:39:15 +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
Brian Clozel 289d378aeb Polish
This fixes an additional case where invoked methods are public but the
declaring class is package private.

Fixes gh-29046
2022-09-01 15:14:58 +02:00
Brian Clozel c470262c8e Rewrite ConcurrentLruCache implementation
Prior to this commit, the `ConcurrentLruCache` implementation would not
perform well under certain conditions. As long as the cache capacity was
not reached, the cache would avoid maintaining an eviction queue
(reordering entries depending with least/most recently read). When the
cache capacity was reached, the LRU queue was updated for each
read/write operation. This decreased performance significantly under
contention when the capacity was reached.

This commit completely rewrites the internals of `ConcurrentLruCache`.
`ConcurrentLruCache` is now a specialized version of the
`ConcurrentLinkedHashMap` [1]. This change focuses on buferring read and
write operations, only processing them at certain times to avoid
contention.

When a cached entry is read, a read operation is queued and buffered
operations are drained if the buffer reached a fixed limit. When a new
cache entry is added or removed, a write operation is queued and
triggers a drain attempt. When the capacity is outgrown, the cache polls
items from the eviction queue, which maintains elements with the
least recently used ones first. Entries are removed until the capacity
is under control.

The behavior described here and the buffer sizes are optimized with the
number of available processors in mind. Work is localized as much as
possible on a per-thread basis to avoid contention on the eviction queue.

The new implementation has been tested with the JMH benchmark provided
here, comparing the former `COncurrentLruCache`, the new implementation
as well as the `ConcurrentLinkedHashMap` [1].

When testing with a cache reaching capacity, under contention, with a
10% cache miss, we're seeing a 40x improvement compared to the previous
implementation and performance on par with the reference.
See [2] for how to replicate the benchmark.

[1] https://github.com/ben-manes/concurrentlinkedhashmap
[2] https://github.com/spring-projects/spring-framework/wiki/Micro-Benchmarks

Closes gh-26320
2022-08-31 19:10:50 +02:00
Johnny Lim 706c1ec8dd Polish 2022-08-31 23:59:51 +09:00
Sam Brannen 2ecc37fbef Reintroduce exclusion of dom4j for findbugs
The removal of the exclusion prevented spring-webmvc from being imported
into Eclipse IDE due to conflicting versions of dom4j on the classpath.

See gh-29045
2022-08-31 16:35:13 +02:00
Sam Brannen b22d01f5f3 Polish TestContextRuntimeHints 2022-08-31 16:35:13 +02:00
Sam Brannen 40647bdaf6 Register hints for test execution event annotations in the TCF
See gh-29044
2022-08-31 16:35:13 +02:00
Sam Brannen 2d35bbd74e Move TestContextRuntimeHints to aot.hint package 2022-08-31 16:35:13 +02:00
Sam Brannen 98c74059e0 Polish Javadoc 2022-08-31 16:35:13 +02:00
Brian Clozel 5757429ea5 Upgrade Mockito to 4.7.0 2022-08-31 16:24:15 +02:00
Brian Clozel fa475d0b63 Upgrade kotlinx dependencies 2022-08-31 16:23:53 +02:00
Brian Clozel 7cb1a4e876 Upgrade to Reactor 2022.0.0-M5 2022-08-31 16:23:14 +02:00
Brian Clozel 5a7189a483 Upgrade to Netty 4.1.80 2022-08-31 16:22:47 +02:00
Brian Clozel 3c22404bce Fix RuntimeHintsAgent instrumentation for method invocation
Prior to this commit, the `RuntimeHintsAgent` would instrument
`Method.invoke` in a way that fails when invoked methods are not public.

This commit ensures that before delegating the invocation call, the
instrumentation makes the method accessible before delegating the call.

Fixes gh-29046
2022-08-31 15:19:31 +02:00
Brian Clozel f877f81ae4 Move Netty 5 dependency to Framework platform 2022-08-30 21:58:41 +02:00
Andy Wilkinson a5fb55fd6d Replace dependency management plugin with built-in platform support 2022-08-30 17:03:24 +01:00
Sam Brannen 741ee960e2 Register runtime hints for TestContext framework classes and annotations
This commit introduces TestContextRuntimeHints which is a
RuntimeHintsRegistrar implementation that makes core types and
annotations from the Spring TestContext Framework available at runtime
within a GraalVM native image.

TestContextRuntimeHints is registered automatically via the
"META-INF/spring/aot.factories" file in spring-test.

This commit also modifies TestContextAotGeneratorTests to assert the
expected runtime hints registered by TestContextRuntimeHints as well as
runtime hints for TestExecutionListener and ContextCustomizerFactory
implementations registered by SpringFactoriesLoaderRuntimeHints.

Closes gh-29028
Closes gh-29044
2022-08-30 15:31:02 +02:00
Arjen Poutsma 8a7e839ad0 Polishing 2022-08-30 15:22:26 +02:00
Arjen Poutsma 4b18cc94ea Merge branch '5.3.x' 2022-08-30 15:15:57 +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 3eaf259f2d Polishing 2022-08-30 12:19:13 +02:00
Arjen Poutsma b5b51e73fc Merge branch '5.3.x' 2022-08-30 12:18:51 +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 0ebc86c1af Merge branch '5.3.x'
# Conflicts:
#	spring-test/src/main/java/org/springframework/test/context/web/socket/MockServerContainerContextCustomizerFactory.java
#	spring-test/src/test/java/org/springframework/test/context/web/socket/WebSocketServletServerContainerFactoryBeanTests.java
2022-08-28 18:48:21 +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 c24e98e51b Avoid reflection for instantiating MockServerContainerContextCustomizer
Since MockServerContainerContextCustomizerFactory already has a
`webSocketPresent` check, there should be no need to instantiate
MockServerContainerContextCustomizer via reflection.

See gh-29028
Closes gh-29035
2022-08-28 18:09:05 +02:00
Sam Brannen 92b582701e Skip ContextCustomizerFactory that cannot be loaded
With this commit, if a ContextCustomizerFactory cannot be loaded due to
a ClassNotFoundException or NoClassDefFoundError, we skip it and log a
DEBUG message.

This aligns with the "skipping" logic already in place for
TestExecutionListeners.

Closes gh-29034
2022-08-28 18:09:05 +02:00
Sam Brannen ab20a189c5 Consistent logging for skipped TestExecutionListeners
With this commit we now log an identical message (without a stack
trace) for a TestExecutionListener skipped due to a
ClassNotFoundException like we already do for a listener skipped due to
a NoClassDefFoundError.
2022-08-28 18:09:05 +02:00
Sam Brannen 7f88f315a4 Introduce logging for ContextCustomizer[Factory] to improve diagnostics
Prior to this commit, we logged which default TestExecutionListeners
were discovered and which listeners were used, but we did not log
anything for ContextCustomizerFactory and ContextCustomizer.

This commit therefore introduces similar logging for
ContextCustomizerFactory and ContextCustomizer to improve diagnostics.

Closes gh-29036
2022-08-28 18:08:12 +02:00
Sam Brannen aa7ef79478 Apply "instanceof pattern matching" in spring-test 2022-08-28 17:51:52 +02:00
Sam Brannen b50415062b Clean up warnings and polish tests
This commit also modifies ResourceWebHandlerTests.getResourceFromFileSystem()
so that it passes in the IDE.
2022-08-26 15:20:16 +02:00
Sam Brannen e53c7ae6f5 Polish Javadoc and internals of the TestContext framework 2022-08-26 13:53:10 +02:00
Sam Brannen c32ff17821 Revise @Nullable declarations in the TestContext framework 2022-08-26 12:21:47 +02:00
Sébastien Deleuze d16fa82888 Remove remaining native build-time class initializations
See oracle/graal#4673 related issue.

Closes gh-29018
2022-08-26 09:29:17 +02:00
Sébastien Deleuze 3e9b57106e Refine TypeHint.Builder#onReachableType Javadoc 2022-08-26 08:35:18 +02:00
Sébastien Deleuze 08f636b691 Introduce TypeHint.Builder#onReachableType(Class<?>)
Closes gh-29017
2022-08-26 08:34:54 +02:00
Sam Brannen 7671d29899 Add missing @Nullable declaration in AotTestMappings 2022-08-25 16:53:54 +02:00
Sam Brannen 593bd064e1 Polishing 2022-08-25 13:23:04 +02:00
Sam Brannen d467db4b9e Make TestClassScanner and TestContextAotGenerator public
This commit makes TestClassScanner and TestContextAotGenerator public so
that the Spring Boot team can take over implementation of the
TestAotProcessor to integrate it into the AOT and native build plugins.
2022-08-25 12:03:11 +02:00
Arjen Poutsma 626739d93f Polishing 2022-08-25 11:31:47 +02:00
Arjen Poutsma 9c33d2707a Introduce support for Netty 5 Buffer
This commit introduces support for Netty 5's Buffer, in the form of
Netty5DataBuffer. Because of the new API offered by Buffer, several
changes have been made to the DataBuffer API:

- CloseableDataBuffer is a simpler alternative to PooledDataBuffer, and
  implemented by Netty5DataBuffer. DataBufferUtils::release can now
  handle CloseableDataBuffer as well as PooledDataBuffer.
- PooledDataBuffer::touch has been moved into a separate interface:
  TouchableDataBuffer, which is implemented by Netty5DataBuffer.
- The capacity of DataBuffers can no longer be reduced, they can only
  grow larger. As a consequence, DataBuffer::capacity(int) has been
  deprecated, but ensureWritable (formally ensureCapacity) still exists.
- DataBuffer::slice and retainedSlice have been deprecated in favor of
  split, a new method that ensures that memory regions do not overlap.
- DataBuffer::asByteBuffer has been deprecated in favor of toByteBuffer,
  a new method that returns a copy, instead of shared data.
- DataBufferFactory::allocateBuffer has been deprecated in favor of
  allocateBuffer(int).

Closes gh-28874
2022-08-25 11:00:22 +02:00
Stephane Nicoll 8a61866ee2 Harmonize registration of reflection hints
Closes gh-29011
2022-08-24 19:34:12 +02:00
Stephane Nicoll 7ca57b7e80 Use consistent registration API in TypeHint.Builder
This commit adapts the registration of fields, constructors, and methods
to provide the same convenience than the reflection-based one available
in ReflectionHints.

See gh-29011
2022-08-24 19:32:02 +02:00
Stephane Nicoll 5aa8583159 Add shortcut to register an executable with a mode
See gh-29011
2022-08-24 19:32:02 +02:00
Stephane Nicoll c164b918c0 Apply consistent RuntimeHints defaults
This commit harmonizes the registration of an executable so that
the default method and the method that takes an empty customizer
produces the same hint. The same applies to the readable flag of
a field hint.

Rather than returning a list of executable modes, the "highest" mode
is retained.

See gh-29011
2022-08-24 19:32:01 +02:00
Sam Brannen 019785a72e Introduce CLI for triggering AOT test context processing
This commit introduces TestAotProcessor which replaces
ProcessTestsAheadOfTimeCommand, removes the dependency on picocli, and
aligns with the implementation of the AotProcessor in Spring Boot.

TestAotProcessor is a command-line application (CLI) that scans the
provided classpath roots for Spring integration test classes and then
generates AOT artifacts for those test classes in the provided output
directories.

This CLI is only intended to be used by build tools.

Closes gh-28825
2022-08-24 17:12:34 +02:00
Sam Brannen 5115deb5e3 Introduce CLI for triggering AOT test context processing
This commit introduces ProcessTestsAheadOfTimeCommand, a command-line
application (CLI) that scans the provided classpath roots for Spring
integration test classes and then generates AOT artifacts for those
test classes in the provided output directories.

This CLI is only intended to be used by build tools.

Closes gh-28825
2022-08-23 16:39:59 +02:00
Sam Brannen feb2a30910 Improve precondition checks in TestClassScanner 2022-08-23 16:03:06 +02:00
Stephane Nicoll 41e8683781 Polish 2022-08-23 14:41:32 +02:00
Stephane Nicoll 560f53dbf7 Polish 2022-08-23 14:34:20 +02:00
Stephane Nicoll c6bcf79c0e Add hint for use of Qualifier in meta-annotations
Closes gh-29000
2022-08-23 14:31:09 +02:00
Sébastien Deleuze 2f920e8fb3 Polish JacksonModulesRuntimeHints
Closes gh-29001
2022-08-23 13:49:53 +02:00
Sam Brannen 8a6c1ba198 Introduce AOT run-time support in the TestContext framework
This commit introduces initial AOT run-time support in the Spring
TestContext Framework.

- DefaultCacheAwareContextLoaderDelegate: when running in AOT mode, now
  loads a test's ApplicationContext via the AotContextLoader SPI
  instead of via the standard SmartContextLoader and ContextLoader SPIs.

- DependencyInjectionTestExecutionListener: when running in AOT mode,
  now injects dependencies into a test instance using a local instance
  of AutowiredAnnotationBeanPostProcessor instead of relying on
  AutowireCapableBeanFactory support.

Closes gh-28205
2022-08-23 13:41:24 +02:00
Sam Brannen ada0880f3c Introduce AotTestMappings and AotTestMappingsCodeGenerator
TestContextAotGenerator now uses AotTestMappingsCodeGenerator to
generate a AotTestMappings__Generated.java class which is loaded in
AotTestMappings via reflection in order to retrieve access to
ApplicationContextIntializers generated during AOT processing.

Furthermore, the processAheadOfTimeAndGenerateAotTestMappings() method
in TestContextAotGeneratorTests now performs a rather extensive test
including:

- emulating TestClassScanner to find test classes
- processing all test classes and generating ApplicationContextIntializers
- generating mappings for AotTestMappings
- compiling all generated code
- loading AotTestMappings
- using AotTestMappings to instantiate the generated ApplicationContextIntializer
- using the AotContextLoader API to load the AOT-optimized ApplicationContext
- asserting the behavior of the loaded ApplicationContext

See gh-28205
Closes gh-28204
2022-08-23 13:41:16 +02:00
Sam Brannen b0d65709ac Test XML, Web, & @TestPropertySource AOT support
See gh-28204, gh-28205
2022-08-23 13:41:07 +02:00
Sam Brannen 84c377965c Introduce AotContextLoader SPI in the TestContext framework
This commit introduces a dedicated AotContextLoader extension of
SmartContextLoader and reverts the recent changes to the existing
contract for SmartContextLoader. This allows existing
SmartContextLoader implementations to continue working unaffected by
AOT support unless they opt into AOT support by explicitly implementing
the new AotContextLoader contract.

In addition, existing SmartContextLoader implementations in the
spring-test module have been modified to implement AotContextLoader
instead of SmartContextLoader. This allows the core framework to
provide built-in AOT support in the TestContext framework, and it also
allows third-party extensions to built-in SmartContextLoaders to
participate in AOT processing and run-time support transparently (or at
least as transparent as possible).

Closes gh-28906
2022-08-23 13:40:58 +02:00
Sam Brannen c1a6bfc701 Introduce initial support for processing test contexts ahead-of-time
This commit introduces TestContextAotGenerator for processing Spring
integration test classes and generating AOT artifacts. Specifically,
this class performs the following.

- bootstraps the TCF for a given test class
- builds the MergedContextConfiguration for each test class and tracks
  all test classes that share the same MergedContextConfiguration
- loads each test ApplicationContext without refreshing it
- passes the test ApplicationContext to ApplicationContextAotGenerator
  to generate the AOT optimized ApplicationContextInitializer
  - The GenerationContext passed to ApplicationContextAotGenerator uses
    a feature name of the form "TestContext###_", where "###" is a
    3-digit sequence ID left padded with zeros.

This commit also includes tests using the TestCompiler to verify that
each generated ApplicationContextInitializer can be used to populate a
GenericApplicationContext as expected.

See gh-28204
2022-08-23 13:40:48 +02:00
Sébastien Deleuze 0973348bde Add classpath checks to JacksonModulesRuntimeHints
Closes gh-29001
2022-08-23 12:55:26 +02:00
Sébastien Deleuze 5525b17f19 Add missing condition in JacksonModulesRuntimeHints
Closes gh-29001
2022-08-23 12:11:42 +02:00
Stephane Nicoll 56551032e3 Merge pull request #28355 from ben-enfuse-io
* pr/28355:
  Treat MariaDB as an independent database type

Closes gh-28355
2022-08-23 07:46:28 +02:00
ben-enfuse-io 21577c4777 Treat MariaDB as an independent database type
See gh-28355
2022-08-23 07:44:02 +02:00
Stephane Nicoll 455715899d Infer proxy on @Lazy-annotated injection points
This commit makes use of the new `getLazyResolutionProxyClass` on
`AutowireCandidateResolver` to detect if a injection point requires
a proxy.

Closes gh-28980
2022-08-22 20:48:02 +02:00
Sam Brannen e5f9bb76b1 Declare covariant return type in DefaultGenerationContext.withName()
Prior to this commit, if infrastructure code working directly with an
instance of DefaultGenerationContext invoked withName() on that
instance, the new GenerationContext had to be cast from
GenerationContext to DefaultGenerationContext in order for the
infrastructure to continue working with the DefaultGenerationContext
API -- for example, the writeGeneratedContent() method which is not
defined in the GenerationContext API.

This commit makes use of a covariant return type by declaring that
DefaultGenerationContext.withName() returns a DefaultGenerationContext.
2022-08-22 16:41:20 +02:00
Sam Brannen 9ab046bdbb Introduce complete DefaultGenerationContext constructor
Prior to this commit, it was possible to create a DefaultGenerationContext
based on a ClassNameGenerator and GeneratedFiles; however, there was no way
to create a DefaultGenerationContext that reused an existing RuntimeHints
instance which is necessary in certain use cases -- for example, in the
TestContext framework where multiple GenerationContexts are created
based on shared instances of GeneratedFiles and RuntimeHints.

This commit addresses this by introducing a public
DefaultGenerationContext(ClassNameGenerator,GeneratedFiles,RuntimeHints)
constructor.
2022-08-22 16:41:11 +02:00
Stephane Nicoll 40de029bf8 Polish 2022-08-22 16:32:53 +02:00
Juergen Hoeller 4eb84a0537 Introduce getLazyResolutionProxyClass mechanism in AutowireCandidateResolver SPI
See gh-28980
2022-08-22 16:24:37 +02:00
Stephane Nicoll 8a51e31069 Make sure that AnnotationAwareOrderComparator is configured with AOT
Closes gh-28988
2022-08-22 14:18:42 +02:00
Juergen Hoeller 9b2a40a3bc Lazy Validator resolution in MethodValidationPostProcessor
Closes gh-28990
2022-08-22 14:07:42 +02:00
Sébastien Deleuze daf2d940e4 Remove specific JDK dynamic proxy configuration
Further refinements will be required for
MethodValidationPostProcessor since @Lazy
used by Spring Boot is not supported yet
for that use case.

See gh-28980
2022-08-22 10:53:12 +02:00
Sébastien Deleuze ebf6de8f5d Infer JDK dynamic proxies for Spring beans
See gh-28980
2022-08-22 07:58:15 +02:00
Sam Brannen a9466437c8 Merge branch '5.3.x'
# Conflicts:
#	spring-test/src/main/java/org/springframework/test/context/cache/DefaultCacheAwareContextLoaderDelegate.java
2022-08-21 15:23:33 +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
Stephane Nicoll 7637a8d0cf Polish 2022-08-20 10:14:32 +02:00
Juergen Hoeller 427e5f5899 Final merged bean definition clearing in freezeConfiguration
Instead of individual last-minute clearing in markBeanAsCreated, the factory clears all merged bean definitions in freezeConfiguration, retaining the changes of merged bean definition post-processing after that point (in particular in refreshForAotProcessing).

Closes gh-28948
2022-08-19 17:30:59 +02:00
Sam Brannen 7c91776d3d Clean up warnings in tests 2022-08-19 16:11:09 +02:00
Sam Brannen 409ee9234d Merge branch '5.3.x' 2022-08-19 16:06:14 +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
Stephane Nicoll 4fb4e54c73 Introduce PersistenceManagedTypes and AOT processing of managed entities
This commit adds PersistenceManagedTypes, an abstraction that represents
what typically happens at runtime when a persistence unit is built based
on classpath scanning.

PersistenceManagedTypesScanner extracts the logic that used to be in
DefaultPersistenceUnitManager and the latter can be configured with
a PersistenceManagedTypes instance.

This commits adds a bean registration AOT contribution that retrieves
the result of the configured instance and replaces it with the list
of managed entities. This has the result of making sure scanning, if
any, does not happen at runtime. This also could help if additional
hints for managed entities are required.

Closes gh-28287
2022-08-19 15:27:44 +02:00
Stephane Nicoll eac616a83e Restore support for package private ReflectiveProcessor
See gh-28975
2022-08-18 14:27:59 +02:00
Stephane Nicoll d6afa8df2d Improve registration of the same hint for multiple classes
Based on the feedback in #28977 an easy way to create a list of
type references based on a vararg of classes is helpful when
registering the same hints for several types.
2022-08-18 06:52:34 +02:00
Stephane Nicoll 4556895e6e Expose registrar for @Reflective
This commit exposes the logic of processing `@Reflective` on beans so
that it can be reused in custom arrangements.

Closes gh-28975
2022-08-17 14:33:09 +02:00
Sam Brannen ef7ab768e7 Polishing 2022-08-17 12:03:10 +02:00
Sébastien Deleuze 06d9db154e Introduce CachingBeanRegistrationAotProcessor
It contributes proxy hints for interfaces when class
proxying is not forced.

Closes gh-28943
2022-08-17 11:38:12 +02:00
Sébastien Deleuze 491b7771d0 Register proper caching annotation runtime hints
See gh-28943
2022-08-17 11:36:24 +02:00
Sam Brannen 8fe6a9f537 Handle NoClassDefFoundError consistently for skipped TestExecutionListener
Commit d1b65f6d3e introduced a regression for the handling of
NoClassDefFoundError when skipping a TestExecutionListener that cannot
be loaded. Specifically, the DEBUG log message changed and included the
stack trace; whereas, it previously did not include the stack trace.

This commit consistently handles NoClassDefFoundError for a skipped
TestExecutionListener, whether a default listener or a listener
registered via @TestExecutionListeners and aligns with the previous
behavior by omitting the stack trace for a NoClassDefFoundError.

Closes gh-28962
2022-08-17 11:25:51 +02:00
Sam Brannen 7e8d6dbd45 Remove obsolete HintType.CLASS_PROXIES enum constant
See gh-28972
2022-08-17 11:16:45 +02:00
Stephane Nicoll 9846d28ae6 Remove support for declaring class proxies hints
Closes gh-28972
2022-08-17 09:25:03 +02:00
Stephane Nicoll f4389c3114 Restore ANNOTATION_HINT in a deprecated form for the time being 2022-08-16 16:18:04 +02:00
Stephane Nicoll b03d0479e4 Merge branch 'gh-28967'
Closes gh-28967
2022-08-16 15:52:04 +02:00
Stephane Nicoll 494bca727f Disable RuntimeHints tests with the agent
Tests with the agent are broken now that hints for an annotation is
no longer required if the annotated element has an introspection hint.

See gh-28967
2022-08-16 15:42:52 +02:00
Stephane Nicoll 4f0c879778 Rationalize hints required for annotations
This commit updates RuntimeHintsUtils to focus on registering a JDK
proxy only as annotations of annotated elements that have at least
an introspection hints are visible out-of-the-box.

This commit also removes unnecessary hints and adapt `@Reflective` to
detect if a hint is required using the introduced
MergedAnnotation#isSynthesizable.

See gh-28967
2022-08-16 15:42:52 +02:00
Stephane Nicoll 32346b8382 Introduce isSynthesizable in MergedAnnotation
This commit adds the ability to check if a the annotation managed by
a MergedAnnotation is synthesizable. This makes it easier to register
a JDK proxy hint if necessary

See gh-28967
2022-08-16 15:42:52 +02:00
Sam Brannen 653552aa6f Make DefaultGenerationContext(GeneratedClasses,...) package private
The DefaultGenerationContext constructor which accepts an instance of
GeneratedClasses is now package private since GeneratedClasses can only
be created within the `org.springframework.aot.generate` package.
2022-08-16 12:06:40 +02:00
Sam Brannen 36fa8bd26b Remove unused constructors in TestGenerationContext 2022-08-16 12:06:40 +02:00
Arjen Poutsma 59c2f4c069 Allow null for ResponseEntity.HeadersBuilder::eTag
Closes gh-28947
2022-08-16 12:02:00 +02:00
Arjen Poutsma ef178d24ec Merge branch '5.3.x' 2022-08-16 11:24:01 +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
Arjen Poutsma cb8163b8c7 Updated Java 17 version in sdkmanrc 2022-08-16 11:00:20 +02:00
Stephane Nicoll 9a1b7c5e47 Allow target type of a cglib proxy to be visible
This commit updates the hints of a Cglib proxy's target type so that
methods can be invoked and constructors can be introspected. The former
is needed as a cglib proxy invokes the target type via reflection. As
for that latter, this is required at least by
Enhancer#filterConstructors.

See gh-28954
2022-08-16 08:30:37 +02:00
Sam Brannen c58c827291 Polishing 2022-08-15 19:53:21 +02:00
Sam Brannen 40f9fe0874 Make eclipse task for spring-core depend on JavaPoet and Objenesis tasks 2022-08-13 16:18:34 +02:00
Sam Brannen d6d629a8eb Clean up warnings in CGLIB fork 2022-08-13 16:03:28 +02:00
Stephane Nicoll 6ba31acf35 Polish "Add support for Async invocation in a native image"
This registers the hints if the annotation post processor is active,
rather than statically.

See gh-28710
2022-08-12 17:43:48 +02:00
Stephane Nicoll 0229cc45a0 Add support for Async invocation in a native image
This commit adds necessary hints so that Async-annotated method can be
discovered in a native image.

Closes gh-28710
2022-08-12 16:34:13 +02:00
Stephane Nicoll 3086d90e7d Add the necessary hints for use of Cglib proxies
This commit expands GeneratedClassHandler to allow invocation of
declared fields and methods. Generated proxies have a number of
internal fields and methods that are invoked via reflection.

See gh-28954
2022-08-12 16:27:10 +02:00
Stephane Nicoll 7c2453c373 Integrate class proxy generation in AOT processing
This commit updates ApplicationContextAotGenerator to register a
handler that process Cglib generated classes. The handler registers
such classes to the GeneratedFiles and provide a hint so that it
can be instantiated using reflection.

Closes gh-28954
2022-08-12 12:17:13 +02:00
Juergen Hoeller d6f73994c2 Fix malformed HTML in CGLIB javadoc
See gh-28955
2022-08-12 12:14:18 +02:00
Juergen Hoeller 7fa5b8dcb5 Turn CGLIB patch into full CGLIB fork in spring-core
Closes gh-28955
2022-08-12 11:38:43 +02:00
Sam Brannen a052f9a34e Polishing 2022-08-11 20:43:35 +02:00
Sam Brannen 7631a09405 Do not register SynthesizedAnnotation proxy for @AliasFor
Closes gh-28953
2022-08-11 20:32:03 +02:00
Sam Brannen 0207f3a55f Polishing 2022-08-11 19:41:56 +02:00
Sébastien Deleuze 5c68a278b5 Add SchedulerFactoryBean runtime hints
Also require oracle/graalvm-reachability-metadata#19.

Closes gh-28725
2022-08-11 15:42:53 +02:00
Stephane Nicoll 6ad7b85c27 Merge branch '5.3.x' 2022-08-11 13:31:58 +02:00
Stephane Nicoll dfc06eda7a Upgrade Java 8 version in CI image and .sdkmanrc 2022-08-11 13:31:36 +02:00
Stephane Nicoll d1abdff89c Merge branch '5.3.x' 2022-08-11 10:44:33 +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
Juergen Hoeller 293e296d59 Reflectively invoke getIdentifier method (for compatibility with Hibernate 6)
Closes gh-28855
2022-08-11 00:55:33 +02:00
Juergen Hoeller 38c9e7f629 Polishing 2022-08-10 23:30:27 +02:00
Juergen Hoeller b31a15851e Support for pre-generated CGLIB proxy classes (in AOT scenarios)
Includes runtime storing of generated classes to a directory specified by the "cglib.generatedClasses" system property. Avoids lazy CGLIB fast-class generation and replaces generated Enhancer and MethodWrapper key classes with equivalent record types. Introduces support for early type determination in InstantiationStrategy, AopProxy and SmartInstantiationAwareBeanPostProcessor - in order to trigger CGLIB class generation in refreshForAotProcessing (through early determineBeanType calls for bean definitions).

Closes gh-28115
2022-08-10 23:30:19 +02:00
Stephane Nicoll 496b1879ab Merge branch '5.3.x' 2022-08-09 15:32:27 +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 005713066c Freeze configuration before invoking MBDPP instances
This commit updates refresh for AOT processing so that the configuration
is frozen before invoking MergedBeanDefinitionPostProcessor instances.
This makes sure that post-processed MergedBeanDefinitions are kept in
cache and not lost if a component attempts to clear the metadata cache.

Closes gh-28941
2022-08-09 13:29:14 +02:00
Stephane Nicoll 0a9db7cc47 Revert "Make sure inferred destroy method is set on the original bean definition"
This reverts commit 2e1538a20b.
2022-08-09 11:31:56 +02:00
Stephane Nicoll cd2b7afc87 Avoid reflection on OptionalValidatorFactoryBean
Closes gh-28939
2022-08-08 16:53:53 +02:00
Stephane Nicoll 2e1538a20b Make sure inferred destroy method is set on the original bean definition
This commit updates InitDestroyAnnotationBeanPostProcessor to mutate
the original bean definition rather than the merged one that can be
recreated without it if the cache gets stale.

See gh-28215
2022-08-08 14:33:00 +02:00
Stephane Nicoll 3c76437868 Update RegisteredBean to take a ConfigurableListableBeanFactory
This allows to have access to `getBeanDefinition` if the original
bean definition needs to be retrieved.

See gh-28936
2022-08-08 14:00:49 +02:00
Stephane Nicoll 832889d801 Polish 2022-08-08 11:31:38 +02:00
Sam Brannen a875db4692 Document limitations of @CompileWithTargetClassAccess
Specifically, @CompileWithTargetClassAccess cannot be used with
@RepeatedTest and @ParameterizedTest methods since the
CompileWithTargetClassAccessExtension cannot support @TestTemplate
invocations.
2022-08-06 14:57:35 +03:00
Sam Brannen 1e8bc1b0fb Polishing 2022-08-06 14:42:19 +03:00
Sam Brannen 7d364bba72 Clean up warnings 2022-08-06 14:41:54 +03:00
Sam Brannen 0944c9a99c Remove throws IOException from DefaultGenerationContext.writeGeneratedContent()
The `throws` declaration is unnecessary since writeGeneratedContent()
will never throw an IOException.
2022-08-06 14:34:04 +03:00
Sam Brannen a466179bc8 Polish and sync TestGenerationContext implementations
- new constructor for providing InMemoryGeneratedFiles
- writeGeneratedContent() now throws UncheckedIOException
2022-08-06 14:08:49 +03:00
Sam Brannen 1de0207874 Rename tests due to change in gh-28927 2022-08-05 13:59:14 +03:00
Sam Brannen 853407b6f8 Polishing 2022-08-05 13:57:28 +03:00
Stephane Nicoll 2cc4486e3d Rename ApplicationContextAotGenerator entry point
Closes gh-28927
2022-08-05 10:19:06 +02:00
Stephane Nicoll 2475523e19 Merge branch '5.3.x' 2022-08-05 10:10:16 +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
Stephane Nicoll 9264d97880 Restore GeneratedTypeReference
Closes gh-28926
2022-08-04 16:30:59 +02:00
Vedran Pavic 7e719fe3f8 Use Jakarta EE XML namespaces instead of Java EE
Closes gh-28903
2022-08-04 13:24:30 +02:00
Sam Brannen 31503df415 Fix Javadoc link syntax plus polishing 2022-08-04 13:52:40 +03:00
Johnny Lim 9fea0be33e Upgrade to Dokka Gradle plugin 1.7.10
Closes gh-28912
2022-08-04 11:37:04 +02:00
Brian Clozel fea29ea4cd Upgrade Gradle plugins 2022-08-04 11:29:34 +02:00
Brian Clozel 9e71889ed9 Merge branch '5.3.x' 2022-08-04 11:02:52 +02:00
Chanhyeong Cho 8685b2f5bf Fix broken kdoc-api links in kotlin.adoc
Fixes gh-28908
2022-08-04 11:02:02 +02:00
Sam Brannen 843221b448 Fix broken Javadoc links
See gh-28906
2022-08-04 11:51:56 +03:00
Stephane Nicoll 6c81ac9454 Merge branch '5.3.x' 2022-08-04 10:04:00 +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
Stephane Nicoll e50db8c8c5 Make sure that ImportAwareAotBeanPostProcessor has role infrastructure
See gh-28915
2022-08-04 09:37:17 +02:00
Stephane Nicoll 332d4a4c9c Apply same order than original BPP
This commit updates ImportAwareAotBeanPostProcessor to be priority
ordered, with the same order as its original BeanPostProcessor. This
makes sure that infrastructure beans can be post-processed if
necessary

See gh-28915
2022-08-04 09:35:11 +02:00
Stephane Nicoll e5f9574800 Fix test
Contribution was not applied on the actual use case

See gh-28915
2022-08-04 09:32:45 +02:00
Brian Clozel 34266f22c7 Merge branch '5.3.x' 2022-08-03 23:16:13 +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
Sam Brannen 855a3e5221 Polish ContextLoader support 2022-08-03 18:37:54 +03:00
Sam Brannen e3f4d810f6 Revise configurable refresh support in SmartContextLoader SPI
This commit revises 903e9f2a02 based on feedback from the Spring Boot
team.

- The original loadContext(MergedContextConfiguration) method is no
  longer deprecated.

- loadContext(MergedContextConfiguration, boolean) has been replaced by
  loadContextForAotProcessing(MergedContextConfiguration) which is
  implemented as a `default` method that throws an
  UnsupportedOperationException.

- Affected code has been refactored to adjust to these changes.

See gh-28906
2022-08-03 16:54:32 +03:00
Stephane Nicoll 3a890033b7 Fix custom bean definition to stop using reflection
See gh-28915
2022-08-03 14:51:52 +02:00
Sam Brannen 903e9f2a02 Introduce configurable refresh support in SmartContextLoader SPI
Prior to this commit, the contract of the loadContext() method in the
SmartContextLoader SPI required that the ApplicationContext be returned
in a fully refreshed state with a JVM shutdown hook registered for it.

However, in order to support AOT processing within the Spring
TestContext Framework (TCF), we need a way to signal to
SmartContextLoader implementations that they should load the test's
ApplicationContext without refreshing it or registering a JVM shutdown
hook.

To address this issue, this commit:

- Introduces a new loadContext(MergedContextConfiguration, boolean)
  method. The boolean `refresh` flag controls whether the returned
  ApplicationContext should be refreshed and have a JVM shutdown hook
  registered for it.

- Deprecates the existing loadContext(MergedContextConfiguration)
  method in favor of loadContext(MergedContextConfiguration, boolean).

- Removes all use of the deprecated method within the spring-test
  module, excluding the exception mentioned below.

Note that loadContext(MergedContextConfiguration, boolean) is
implemented as an interface `default` method which delegates to the
deprecated loadContext(MergedContextConfiguration) method for backward
compatibility. When migrating a SmartContextLoader to Spring Framework
6.0, implementations that directly implement the SmartContextLoader SPI
(instead of extending AbstractGenericContextLoader or
AbstractGenericWebContextLoader) will need to override the new
loadContext(MergedContextConfiguration, boolean) method in order to
honor the `refresh` flag for AOT processing support. See the
implementation in AbstractGenericContextLoader for an example of how
this can be achieved.

Closes gh-28906
2022-08-03 13:10:35 +03:00
Stephane Nicoll dcad3beeb9 Polish 2022-08-03 11:03:28 +02:00
Stephane Nicoll c9faff7491 Apply property hints to FactoryBean if necessary
This commit handles a BeanDefinition that configures the FactoryBean
as the "beanClass", while exposing the actual type in "resolvedType".
While unusual, this is required in certain cases when the factory
bean exposes generic information itself.

Previously, the hints for properties injection were applied on the
user type.

Closes gh-28913
2022-08-03 10:58:41 +02:00
Stephane Nicoll e79a8f6733 Polish 2022-08-03 10:53:57 +02:00
Stephane Nicoll 1fdd91eb30 Restore order of setImportMetadata in AOT optimized contexts
This commit adapts the generated code for handling ImportAware to
register a bean definition rather than adding the BeanPostProcessor
directly on the beanFactory. The previous arrangement put the
post processor handling import aware callbacks first on the list,
leading to inconsistent callback orders.

Tests have been adapted to validate this exact scenario.

Closes gh-28915
2022-08-03 10:16:20 +02:00
Stephane Nicoll 058b5fef6b Merge branch '5.3.x' 2022-08-02 16:11:16 +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
Sam Brannen abd06768a3 Avoid dependence on deprecated ContextLoader API within AbstractContextLoader
See gh-28905
2022-08-02 15:29:04 +03:00
Sam Brannen cf1d4638ae Avoid use of deprecated ContextLoader methods in tests
See gh-28905
2022-08-02 15:12:40 +03:00
Sam Brannen 72548f7611 Improve documentation of SmartContextLoader contracts 2022-08-02 13:48:53 +03:00
Sam Brannen ee33aa6117 Remove remaining reference to GenericPropertiesContextLoader
See gh-28911
2022-08-02 13:12:28 +03:00
Sam Brannen 2207d65b82 Deprecate methods in ContextLoader API in the TestContext framework
For Spring Framework 6.0 we have decided to deprecate the obsolete
methods in the ContextLoader API in the Spring TestContext Framework in
favor of the methods in the SmartContextLoader API which has been
available since Spring Framework 3.1.

Closes gh-28905
2022-08-02 13:07:12 +03:00
Sam Brannen 9c91375d75 Remove deprecated GenericPropertiesContextLoader from the TCF
Since GenericPropertiesContextLoader was deprecated in Spring Framework
5.3, we have decided to remove it in Spring Framework 6.0.

Closes gh-28911
2022-08-02 13:07:12 +03:00
Sam Brannen b0ab0edd9d Polishing 2022-08-02 13:07:12 +03:00
Brian Clozel 42b3339cb9 Fix RecordedInvocation instance resolution
This commit fixes `RecordedInvocation` and
`RuntimeHintsInvocationsAssert` so that they don't refer to the recorded
instance for static calls.

This also consistently resolves the `TypeReference` of recorded
instances.

Fixes gh-28907
2022-08-01 17:45:55 +02:00
Sam Brannen e4a7e35ead Polish TestCompiler 2022-08-01 13:41:50 +03:00
Sam Brannen 42ea09b08a Remove Hamcrest support from CompileWithTargetClassAccessClassLoader
CompileWithTargetClassAccessClassLoader is currently only used within the
CompileWithTargetClassAccessExtension which is dedicated to JUnit Jupiter
support which in turn should not have any direct dependencies on Hamcrest.

In other words, the JupiterTestEngine should not load any Hamcrest types
that would cause issues with the CompileWithTargetClassAccessClassLoader.
2022-08-01 13:37:03 +03:00
Sam Brannen d9bf3e54f7 Removed unused method parameter
See gh-28901
2022-08-01 13:29:48 +03:00
Phillip Webb 4a23d9234c Include shadow source jars in eclipse setup
See gh-28892
2022-08-01 11:28:01 +01:00
Sam Brannen ce850a583c Support overloaded test methods in CompileWithTargetClassAccessExtension
Prior to this commit, CompileWithTargetClassAccessExtension failed to
properly select overloaded test methods because it ignored the method
parameter list when looking up the test method.

This commit addresses this issue by selecting the test method using its
fully qualified method name which takes in account the class name,
method name, and parameter names.

Closes gh-28901
2022-08-01 13:07:58 +03:00
Sam Brannen 8fb27c3857 Polish CompileWithTargetClassAccessExtension 2022-08-01 13:07:58 +03:00
Sam Brannen 4896b115d2 Ensure CompileWithTargetClassAccessExtension only uses Jupiter TestEngine
Commit 9dd7f5412a (which has now been
reverted) addressed the issue of having the TestNG TestEngine for the
JUnit Platform on the test runtime classpath by allowing `org.testng`
types to pass through to the original ClassLoader; however, that fix
merely obfuscated the underlying issue.

The underlying issue is that the CompileWithTargetClassAccessExtension
is only applicable to JUnit Jupiter tests and therefore should launch
the JUnit Platform with only the JUnit Jupiter TestEngine active.

This commit addresses this issue by applying an EngineFilter to include
only the "junit-jupiter" test engine.

Closes gh-28900
2022-08-01 12:48:41 +03:00
Sam Brannen b89b6bd7a8 Revert "Support TestNG with @CompileWithTargetClassAccess"
This reverts commit 9dd7f5412a.
2022-08-01 12:44:42 +03:00
Sam Brannen fa74c353eb Revert "Polishing"
This reverts commit c8648b523b.
2022-08-01 12:44:34 +03:00
Stephane Nicoll 13c68aab52 Merge pull request #28890 from eltociear
* pr/28890:
  Fix typo in BasicJsonWriter.java

Closes gh-28890
2022-08-01 09:17:51 +02:00
Ikko Ashimine 4ac9b7bff2 Fix typo in BasicJsonWriter.java
See gh-28890
2022-08-01 09:17:28 +02:00
Sam Brannen c8648b523b Polishing 2022-07-31 15:07:02 +03:00
Sam Brannen 9dd7f5412a Support TestNG with @CompileWithTargetClassAccess 2022-07-31 14:57:48 +03:00
Sam Brannen e4395f2f8b Clean up warnings and polishing 2022-07-31 14:14:56 +03:00
Phillip WebbandAndy Wilkinson 9d1e9703ae Include shadowed jar source in published source artifacts
Add a new `ShadowSource` Gradle task and update `spring-core.gradle`
to include source for cglib, javapoet and objenesis.

Closes gh-28892

Co-authored-by: Andy Wilkinson <wilkinsona@vmware.com>
2022-07-30 10:25:58 +01:00
Sam Brannen 2dc8335b7f Make BootstrapUtils public
See gh-28891
2022-07-30 11:21:14 +03:00
Sam Brannen ebeadc74c5 Add missing [@]since tag
See gh-17282
2022-07-30 11:14:06 +03:00
Sam Brannen 64c3ad3634 Make BootstrapUtils.resolveTestContextBootstrapper() public
Closes gh-28891
2022-07-30 11:09:07 +03:00
Sam Brannen ad99add429 Polish AOT support 2022-07-30 10:51:14 +03:00
Sam Brannen 3912ef1507 Polish TestCompiler support 2022-07-30 10:51:14 +03:00
Stephane Nicoll 11d790c6eb Merge branch '5.3.x' 2022-07-29 18:07:37 +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 7b4a37f573 Merge pull request #28472 from JiayiLi1999
* pr/28472:
  Polish "Improve test coverage of RdbmsOperation"
  Improve test coverage of RdbmsOperation

Closes gh-28472
2022-07-29 17:37:30 +02:00
Stephane Nicoll f9ee8a93ad Polish "Improve test coverage of RdbmsOperation"
See gh-28472
2022-07-29 17:36:33 +02:00
Jiayi Li 608be54a58 Improve test coverage of RdbmsOperation
See gh-28472
2022-07-29 17:28:00 +02:00
Stephane Nicoll 1bdb67cda9 Merge branch '5.3.x' 2022-07-29 17:13:52 +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 c2f6d346d5 Merge branch '5.3.x' 2022-07-29 17:01:28 +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
Stephane Nicoll 916a871fbc Add dedicated hint support for composable annotations
This commit adds a dedicated method for annotations that are used as
meta-annotation when the composed annotation does not require to be
visible at runtime.

Closes gh-28887
2022-07-29 15:38:09 +02:00
Rossen Stoyanchev 1aa4e7c68d Merge branch '5.3.x' 2022-07-29 16:20:51 +03: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
Stephane Nicoll 56a8c1a9db Register proxy hint for meta-annotations with attribute override
Closes gh-28767
2022-07-29 13:23:32 +02:00
Arjen Poutsma e0190c12d4 Merge branch '5.3.x' 2022-07-29 11:10:09 +02:00
Arjen Poutsma 3d4a778b73 Fix KDoc API link 2022-07-29 11:08:57 +02:00
Stephane Nicoll 28ca0dd642 Merge branch '5.3.x' 2022-07-29 09:31:50 +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
Stephane Nicoll 8e7faab4f6 Polish 2022-07-28 16:37:08 +02:00
Phillip Webb 24fafc2fb7 Document that AOT processors are initialized during AOT processing
Closes gh-28866
2022-07-28 14:30:26 +01:00
Phillip Webb 9413383d72 Enforce BeanRegistrationExcludeFilter beans are also AOT processors
Update `BeanDefinitionMethodGeneratorFactory` to enforce that any
`BeanRegistrationExcludeFilter` filter that is from a bean factory
also implements an AOT processor interface.

See gh-28866
2022-07-28 14:29:28 +01:00
Phillip Webb a4f3d1d6e8 Track the sources used to load AOT services
Update `AotServices` so that it tracks which source was used to
provide a given instance.

See gh-28866
2022-07-28 14:28:37 +01:00
Phillip Webb 5218cf4c16 Fix BeanFactoryInitializationAotProcessor javadoc
Update javadoc since BeanRegistrationExcludeFilter is not longer an
exclude signal

See gh-28833
2022-07-28 14:25:56 +01:00
Arjen Poutsma 619f0e4266 Merge branch '5.3.x' 2022-07-28 14:24:25 +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
Brian Clozel 10e4965f99 Guard against new Spring modules in ApiDiff task
Prior to this commit, the ApiDiff Gradle task would be configured for
all submodules of the Spring Framework project and would assume that
they all existed for the baseline version considered for the API diff.

This would cause issues when:
* the sub-project is not published as it's not an official "spring-*"
  module
* the "spring-*" module is new and did not exist for the baseline
  version

This commit ensures that only "spring-*" modules are considered for this
task and that we trigger an early resolution of the baseline version -
if the version doesn't exist, a warn message is logged and we assume
that this is a new module, to be compared with an empty configuration.

This commit also renames the "spring-core-graalvm" project to
"graalvm-feature", since this sub-project is not an official module
published to Maven Central, but rather an internal dependency.

Fixes gh-28818
2022-07-28 10:51:53 +02:00
Phillip Webb d33c2b52cc Don't look for RuntimeHintsRegistrar beans
Update `RuntimeHintsBeanFactoryInitializationAotProcessor` so
that `RuntimeHintsRegistrar` beans are not loaded.

See gh-28866
2022-07-27 19:26:12 +01:00
Phillip Webb e928943d1a Don't use BeanRegistrationExcludeFilter as an exclude signal
Closes gh-28833
2022-07-27 19:26:11 +01:00
Phillip Webb 472c23455a Add AotServices class to replace AotFactoriesLoader
Add an `AotServices` class to replace `AotFactoriesLoader`. The
replacement class allow instances to be loaded from just the
`aot.factories` file if required. It also retains a link to the bean
names so that a `findByBeanName(...)` method can be provided.

See gh-28833
2022-07-27 19:25:28 +01:00
Stephane Nicoll 498668fc57 Deprecate SpringFactoriesLoader#loadFactoryNames
Closes gh-27954
2022-07-27 17:56:33 +02:00
Stephane Nicoll 88e29689b6 Polish 2022-07-27 15:10:09 +02:00
Stephane Nicoll f0f7f72de9 Do not write BeanDefinition attributes by default
This commit flips the default strategy for BeanDefinition attributes so
that they are not generated in AOT-optimized contexts.

Closes gh-28516
2022-07-27 15:01:50 +02:00
Arjen Poutsma b38a5df563 Javadoc 2022-07-27 13:54:09 +02:00
Arjen Poutsma 2aa74c9121 Deprecate ListenableFuture in favor of CompletableFuture
This commit deprecates ListenableFuture in favor of CompletableFuture.
ListenableFuture was introduced in Spring Framework 4.0, when
CompletableFuture was not yet available. Spring now requires JDK 17, so
having our own type no longer seems necessary.

Major changes in this commit include:
- Deprecation of ListenableFuture and related types
  (ListenableFutureCallback, SettableListenableFuture, etc.)
- Deprecation of AsyncListenableTaskExecutor in favor of default methods
  in AsyncTaskExecutor (submitCompletable).
- AsyncHandlerMethodReturnValueHandler now has toCompletableFuture
  instead of toListenableFuture.
- WebSocketClient now has execute methods, which do the same as
  doHandshake, but return CompletableFutures (cf. the reactive
  WebSocketClient).

All other changes
- add an overloaded method that takes a CompletableFuture parameter
  instead of ListenableFuture, and/or
- add a method with a 'Async' suffix that returns a CompletableFuture
  instead of a ListenableFuture (connectAsync, sendAsync).

Closes gh-27780
2022-07-27 12:41:35 +02:00
Stephane Nicoll 735051bf7d Resolve infer destroy method at build-time
This commit allows a RootBeanDefinition to resolve its infer destroy
method if necessary. Contrary to BeanInstanceAdapter that uses the
actual bean instance, the new method works against the type exposed
in the bean definition.

The AOT contribution of InitDestroyAnnotationBeanPostProcessor uses
the new method to make sure the special '(inferred)' placeholder is
handled prior to code generation.

Closes gh-28215
2022-07-27 11:48:13 +02:00
Sam Brannen 3f3e37e66c Upgrade to JUnit 5.9
Closes gh-28752
2022-07-27 11:02:34 +03:00
Stephane Nicoll 3d5003ad63 Introduce TestGenerationContext
This commit polishes DefaultGenerationContext to make the method
that flushes generated classes more explicit. It now throws an
IOException and TestGenerationContext has been updated to handle
that to ease its use in code that can't throw such an exception.

As this use case is likely to happen outside the Spring Framework,
this commit adds such a convenience to spring-test as well.

Closes gh-28877
2022-07-26 17:56:17 +02:00
Stephane Nicoll 60d2d16b2b Polish 2022-07-26 15:18:35 +02:00
Stephane Nicoll ebe3b37298 Allow MergedBeanDefinitionPostProcessor to handle bean creation
This commit registers the MergedBeanDefinitionPostProcessor instances
on the BeanFactory processed for AOT purposes. This allows beans that
are created at build-time to be post-processed for low-level needs such
as initialization and autowiring.

Closes gh-28777
2022-07-26 09:25:11 +02:00
Stephane Nicoll 9573fc96ec Polish 2022-07-25 13:45:46 +02:00
Stephane Nicoll 75c63f877b Merge branch '5.3.x' 2022-07-25 13:33:06 +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 1bce274099 Merge branch '5.3.x' 2022-07-25 12:24:16 +02:00
Arjen Poutsma f7b94fc3e8 Updated sdkmanrc 2022-07-25 12:21:58 +02:00
Stephane Nicoll ae6a464a80 Merge branch '5.3.x' 2022-07-22 16:15:55 +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 c1738aab0d Improve target detection for FactoryBeans with generic
Closes gh-28809
2022-07-22 13:10:44 +02:00
Stephane Nicoll bbcc269487 Polish 2022-07-22 12:09:16 +02:00
Stephane Nicoll c09eb633db Rename test fixture to avoid class with existing TestBean class 2022-07-22 12:03:00 +02:00
Stephane Nicoll ba5ab1ad9d Polish 2022-07-22 09:36:45 +02:00
Phillip Webb cfb61d2a17 Add generics to BeanInstanceSupplier
Update `BeanInstanceSupplier` to support a generic type.

See gh-28748
2022-07-21 13:29:15 +01:00
Phillip Webb 069d6d3280 Propagate getFactoryMethod() when using InstanceSupplier.andThen()
Update `InstanceSupplier.andThen` to propagate the result of
`getFactoryMethod()`.

See gh-28748
2022-07-20 18:56:57 +01:00
Phillip Webb 3ae1b9ba57 Polish CodeBlock joining logic
Consistently use `CodeBlock.joining(", ")` when generating code.
2022-07-20 10:25:45 +01:00
Stephane Nicoll 4560313b9d Merge pull request #28843 from OlgaMaciaszek
* pr/28843:
  Polish "Handle inferred init/destroy method consistently"
  Handle inferred init/destroy method consistently

Closes gh-28843
2022-07-20 10:46:47 +02:00
Stephane Nicoll 85173b5de3 Polish "Handle inferred init/destroy method consistently"
See gh-28843
2022-07-20 10:45:51 +02:00
Olga Maciaszek-Sharma 68e28a5f59 Handle inferred init/destroy method consistently
See gh-28843
2022-07-20 10:40:51 +02:00
Stephane Nicoll d6345db7c9 Use target of the FactoryBean only if the FactoryBean is public
This commit polishes 85d4a79 so that the target type of factory bean
is only considered if the FactoryBean is accessible. If the FactoryBean
requires protected access, we still generate the code in the package of
the FactoryBean.

Those two commits combined are actually providing a fix for the use
case described in gh-28809.

Closes gh-28809
2022-07-19 21:02:24 +02:00
Stephane Nicoll 978cdfff46 Formatting 2022-07-19 17:57:28 +02:00
Stephane Nicoll 1acb41ff43 Add AOT support for by-type RuntimeBeanReference
Closes gh-28841
2022-07-19 17:57:12 +02:00
Stephane Nicoll cd4f4d978d Merge branch '5.3.x' 2022-07-19 15:39:44 +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
Stephane Nicoll 85d4a79cdc Improve location of generated bean definitions of FactoryBeans
This commit improves the location of generated bean definitions for
FactoryBean implementations by checking the type that the factory
bean generates, rather than the factory bean implementation itself.

Closes gh-28812
2022-07-19 15:17:31 +02:00
Sébastien Deleuze c0bea373a2 Merge branch '5.3.x' 2022-07-19 10:19:00 +02:00
Jupiter 7fa9f1c9cf Fix broken link to rsocket protocol page
Closes gh-28817
2022-07-19 10:14:46 +02:00
Phillip Webb 578f155809 Polishing 2022-07-18 15:01:51 +01:00
Stephane Nicoll 444e06fa22 Harmonize visibility of RuntimeHints builders
Closes gh-28835
2022-07-18 14:09:52 +02:00
Phillip Webb 87b83e8291 Make MethodName package-private
Closes gh-28832
2022-07-18 11:20:43 +01:00
Phillip Webb 0ea4ee163c Polishing 2022-07-18 10:54:30 +01:00
Stephane Nicoll 75ab47b57c Link factoryMethod consistently in AOT-generated bean definitions
Closes gh-28748
2022-07-18 10:06:48 +01:00
Phillip Webb f2d31b7a20 Migrate AOT tests to use GeneratedClasses and refine/polish AOT APIs
Migrate all AOT tests to make use of `GeneratedClasses` rather than
directly generating Java files. This commit also refines and polishes
AOT APIs to being greater consistency.

Specifically:

	- The `MethodGenerator` interface has been removed in favor of
	  working directly with `GeneratedMethods`.
	- The visibility of several constructors and methods has been
	  reduced to package-private.
	- The `using(...)` and `builder` methods have been removed in
	  favor of setting the `Consumer` callbacks directly as
	  constructor arguments.
	- Variable names for builders are now named `type` or `method`
	  depending on what they're building.

Closes gh-28831
2022-07-18 08:40:59 +01:00
Sam Brannen 4f8516e2c3 Polishing 2022-07-15 18:24:55 +02:00
Sam Brannen 72e4a5f9fe Fix precondition check in TestClassScanner and improve Javadoc
- remove not-empty precondition check for packageNames so that the core
  scan() method can actually be used.
- document constructor
- document use case for packageNames
- add test that scan's all test classes in the spring-test project
- reduce logging due to the previous action item

See gh-28824
2022-07-15 17:10:47 +02:00
Sam Brannen 3fd72652be Fix @ExtendWith search in TestClassScanner
The search algorithm for @ExtendWith should not be tied to Spring's
@NestedTestConfiguration semantics. Rather, general JUnit annotation
search semantics should be used to find @ExtendWith.

See gh-28824
2022-07-15 16:46:39 +02:00
Sam Brannen 1f3ea5133f Polishing 2022-07-15 15:28:47 +02:00
Brian Clozel 77f8408e80 Polish
Closes gh-28751
2022-07-15 14:28:19 +02:00
Sam Brannen c34ccfdb81 Simplify @EneabledIfRuntimeHintsAgent support
Since the RuntimeHintsAgentCondition is based solely on the result of
invoking a boolean static method, there is no need to implement a custom
ExecutionCondition. For such use cases, the @EnabledIf support in JUnit
Jupiter is sufficient.

This commit therefore replaces the custom RuntimeHintsAgentCondition
with use of @EnabledIf as a meta-annotation.
2022-07-15 14:22:06 +02:00
Sam Brannen f5503298fb Handle missing dependencies for optional TestExecutionListener again
Commit d1b65f6d3e introduced a regression regarding the handling of
missing dependencies for optional (typically default)
TestExecutionListeners.

Prior to d1b65f6d3e a TestExecutionListener was instantiated using
java.lang.Class.newInstance() which never throws an
InvocationTargetException. With the switch to the new
SpringFactoriesLoader APIs, a TestExecutionListener is now instantiated
using java.lang.reflect.Constructor.newInstance(Object...) which can
throw an InvocationTargetException.

This commit addresses the regression by unwrapping the target exception
in an InvocationTargetException.

See gh-28666
Closes gh-28828
2022-07-15 13:50:32 +02:00
Sam Brannen 9962aa00a0 Introduce TestClassScanner to locate Spring test classes for AOT processing
This commit introduces the TestClassScanner which scans provided
classpath roots for Spring integration test classes using the JUnit
Platform Launcher API which allows all registered TestEngines to
discover tests according to their own rules.

The scanner currently detects the following categories of Spring
integration test classes.

- JUnit Jupiter: classes that register the SpringExtension via
  @ExtendWith.
- JUnit 4: classes that register the SpringJUnit4ClassRunner or
  SpringRunner via @RunWith.
- Generic: classes that are annotated with @ContextConfiguration or
  @BootstrapWith.

The scanner has been tested with the following TestEngine
implementations for the JUnit Platform.

- JUnit Jupiter
- JUnit Vintage
- JUnit Platform Suite Engine
- TestNG Engine for the JUnit Platform

Closes gh-28824
2022-07-15 13:21:22 +02:00
Arjen Poutsma db43425bf9 Javadoc 2022-07-14 15:24:47 +02:00
Arjen Poutsma f145b53fc8 Use existing context path in DefaultServerRequestBuilder
Closes gh-28820
2022-07-14 15:24:44 +02:00
Arjen Poutsma 1e03b30d33 Use existing context path in DefaultServerRequestBuilder
Closes gh-28820
2022-07-14 15:10:31 +02:00
rstoyanchev bf63309d05 Allow empty path in MockMvc
Closes gh-28823
2022-07-14 12:50:57 +01:00
Stephane Nicoll 963fd75aff Merge branch '5.3.x' 2022-07-14 11:34:36 +02:00
Spring Builds 7df149c8b8 Next development version (v5.3.23-SNAPSHOT) 2022-07-14 08:50:40 +00:00
4451 changed files with 216404 additions and 120848 deletions
+8
View File
@@ -3,11 +3,19 @@ name: Backport Bot
on:
issues:
types: [labeled]
pull_request:
types: [labeled]
push:
branches:
- '*.x'
permissions:
contents: read
jobs:
build:
permissions:
contents: read
issues: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
+32
View File
@@ -0,0 +1,32 @@
name: Deploy Docs
on:
push:
branches-ignore: [ gh-pages ]
tags: '**'
repository_dispatch:
types: request-build-reference # legacy
schedule:
- cron: '0 10 * * *' # Once per day at 10am UTC
workflow_dispatch:
permissions:
actions: write
jobs:
build:
runs-on: ubuntu-latest
if: github.repository_owner == 'spring-projects'
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: docs-build
fetch-depth: 1
- name: Dispatch (partial build)
if: github.ref_type == 'branch'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD) -f build-refname=${{ github.ref_name }}
- name: Dispatch (full build)
if: github.ref_type == 'tag'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD)
@@ -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
+4 -3
View File
@@ -21,16 +21,15 @@ derby.log
/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
spring-test/test-output/
# Maven artifacts
pom.xml
target/
/target/
# Eclipse artifacts, including WTP generated manifests
bin
@@ -51,3 +50,5 @@ atlassian-ide-plugin.xml
# VS Code
.vscode/
cached-antora-playbook.yml
+2
View File
@@ -30,5 +30,7 @@ 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>
Simon Basle <sbasle@vmware.com>
Simon Baslé <sbasle@vmware.com>
<dmitry.katsubo@gmail.com> <dmitry.katsubo@gmai.com>
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=17.0.3.1-librca
java=17.0.7-librca
+7 -7
View File
@@ -66,7 +66,7 @@ follow-up reports will need to be created as new issues with a fresh description
#### Submit a Pull Request
1. If you have not previously done so, please sign the
[Contributor License Agreement](https://cla.pivotal.io/sign/spring). You will be reminded
[Contributor License Agreement](https://cla.spring.io/sign/spring). You will be reminded
automatically when you submit the PR.
1. Should you create an issue first? No, just create the pull request and use the
@@ -123,13 +123,13 @@ define the source file coding standards we use along with some IDEA editor setti
### Reference Docs
The reference documentation is in the [src/docs/asciidoc](src/docs/asciidoc) directory, in
[Asciidoctor](https://asciidoctor.org/) format. For trivial changes, you may be able to browse,
edit source files, and submit directly from GitHub.
The reference documentation is authored in [Asciidoctor](https://asciidoctor.org/) format
using [Antora](https://docs.antora.org/antora/latest/). The source files for the documentation
reside in the [framework-docs/modules/ROOT](framework-docs/modules/ROOT) directory. For
trivial changes, you may be able to browse, edit source files, and submit directly from GitHub.
When making changes locally, execute `./gradlew asciidoctor` and then browse the result under
`build/docs/ref-docs/html5/index.html`.
When making changes locally, execute `./gradlew antora` and then browse the results under
`framework-docs/build/site/index.html`.
Asciidoctor also supports live editing. For more details see
[AsciiDoc Tooling](https://docs.asciidoctor.org/asciidoctor/latest/tooling/).
+4 -4
View File
@@ -1,8 +1,8 @@
# <img src="src/docs/spring-framework.png" width="80" height="80"> Spring Framework [![Build Status](https://ci.spring.io/api/v1/teams/spring-framework/pipelines/spring-framework-5.3.x/jobs/build/badge)](https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-5.3.x?groups=Build") [![Revved up by Gradle Enterprise](https://img.shields.io/badge/Revved%20up%20by-Gradle%20Enterprise-06A0CE?logo=Gradle&labelColor=02303A)](https://ge.spring.io/scans?search.rootProjectNames=spring)
# <img src="framework-docs/src/docs/spring-framework.png" width="80" height="80"> Spring Framework [![Build Status](https://ci.spring.io/api/v1/teams/spring-framework/pipelines/spring-framework-6.0.x/jobs/build/badge)](https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-6.0.x?groups=Build") [![Revved up by Gradle Enterprise](https://img.shields.io/badge/Revved%20up%20by-Gradle%20Enterprise-06A0CE?logo=Gradle&labelColor=02303A)](https://ge.spring.io/scans?search.rootProjectNames=spring)
This is the home of the Spring Framework: the foundation for all [Spring projects](https://spring.io/projects). Collectively the Spring Framework and the family of Spring projects are often referred to simply as "Spring".
Spring provides everything required beyond the Java programming language for creating enterprise applications for a wide range of scenarios and architectures. Please read the [Overview](https://docs.spring.io/spring/docs/current/spring-framework-reference/overview.html#spring-introduction) section as reference for a more complete introduction.
Spring provides everything required beyond the Java programming language for creating enterprise applications for a wide range of scenarios and architectures. Please read the [Overview](https://docs.spring.io/spring-framework/reference/overview.html) section of the reference documentation for a more complete introduction.
## Code of Conduct
@@ -14,7 +14,7 @@ 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/reference/) and [source](framework-docs/modules/ROOT)), 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
@@ -31,7 +31,7 @@ Information regarding CI builds can be found in the [Spring Framework Concourse
## Stay in Touch
Follow [@SpringCentral](https://twitter.com/springcentral), [@SpringFramework](https://twitter.com/springframework), and its [team members](https://twitter.com/springframework/lists/team/members) on Twitter. In-depth articles can be found at [The Spring Blog](https://spring.io/blog/), and releases are announced via our [news feed](https://spring.io/blog/category/news).
Follow [@SpringCentral](https://twitter.com/springcentral), [@SpringFramework](https://twitter.com/springframework), and its [team members](https://twitter.com/springframework/lists/team/members) on Twitter. In-depth articles can be found at [The Spring Blog](https://spring.io/blog/), and releases are announced via our [releases feed](https://spring.io/blog/category/releases).
## License
+5
View File
@@ -1,5 +1,10 @@
# Security Policy
## JAR signing
Spring Framework JARs released on Maven Central are signed.
You'll find more information about the key here: https://spring.io/GPG-KEY-spring.txt
## Supported Versions
Please see the
+47 -330
View File
@@ -1,260 +1,36 @@
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.4.0' apply false
id 'org.jetbrains.dokka' version '1.7.0' apply false
id 'org.jetbrains.kotlin.jvm' version '1.7.10' apply false
id "org.jetbrains.kotlin.plugin.serialization" version '1.7.10' 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 'de.undercouch.download' version '4.1.2'
id "me.champeau.jmh" version "0.6.6" apply false
id 'io.freefair.aspectj' version '8.0.1' apply false
// kotlinVersion is managed in gradle.properties
id 'org.jetbrains.kotlin.plugin.serialization' version "${kotlinVersion}" apply false
id 'org.jetbrains.dokka' version '1.8.20'
id 'org.unbroken-dome.xjc' version '2.0.0' apply false
id 'com.github.ben-manes.versions' version '0.46.0'
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
id 'de.undercouch.download' version '5.4.0'
id 'me.champeau.jmh' version '0.7.1' apply false
id 'me.champeau.mrjar' version '0.1.1'
}
ext {
moduleProjects = subprojects.findAll { it.name.startsWith("spring-") }
javaProjects = subprojects - project(":framework-bom")
withoutJclOverSlf4j = {
exclude group: "org.slf4j", name: "jcl-over-slf4j"
}
javaProjects = subprojects - project(":framework-bom") - project(":framework-platform")
}
configure(allprojects) { project ->
apply plugin: "io.spring.dependency-management"
dependencyManagement {
imports {
mavenBom "com.fasterxml.jackson:jackson-bom:2.13.3"
mavenBom "io.netty:netty-bom:4.1.79.Final"
mavenBom "io.projectreactor:reactor-bom:2022.0.0-M4"
mavenBom "io.rsocket:rsocket-bom:1.1.2"
mavenBom "org.eclipse.jetty:jetty-bom:11.0.11"
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.7.10"
mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.2"
mavenBom "org.jetbrains.kotlinx:kotlinx-serialization-bom:1.3.3"
mavenBom "org.junit:junit-bom:5.9.0-RC1"
repositories {
mavenCentral()
maven {
url "https://repo.spring.io/milestone"
content {
// Netty 5 optional support
includeGroup 'io.projectreactor.netty'
}
}
dependencies {
dependencySet(group: 'org.apache.logging.log4j', version: '2.18.0') {
entry 'log4j-api'
entry 'log4j-core'
entry 'log4j-jul'
entry 'log4j-slf4j-impl'
}
dependency "org.slf4j:slf4j-api:1.7.36"
dependency("com.google.code.findbugs:findbugs:3.0.1") {
exclude group: "dom4j", name: "dom4j"
}
dependency "com.google.code.findbugs:jsr305:3.0.2"
dependencySet(group: 'org.aspectj', version: '1.9.9.1') {
entry 'aspectjrt'
entry 'aspectjtools'
entry 'aspectjweaver'
}
dependencySet(group: 'org.apache.groovy', version: '4.0.2') {
entry 'groovy'
entry 'groovy-jsr223'
entry 'groovy-templates' // requires findbugs for warning-free compilation
entry 'groovy-xml'
}
dependency "io.reactivex.rxjava3:rxjava:3.1.4"
dependency "io.smallrye.reactive:mutiny:1.4.0"
dependency "io.projectreactor.tools:blockhound:1.0.6.RELEASE"
dependency "io.r2dbc:r2dbc-spi:1.0.0.RELEASE"
dependency "io.r2dbc:r2dbc-spi-test:1.0.0.RELEASE"
dependency "io.r2dbc:r2dbc-h2:1.0.0.RC1"
dependency "com.fasterxml:aalto-xml:1.3.1"
dependency("com.fasterxml.woodstox:woodstox-core:6.3.0") {
exclude group: "stax", name: "stax-api"
}
dependency "com.google.code.gson:gson:2.9.0"
dependency "com.google.protobuf:protobuf-java-util:3.21.2"
dependency "com.googlecode.protobuf-java-format:protobuf-java-format:1.4"
dependency "com.thoughtworks.qdox:qdox:2.0.1"
dependency("com.thoughtworks.xstream:xstream:1.4.19") {
exclude group: "xpp3", name: "xpp3_min"
exclude group: "xmlpull", name: "xmlpull"
}
dependency "org.eclipse:yasson:2.0.4"
dependency("org.codehaus.jettison:jettison:1.3.8") {
exclude group: "stax", name: "stax-api"
}
dependency "org.ogce:xpp3:1.1.6"
dependency "org.yaml:snakeyaml:1.30"
dependency "com.h2database:h2:2.1.214"
dependency "com.github.ben-manes.caffeine:caffeine:3.1.1"
dependency "com.github.librepdf:openpdf:1.3.29"
dependency "com.rometools:rome:1.18.0"
dependency "commons-io:commons-io:2.11.0"
dependency "io.vavr:vavr:0.10.4"
dependency "net.sf.jopt-simple:jopt-simple:5.0.4"
dependencySet(group: 'org.apache.activemq', version: '5.16.2') {
entry 'activemq-broker'
entry('activemq-kahadb-store') {
exclude group: "org.springframework", name: "spring-context"
}
entry 'activemq-stomp'
}
dependency "org.apache.commons:commons-pool2:2.9.0"
dependencySet(group: 'org.apache.derby', version: '10.14.2.0') {
entry 'derby'
entry 'derbyclient'
}
dependency "org.apache.poi:poi-ooxml:5.2.2"
dependency "org.apache-extras.beanshell:bsh:2.0b6"
dependency "org.freemarker:freemarker:2.3.31"
dependency "org.hsqldb:hsqldb:2.5.2"
dependency "org.quartz-scheduler:quartz:2.3.2"
dependency "org.ehcache:jcache:1.0.1"
dependency "org.ehcache:ehcache:3.4.0"
dependency "org.hibernate:hibernate-core-jakarta:5.6.10.Final"
dependency "org.hibernate:hibernate-validator:7.0.4.Final"
dependency "org.webjars:webjars-locator-core:0.48"
dependency "org.webjars:underscorejs:1.8.3"
dependencySet(group: 'org.apache.tomcat', version: '10.0.22') {
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: '10.0.22') {
entry 'tomcat-embed-core'
entry 'tomcat-embed-websocket'
}
dependencySet(group: 'io.undertow', version: '2.2.18.Final') {
entry 'undertow-core'
entry 'undertow-servlet-jakarta'
entry 'undertow-websockets-jsr-jakarta'
}
dependency "org.eclipse.jetty:jetty-reactive-httpclient:3.0.6"
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") {
exclude group: "commons-logging", name: "commons-logging"
}
dependencySet(group: 'com.squareup.okhttp3', version: '3.14.9') {
entry 'okhttp'
entry 'mockwebserver'
}
dependency "org.jruby:jruby:9.3.4.0"
dependency "org.python:jython-standalone:2.7.1"
dependency "org.mozilla:rhino:1.7.11"
dependency("org.dom4j:dom4j:2.1.3") {
exclude group: 'javax.xml.bind', name: "jaxb-api"
exclude group: "jaxen", name: "jaxen"
exclude group: "net.java.dev.msv", name: "xsdlib"
exclude group: "pull-parser", name: "pull-parser"
exclude group: "xpp3", name: "xpp3"
}
dependency("jaxen:jaxen:1.2.0") {
exclude group: "dom4j", name: "dom4j"
}
dependency("junit:junit:4.13.2") {
exclude group: "org.hamcrest", name: "hamcrest-core"
}
dependency("de.bechte.junit:junit-hierarchicalcontextrunner:4.12.1") {
exclude group: "junit", name: "junit"
}
dependency "org.testng:testng:7.6.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.23.1"
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.6.1') {
entry('mockito-core') {
exclude group: "org.hamcrest", name: "hamcrest-core"
}
entry 'mockito-junit-jupiter'
}
dependency "io.mockk:mockk:1.12.1"
dependency("net.sourceforge.htmlunit:htmlunit:2.63.0") {
exclude group: "commons-logging", name: "commons-logging"
}
dependency("org.seleniumhq.selenium:htmlunit-driver:2.63.0") {
exclude group: "commons-logging", name: "commons-logging"
}
dependency("org.seleniumhq.selenium:selenium-java:3.141.59") {
exclude group: "commons-logging", name: "commons-logging"
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-jdk18on:1.71"
dependency "javax.cache:cache-api:1.1.1"
dependency "javax.money:money-api:1.1"
dependency "org.javamoney:moneta:1.4.2"
dependency "jakarta.activation:jakarta.activation-api:2.0.1"
dependency "jakarta.annotation:jakarta.annotation-api:2.0.0"
dependency "jakarta.ejb:jakarta.ejb-api:4.0.0"
dependency "jakarta.el:jakarta.el-api:4.0.0"
dependency "jakarta.enterprise.concurrent:jakarta.enterprise.concurrent-api:2.0.0"
dependency "jakarta.faces:jakarta.faces-api:3.0.0"
dependency "jakarta.inject:jakarta.inject-api:2.0.0"
dependency "jakarta.inject:jakarta.inject-tck:2.0.1"
dependency "jakarta.interceptor:jakarta.interceptor-api:2.0.0"
dependency "jakarta.jms:jakarta.jms-api:3.0.0"
dependency "jakarta.json:jakarta.json-api:2.0.1"
dependency "jakarta.json.bind:jakarta.json.bind-api:2.0.0"
dependency "jakarta.mail:jakarta.mail-api:2.0.1"
dependency "jakarta.persistence:jakarta.persistence-api:3.0.0"
dependency "jakarta.resource:jakarta.resource-api:2.0.0"
dependency "jakarta.servlet:jakarta.servlet-api:5.0.0"
dependency "jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.0.0"
dependency "jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:2.0.0"
dependency "jakarta.transaction:jakarta.transaction-api:2.0.0"
dependency "jakarta.validation:jakarta.validation-api:3.0.0"
dependency "jakarta.websocket:jakarta.websocket-api:2.0.0"
dependency "jakarta.xml.bind:jakarta.xml.bind-api:3.0.1"
dependency "com.sun.activation:jakarta.activation:2.0.1"
dependency "com.sun.mail:jakarta.mail:2.0.1"
dependencySet(group: 'com.sun.xml.bind', version: '3.0.2') {
entry 'jaxb-core'
entry 'jaxb-impl'
entry 'jaxb-xjc'
}
// Substitute for "javax.management:jmxremote_optional:1.0.1_04" which
// is not available on Maven Central
dependency "org.glassfish.external:opendmk_jmxremote_optional_jar:1.0-b01-ea"
dependency "org.glassfish:jakarta.el:4.0.2"
dependency "org.glassfish.tyrus:tyrus-container-servlet:2.0.1"
dependency "org.eclipse.persistence:org.eclipse.persistence.jpa:3.0.2"
dependency "org.graalvm.nativeimage:svm:22.1.0.1"
if (version.contains('-')) {
maven { url "https://repo.spring.io/milestone" }
}
generatedPomCustomization {
enabled = false
}
resolutionStrategy {
cacheChangingModulesFor 0, "seconds"
}
repositories {
mavenCentral()
maven { url "https://repo.spring.io/libs-spring-framework-build" }
maven { url "https://repo.spring.io/milestone" } // temporarily for context-propagation via Reactor Netty
if (version.endsWith('-SNAPSHOT')) {
maven { url "https://repo.spring.io/snapshot" }
}
}
configurations.all {
@@ -270,44 +46,21 @@ configure([rootProject] + javaProjects) { project ->
apply plugin: "java"
apply plugin: "java-test-fixtures"
apply plugin: "checkstyle"
apply plugin: 'org.springframework.build.compile'
apply plugin: 'org.springframework.build.conventions'
apply from: "${rootDir}/gradle/toolchains.gradle"
apply from: "${rootDir}/gradle/ide.gradle"
pluginManager.withPlugin("kotlin") {
apply plugin: "org.jetbrains.dokka"
apply from: "${rootDir}/gradle/docs-dokka.gradle"
compileKotlin {
kotlinOptions {
languageVersion = "1.7"
apiVersion = "1.7"
freeCompilerArgs = ["-Xjsr305=strict", "-Xsuppress-version-warnings", "-opt-in=kotlin.RequiresOptIn"]
allWarningsAsErrors = true
}
configurations {
dependencyManagement {
canBeConsumed = false
canBeResolved = false
visible = false
}
compileTestKotlin {
kotlinOptions {
freeCompilerArgs = ["-Xjsr305=strict", "-opt-in=kotlin.RequiresOptIn"]
}
}
}
test {
useJUnitPlatform()
include(["**/*Tests.class", "**/*Test.class"])
systemProperty("java.awt.headless", "true")
systemProperty("testGroups", project.properties.get("testGroups"))
systemProperty("io.netty.leakDetection.level", "paranoid")
}
checkstyle {
toolVersion = "10.3.1"
configDirectory.set(rootProject.file("src/checkstyle"))
matching { it.name.endsWith("Classpath") }.all { it.extendsFrom(dependencyManagement) }
}
dependencies {
dependencyManagement(enforcedPlatform(dependencies.project(path: ":framework-platform")))
testImplementation("org.junit.jupiter:junit-jupiter-api")
testImplementation("org.junit.jupiter:junit-jupiter-params")
testImplementation("org.junit.platform:junit-platform-suite-api")
@@ -321,43 +74,37 @@ configure([rootProject] + javaProjects) { project ->
testRuntimeOnly("org.junit.platform:junit-platform-suite-engine")
testRuntimeOnly("org.apache.logging.log4j:log4j-core")
testRuntimeOnly("org.apache.logging.log4j:log4j-jul")
testRuntimeOnly("org.apache.logging.log4j:log4j-slf4j-impl")
testRuntimeOnly("org.apache.logging.log4j:log4j-slf4j2-impl")
// JSR-305 only used for non-required meta-annotations
compileOnly("com.google.code.findbugs:jsr305")
testCompileOnly("com.google.code.findbugs:jsr305")
checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:0.0.31")
}
ext.javadocLinks = [
"https://docs.oracle.com/en/java/javase/17/docs/api/",
"https://jakarta.ee/specifications/platform/9/apidocs/",
"https://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/", // CommonJ
"https://www.ibm.com/docs/api/v1/content/SSEQTP_8.5.5/com.ibm.websphere.javadoc.doc/web/apidocs/",
"https://docs.jboss.org/jbossas/javadoc/4.0.5/connector/",
"https://docs.jboss.org/jbossas/javadoc/7.1.2.Final/",
"https://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
"https://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/", // CommonJ and weblogic.* packages
"https://www.ibm.com/docs/api/v1/content/SSEQTP_8.5.5/com.ibm.websphere.javadoc.doc/web/apidocs/", // com.ibm.*
"https://docs.jboss.org/jbossas/javadoc/4.0.5/connector/", // org.jboss.resource.*
"https://docs.jboss.org/hibernate/orm/5.6/javadocs/",
"https://eclipse.dev/aspectj/doc/released/aspectj5rt-api",
"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/",
// TODO Uncomment once httpclient5 API docs are again online.
// "https://hc.apache.org/httpcomponents-client-5.1.x/current/httpclient5/apidocs/",
"https://www.javadoc.io/doc/com.fasterxml.jackson.core/jackson-core/2.14.1/",
"https://www.javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind/2.14.1/",
"https://www.javadoc.io/doc/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.14.1/",
"https://hc.apache.org/httpcomponents-client-5.2.x/current/httpclient5/apidocs/",
"https://projectreactor.io/docs/test/release/api/",
"https://junit.org/junit4/javadoc/4.13.2/",
// TODO Uncomment link to JUnit 5 docs once we have sorted out
// the following warning in the build.
// TODO Uncomment link to JUnit 5 docs once we execute Gradle with Java 18+.
// See https://github.com/spring-projects/spring-framework/issues/27497
//
// warning: The code being documented uses packages in the unnamed module, but the packages defined in https://junit.org/junit5/docs/5.8.1/api/ are in named modules.
//
// "https://junit.org/junit5/docs/5.8.2/api/",
// "https://junit.org/junit5/docs/5.10.0/api/",
"https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/",
"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/",
"https://r2dbc.io/spec/1.0.0.RELEASE/api/",
// The external Javadoc link for JSR 305 must come last to ensure that types from
// JSR 250 (such as @PostConstruct) are still supported. This is due to the fact
// that JSR 250 and JSR 305 both define types in javax.annotation, which results
// in a split package, and the javadoc tool does not support split packages
// across multiple external Javadoc sites.
// Previously there could be a split-package issue between JSR250 and JSR305 javax.annotation packages,
// but since 6.0 JSR 250 annotations such as @Resource and @PostConstruct have been replaced by their
// JakartaEE equivalents in the jakarta.annotation package.
"https://www.javadoc.io/doc/com.google.code.findbugs/jsr305/3.0.2/"
] as String[]
}
@@ -368,35 +115,5 @@ configure(moduleProjects) { project ->
configure(rootProject) {
description = "Spring Framework"
apply plugin: "kotlin"
apply plugin: "io.spring.nohttp"
apply plugin: 'org.springframework.build.api-diff'
apply from: "${rootDir}/gradle/publications.gradle"
apply from: "${rootDir}/gradle/docs.gradle"
nohttp {
source.exclude "**/test-output/**"
allowlistFile = project.file("src/nohttp/allowlist.lines")
def rootPath = file(rootDir).toPath()
def projectDirs = allprojects.collect { it.projectDir } + "${rootDir}/buildSrc"
projectDirs.forEach { dir ->
[ 'bin', 'build', 'out', '.settings' ]
.collect { rootPath.relativize(new File(dir, it).toPath()) }
.forEach { source.exclude "$it/**" }
[ '.classpath', '.project' ]
.collect { rootPath.relativize(new File(dir, it).toPath()) }
.forEach { source.exclude "$it" }
}
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact docsZip
artifact schemaZip
artifact distZip
}
}
}
}
+5 -2
View File
@@ -5,9 +5,12 @@ They are declared in the `build.gradle` file in this folder.
## Build Conventions
### Compiler conventions
The `org.springframework.build.conventions` plugin applies all conventions to the Framework build:
* Configuring the Java compiler, see `JavaConventions`
* Configuring the Kotlin compiler, see `KotlinConventions`
* Configuring testing in the build with `TestConventions`
The `org.springframework.build.compile` plugin applies the Java compiler conventions to the build.
## Build Plugins
+20 -3
View File
@@ -1,5 +1,7 @@
plugins {
id 'java-gradle-plugin'
id 'checkstyle'
id 'io.spring.javaformat' version "${javaFormatVersion}"
}
repositories {
@@ -7,8 +9,23 @@ repositories {
gradlePluginPortal()
}
ext {
def propertiesFile = new File(new File("$projectDir").parentFile, "gradle.properties")
propertiesFile.withInputStream {
def properties = new Properties()
properties.load(it)
set("kotlinVersion", properties["kotlinVersion"])
}
}
dependencies {
checkstyle "io.spring.javaformat:spring-javaformat-checkstyle:${javaFormatVersion}"
implementation "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}"
implementation "org.jetbrains.kotlin:kotlin-compiler-embeddable:${kotlinVersion}"
implementation "me.champeau.gradle:japicmp-gradle-plugin:0.3.0"
implementation "org.gradle:test-retry-gradle-plugin:1.4.1"
implementation "io.spring.javaformat:spring-javaformat-gradle-plugin:${javaFormatVersion}"
implementation "io.spring.nohttp:nohttp-gradle:0.0.11"
}
gradlePlugin {
@@ -17,9 +34,9 @@ gradlePlugin {
id = "org.springframework.build.api-diff"
implementationClass = "org.springframework.build.api.ApiDiffPlugin"
}
compileConventionsPlugin {
id = "org.springframework.build.compile"
implementationClass = "org.springframework.build.compile.CompilerConventionsPlugin"
conventionsPlugin {
id = "org.springframework.build.conventions"
implementationClass = "org.springframework.build.ConventionsPlugin"
}
optionalDependenciesPlugin {
id = "org.springframework.build.optional-dependencies"
+1
View File
@@ -1 +1,2 @@
org.gradle.caching=true
javaFormatVersion=0.0.38
@@ -0,0 +1,79 @@
/*
* 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.
* 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.build;
import java.io.File;
import java.nio.file.Path;
import java.util.List;
import io.spring.javaformat.gradle.SpringJavaFormatPlugin;
import io.spring.nohttp.gradle.NoHttpExtension;
import io.spring.nohttp.gradle.NoHttpPlugin;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.plugins.quality.Checkstyle;
import org.gradle.api.plugins.quality.CheckstyleExtension;
import org.gradle.api.plugins.quality.CheckstylePlugin;
/**
* {@link Plugin} that applies conventions for checkstyle.
*
* @author Brian Clozel
*/
public class CheckstyleConventions {
/**
* Applies the Spring Java Format and Checkstyle plugins with the project conventions.
* @param project the current project
*/
public void apply(Project project) {
project.getPlugins().withType(JavaBasePlugin.class, (java) -> {
if (project.getRootProject() == project) {
configureNoHttpPlugin(project);
}
project.getPlugins().apply(CheckstylePlugin.class);
project.getTasks().withType(Checkstyle.class).forEach(checkstyle -> checkstyle.getMaxHeapSize().set("1g"));
CheckstyleExtension checkstyle = project.getExtensions().getByType(CheckstyleExtension.class);
checkstyle.setToolVersion("10.12.1");
checkstyle.getConfigDirectory().set(project.getRootProject().file("src/checkstyle"));
String version = SpringJavaFormatPlugin.class.getPackage().getImplementationVersion();
DependencySet checkstyleDependencies = project.getConfigurations().getByName("checkstyle").getDependencies();
checkstyleDependencies
.add(project.getDependencies().create("io.spring.javaformat:spring-javaformat-checkstyle:" + version));
});
}
private static void configureNoHttpPlugin(Project project) {
project.getPlugins().apply(NoHttpPlugin.class);
NoHttpExtension noHttp = project.getExtensions().getByType(NoHttpExtension.class);
noHttp.setAllowlistFile(project.file("src/nohttp/allowlist.lines"));
noHttp.getSource().exclude("**/test-output/**", "**/.settings/**",
"**/.classpath", "**/.project", "**/.gradle/**");
List<String> buildFolders = List.of("bin", "build", "out");
project.allprojects(subproject -> {
Path rootPath = project.getRootDir().toPath();
Path projectPath = rootPath.relativize(subproject.getProjectDir().toPath());
for (String buildFolder : buildFolders) {
Path innerBuildDir = projectPath.resolve(buildFolder);
noHttp.getSource().exclude(innerBuildDir + File.separator + "**");
}
});
}
}
@@ -0,0 +1,45 @@
/*
* 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.
* 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.build;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaBasePlugin;
import org.jetbrains.kotlin.gradle.plugin.KotlinBasePlugin;
/**
* Plugin to apply conventions to projects that are part of Spring Framework's build.
* Conventions are applied in response to various plugins being applied.
*
* <p>When the {@link JavaBasePlugin} is applied, the conventions in {@link CheckstyleConventions},
* {@link TestConventions} and {@link JavaConventions} are applied.
* When the {@link KotlinBasePlugin} is applied, the conventions in {@link KotlinConventions}
* are applied.
*
* @author Brian Clozel
*/
public class ConventionsPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
new CheckstyleConventions().apply(project);
new JavaConventions().apply(project);
new KotlinConventions().apply(project);
new TestConventions().apply(project);
}
}
@@ -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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.build.compile;
package org.springframework.build;
import java.util.ArrayList;
import java.util.Arrays;
@@ -22,9 +22,11 @@ import java.util.List;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaLibraryPlugin;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.jvm.toolchain.JavaLanguageVersion;
/**
* {@link Plugin} that applies conventions for compiling Java sources in Spring Framework.
@@ -33,7 +35,7 @@ import org.gradle.api.tasks.compile.JavaCompile;
* @author Sam Brannen
* @author Sebastien Deleuze
*/
public class CompilerConventionsPlugin implements Plugin<Project> {
public class JavaConventions {
private static final List<String> COMPILER_ARGS;
@@ -58,9 +60,8 @@ public class CompilerConventionsPlugin implements Plugin<Project> {
"-Xlint:-deprecation", "-Xlint:-unchecked"));
}
@Override
public void apply(Project project) {
project.getPlugins().withType(JavaLibraryPlugin.class, javaPlugin -> applyJavaCompileConventions(project));
project.getPlugins().withType(JavaBasePlugin.class, javaPlugin -> applyJavaCompileConventions(project));
}
/**
@@ -69,6 +70,8 @@ public class CompilerConventionsPlugin implements Plugin<Project> {
* @param project the current project
*/
private void applyJavaCompileConventions(Project project) {
project.getExtensions().getByType(JavaPluginExtension.class)
.getToolchain().getLanguageVersion().set(JavaLanguageVersion.of(17));
project.getTasks().withType(JavaCompile.class)
.matching(compileTask -> compileTask.getName().equals(JavaPlugin.COMPILE_JAVA_TASK_NAME))
.forEach(compileTask -> {
@@ -0,0 +1,48 @@
/*
* 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.build;
import java.util.ArrayList;
import java.util.List;
import org.gradle.api.Project;
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions;
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile;
/**
* @author Brian Clozel
*/
public class KotlinConventions {
void apply(Project project) {
project.getPlugins().withId("org.jetbrains.kotlin.jvm",
(plugin) -> project.getTasks().withType(KotlinCompile.class, this::configure));
}
private void configure(KotlinCompile compile) {
KotlinJvmOptions kotlinOptions = compile.getKotlinOptions();
kotlinOptions.setApiVersion("1.7");
kotlinOptions.setLanguageVersion("1.7");
kotlinOptions.setJvmTarget("17");
kotlinOptions.setJavaParameters(true);
kotlinOptions.setAllWarningsAsErrors(true);
List<String> freeCompilerArgs = new ArrayList<>(compile.getKotlinOptions().getFreeCompilerArgs());
freeCompilerArgs.addAll(List.of("-Xsuppress-version-warnings", "-Xjsr305=strict", "-opt-in=kotlin.RequiresOptIn"));
compile.getKotlinOptions().setFreeCompilerArgs(freeCompilerArgs);
}
}
@@ -0,0 +1,82 @@
/*
* 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.
* 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.build;
import java.util.Map;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.tasks.testing.Test;
import org.gradle.testretry.TestRetryPlugin;
import org.gradle.testretry.TestRetryTaskExtension;
/**
* Conventions that are applied in the presence of the {@link JavaBasePlugin}. When the
* plugin is applied:
* <ul>
* <li>The {@link TestRetryPlugin Test Retry} plugin is applied so that flaky tests
* are retried 3 times when running on the CI server.
* </ul>
*
* @author Brian Clozel
* @author Andy Wilkinson
*/
class TestConventions {
void apply(Project project) {
project.getPlugins().withType(JavaBasePlugin.class, (java) -> configureTestConventions(project));
}
private void configureTestConventions(Project project) {
project.getTasks().withType(Test.class,
test -> {
configureTests(project, test);
configureTestRetryPlugin(project, test);
});
}
private void configureTests(Project project, Test test) {
test.useJUnitPlatform();
test.include("**/*Tests.class", "**/*Test.class");
test.setSystemProperties(Map.of(
"java.awt.headless", "true",
"io.netty.leakDetection.level", "paranoid",
"io.netty5.leakDetectionLevel", "paranoid",
"io.netty5.leakDetection.targetRecords", "32",
"io.netty5.buffer.lifecycleTracingEnabled", "true"
));
if (project.hasProperty("testGroups")) {
test.systemProperty("testGroups", project.getProperties().get("testGroups"));
}
test.jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED",
"--add-opens=java.base/java.util=ALL-UNNAMED",
"-Djava.locale.providers=COMPAT");
}
private void configureTestRetryPlugin(Project project, Test test) {
project.getPlugins().withType(TestRetryPlugin.class, testRetryPlugin -> {
TestRetryTaskExtension testRetry = test.getExtensions().getByType(TestRetryTaskExtension.class);
testRetry.getFailOnPassedAfterRetry().set(true);
testRetry.getMaxRetries().set(isCi() ? 3 : 0);
});
}
private boolean isCi() {
return Boolean.parseBoolean(System.getenv("CI"));
}
}
@@ -24,23 +24,22 @@ import java.util.List;
import me.champeau.gradle.japicmp.JapicmpPlugin;
import me.champeau.gradle.japicmp.JapicmpTask;
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.repositories.ArtifactRepository;
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import org.gradle.api.artifacts.repositories.RepositoryContentDescriptor;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.jvm.tasks.Jar;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* {@link Plugin} that applies the {@code "japicmp-gradle-plugin"}
* and create tasks for all subprojects, diffing the public API one by one
* and create tasks for all subprojects named {@code "spring-*"}, diffing the public API one by one
* and creating the reports in {@code "build/reports/api-diff/$OLDVERSION_to_$NEWVERSION/"}.
* <p>{@code "./gradlew apiDiff -PbaselineVersion=5.1.0.RELEASE"} will output the
* reports for the API diff between the baseline version and the current one for all modules.
@@ -51,6 +50,8 @@ import org.gradle.jvm.tasks.Jar;
*/
public class ApiDiffPlugin implements Plugin<Project> {
private static final Logger logger = LoggerFactory.getLogger(ApiDiffPlugin.class);
public static final String TASK_NAME = "apiDiff";
private static final String BASELINE_VERSION_PROPERTY = "baselineVersion";
@@ -70,7 +71,11 @@ public class ApiDiffPlugin implements Plugin<Project> {
private void applyApiDiffConventions(Project project) {
String baselineVersion = project.property(BASELINE_VERSION_PROPERTY).toString();
project.subprojects(subProject -> createApiDiffTask(baselineVersion, subProject));
project.subprojects(subProject -> {
if (subProject.getName().startsWith("spring-")) {
createApiDiffTask(baselineVersion, subProject);
}
});
}
private void createApiDiffTask(String baselineVersion, Project project) {
@@ -83,7 +88,7 @@ public class ApiDiffPlugin implements Plugin<Project> {
apiDiff.setDescription("Generates an API diff report with japicmp");
apiDiff.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP);
apiDiff.setOldClasspath(project.files(createBaselineConfiguration(baselineVersion, project)));
apiDiff.setOldClasspath(createBaselineConfiguration(baselineVersion, project));
TaskProvider<Jar> jar = project.getTasks().withType(Jar.class).named("jar");
apiDiff.setNewArchives(project.getLayout().files(jar.get().getArchiveFile().get().getAsFile()));
apiDiff.setNewClasspath(getRuntimeClassPath(project));
@@ -109,7 +114,16 @@ public class ApiDiffPlugin implements Plugin<Project> {
String baseline = String.join(":",
project.getGroup().toString(), project.getName(), baselineVersion);
Dependency baselineDependency = project.getDependencies().create(baseline + "@jar");
return project.getRootProject().getConfigurations().detachedConfiguration(baselineDependency);
Configuration baselineConfiguration = project.getRootProject().getConfigurations().detachedConfiguration(baselineDependency);
try {
// eagerly resolve the baseline configuration to check whether this is a new Spring module
baselineConfiguration.resolve();
return baselineConfiguration;
}
catch (GradleException exception) {
logger.warn("Could not resolve {} - assuming this is a new Spring module.", baseline);
}
return project.getRootProject().getConfigurations().detachedConfiguration();
}
private Configuration getRuntimeClassPath(Project project) {
@@ -0,0 +1,48 @@
/*
* 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.
* 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.build.hint;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.Input;
import org.gradle.process.CommandLineArgumentProvider;
import java.util.Collections;
/**
* Argument provider for registering the runtime hints agent with a Java process.
*/
public interface RuntimeHintsAgentArgumentProvider extends CommandLineArgumentProvider {
@Classpath
ConfigurableFileCollection getAgentJar();
@Input
SetProperty<String> getIncludedPackages();
@Input
SetProperty<String> getExcludedPackages();
@Override
default Iterable<String> asArguments() {
StringBuilder packages = new StringBuilder();
getIncludedPackages().get().forEach(packageName -> packages.append('+').append(packageName).append(','));
getExcludedPackages().get().forEach(packageName -> packages.append('-').append(packageName).append(','));
return Collections.singleton("-javaagent:" + getAgentJar().getSingleFile() + "=" + packages);
}
}
@@ -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.
@@ -16,38 +16,15 @@
package org.springframework.build.hint;
import java.util.Collections;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.SetProperty;
/**
* Entry point to the DSL extension for the {@link RuntimeHintsAgentPlugin} Gradle plugin.
* @author Brian Clozel
*/
public class RuntimeHintsAgentExtension {
public interface RuntimeHintsAgentExtension {
private final SetProperty<String> includedPackages;
SetProperty<String> getIncludedPackages();
private final SetProperty<String> excludedPackages;
public RuntimeHintsAgentExtension(ObjectFactory objectFactory) {
this.includedPackages = objectFactory.setProperty(String.class).convention(Collections.singleton("org.springframework"));
this.excludedPackages = objectFactory.setProperty(String.class).convention(Collections.emptySet());
}
public SetProperty<String> getIncludedPackages() {
return this.includedPackages;
}
public SetProperty<String> getExcludedPackages() {
return this.excludedPackages;
}
String asJavaAgentArgument() {
StringBuilder builder = new StringBuilder();
this.includedPackages.get().forEach(packageName -> builder.append('+').append(packageName).append(','));
this.excludedPackages.get().forEach(packageName -> builder.append('-').append(packageName).append(','));
return builder.toString();
}
SetProperty<String> getExcludedPackages();
}
@@ -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.
@@ -16,41 +16,79 @@
package org.springframework.build.hint;
import org.gradle.api.JavaVersion;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.attributes.Bundling;
import org.gradle.api.attributes.Category;
import org.gradle.api.attributes.LibraryElements;
import org.gradle.api.attributes.Usage;
import org.gradle.api.attributes.java.TargetJvmVersion;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.tasks.bundling.Jar;
import org.gradle.api.tasks.testing.Test;
import java.util.Collections;
/**
* {@link Plugin} that configures the {@code RuntimeHints} Java agent to test tasks.
*
* @author Brian Clozel
* @author Sebastien Deleuze
*/
public class RuntimeHintsAgentPlugin implements Plugin<Project> {
public static final String RUNTIMEHINTS_TEST_TASK = "runtimeHintsTest";
private static final String EXTENSION_NAME = "runtimeHintsAgent";
private static final String CONFIGURATION_NAME = "testRuntimeHintsAgentJar";
@Override
public void apply(Project project) {
project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
RuntimeHintsAgentExtension agentExtension = project.getExtensions().create(EXTENSION_NAME,
RuntimeHintsAgentExtension.class, project.getObjects());
RuntimeHintsAgentExtension agentExtension = createRuntimeHintsAgentExtension(project);
Test agentTest = project.getTasks().create(RUNTIMEHINTS_TEST_TASK, Test.class, test -> {
test.useJUnitPlatform(options -> {
options.includeTags("RuntimeHintsTests");
});
test.include("**/*Tests.class", "**/*Test.class");
test.systemProperty("java.awt.headless", "true");
});
project.afterEvaluate(p -> {
Jar jar = project.getRootProject().project("spring-core-test").getTasks().withType(Jar.class).named("jar").get();
agentTest.jvmArgs("-javaagent:" + jar.getArchiveFile().get().getAsFile() + "=" + agentExtension.asJavaAgentArgument());
test.systemProperty("org.graalvm.nativeimage.imagecode", "runtime");
test.getJvmArgumentProviders().add(createRuntimeHintsAgentArgumentProvider(project, agentExtension));
});
project.getTasks().getByName("check", task -> task.dependsOn(agentTest));
project.getDependencies().add(CONFIGURATION_NAME, project.project(":spring-core-test"));
});
}
private static RuntimeHintsAgentExtension createRuntimeHintsAgentExtension(Project project) {
RuntimeHintsAgentExtension agentExtension = project.getExtensions().create(EXTENSION_NAME, RuntimeHintsAgentExtension.class);
agentExtension.getIncludedPackages().convention(Collections.singleton("org.springframework"));
agentExtension.getExcludedPackages().convention(Collections.emptySet());
return agentExtension;
}
private static RuntimeHintsAgentArgumentProvider createRuntimeHintsAgentArgumentProvider(
Project project, RuntimeHintsAgentExtension agentExtension) {
RuntimeHintsAgentArgumentProvider agentArgumentProvider = project.getObjects().newInstance(RuntimeHintsAgentArgumentProvider.class);
agentArgumentProvider.getAgentJar().from(createRuntimeHintsAgentConfiguration(project));
agentArgumentProvider.getIncludedPackages().set(agentExtension.getIncludedPackages());
agentArgumentProvider.getExcludedPackages().set(agentExtension.getExcludedPackages());
return agentArgumentProvider;
}
private static Configuration createRuntimeHintsAgentConfiguration(Project project) {
return project.getConfigurations().create(CONFIGURATION_NAME, configuration -> {
configuration.setCanBeConsumed(false);
configuration.setTransitive(false); // Only the built artifact is required
configuration.attributes(attributes -> {
attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, project.getObjects().named(Bundling.class, Bundling.EXTERNAL));
attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.getObjects().named(Category.class, Category.LIBRARY));
attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.getObjects().named(LibraryElements.class, LibraryElements.JAR));
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, Integer.valueOf(JavaVersion.current().getMajorVersion()));
attributes.attribute(Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, Usage.JAVA_RUNTIME));
});
});
}
}
@@ -0,0 +1,175 @@
package org.springframework.build.shadow;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.gradle.api.DefaultTask;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.component.ModuleComponentSelector;
import org.gradle.api.artifacts.query.ArtifactResolutionQuery;
import org.gradle.api.artifacts.result.ArtifactResolutionResult;
import org.gradle.api.artifacts.result.ComponentArtifactsResult;
import org.gradle.api.artifacts.result.DependencyResult;
import org.gradle.api.artifacts.result.ResolutionResult;
import org.gradle.api.artifacts.result.ResolvedArtifactResult;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.FileCopyDetails;
import org.gradle.api.file.FileTree;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import org.gradle.jvm.JvmLibrary;
import org.gradle.language.base.artifact.SourcesArtifact;
/**
* Gradle task to add source from shadowed jars into our own source jars.
*
* @author Phillip Webb
* @author Andy Wilkinson
*/
public class ShadowSource extends DefaultTask {
private final DirectoryProperty outputDirectory = getProject().getObjects().directoryProperty();
private List<Configuration> configurations = new ArrayList<>();
private final List<Relocation> relocations = new ArrayList<>();
@Classpath
@Optional
public List<Configuration> getConfigurations() {
return this.configurations;
}
public void setConfigurations(List<Configuration> configurations) {
this.configurations = configurations;
}
@Nested
public List<Relocation> getRelocations() {
return this.relocations;
}
public void relocate(String pattern, String destination) {
this.relocations.add(new Relocation(pattern, destination));
}
@OutputDirectory
DirectoryProperty getOutputDirectory() {
return this.outputDirectory;
}
@TaskAction
void syncSourceJarFiles() {
sync(getSourceJarFiles());
}
private List<File> getSourceJarFiles() {
List<File> sourceJarFiles = new ArrayList<>();
for (Configuration configuration : this.configurations) {
ResolutionResult resolutionResult = configuration.getIncoming().getResolutionResult();
resolutionResult.getRootComponent().get().getDependencies().forEach(dependency -> {
Set<ComponentArtifactsResult> artifactsResults = resolveSourceArtifacts(dependency);
for (ComponentArtifactsResult artifactResult : artifactsResults) {
artifactResult.getArtifacts(SourcesArtifact.class).forEach(sourceArtifact -> {
sourceJarFiles.add(((ResolvedArtifactResult) sourceArtifact).getFile());
});
}
});
}
return Collections.unmodifiableList(sourceJarFiles);
}
private Set<ComponentArtifactsResult> resolveSourceArtifacts(DependencyResult dependency) {
ModuleComponentSelector componentSelector = (ModuleComponentSelector) dependency.getRequested();
ArtifactResolutionQuery query = getProject().getDependencies().createArtifactResolutionQuery()
.forModule(componentSelector.getGroup(), componentSelector.getModule(), componentSelector.getVersion());
return executeQuery(query).getResolvedComponents();
}
@SuppressWarnings("unchecked")
private ArtifactResolutionResult executeQuery(ArtifactResolutionQuery query) {
return query.withArtifacts(JvmLibrary.class, SourcesArtifact.class).execute();
}
private void sync(List<File> sourceJarFiles) {
getProject().sync(spec -> {
spec.into(this.outputDirectory);
spec.eachFile(this::relocateFile);
spec.filter(this::transformContent);
spec.exclude("META-INF/**");
spec.setIncludeEmptyDirs(false);
sourceJarFiles.forEach(sourceJar -> spec.from(zipTree(sourceJar)));
});
}
private void relocateFile(FileCopyDetails details) {
String path = details.getPath();
for (Relocation relocation : this.relocations) {
path = relocation.relocatePath(path);
}
details.setPath(path);
}
private String transformContent(String content) {
for (Relocation relocation : this.relocations) {
content = relocation.transformContent(content);
}
return content;
}
private FileTree zipTree(File sourceJar) {
return getProject().zipTree(sourceJar);
}
/**
* A single relocation.
*/
static class Relocation {
private final String pattern;
private final String pathPattern;
private final String destination;
private final String pathDestination;
Relocation(String pattern, String destination) {
this.pattern = pattern;
this.pathPattern = pattern.replace('.', '/');
this.destination = destination;
this.pathDestination = destination.replace('.', '/');
}
@Input
public String getPattern() {
return this.pattern;
}
@Input
public String getDestination() {
return this.destination;
}
String relocatePath(String path) {
return path.replace(this.pathPattern, this.pathDestination);
}
public String transformContent(String content) {
return content.replaceAll("\\b" + this.pattern, this.destination);
}
}
}
+3
View File
@@ -15,3 +15,6 @@ changelog:
sort: "title"
labels:
- "type: dependency-upgrade"
contributors:
exclude:
names: ["bclozel", "jhoeller", "poutsma", "rstoyanchev", "sbrannen", "sdeleuze", "snicoll", "simonbasle"]
+2 -2
View File
@@ -1,4 +1,4 @@
FROM ubuntu:focal-20220531
FROM ubuntu:jammy-20230425
ADD setup.sh /setup.sh
ADD get-jdk-url.sh /get-jdk-url.sh
@@ -6,6 +6,6 @@ RUN ./setup.sh
ENV JAVA_HOME /opt/openjdk/java17
ENV JDK17 /opt/openjdk/java17
ENV JDK18 /opt/openjdk/java18
ENV JDK21 /opt/openjdk/java21
ENV PATH $JAVA_HOME/bin:$PATH
+3 -3
View File
@@ -3,10 +3,10 @@ set -e
case "$1" in
java17)
echo "https://github.com/bell-sw/Liberica/releases/download/17.0.3.1+2/bellsoft-jdk17.0.3.1+2-linux-amd64.tar.gz"
echo "https://github.com/bell-sw/Liberica/releases/download/17.0.7+7/bellsoft-jdk17.0.7+7-linux-amd64.tar.gz"
;;
java18)
echo "https://github.com/bell-sw/Liberica/releases/download/18.0.1.1+2/bellsoft-jdk18.0.1.1+2-linux-amd64.tar.gz"
java21)
echo "https://download.java.net/java/early_access/jdk21/31/GPL/openjdk-21-ea+31_linux-x64_bin.tar.gz"
;;
*)
echo $"Unknown java version"
+1 -1
View File
@@ -20,7 +20,7 @@ curl https://raw.githubusercontent.com/spring-io/concourse-java-scripts/v0.0.4/c
mkdir -p /opt/openjdk
pushd /opt/openjdk > /dev/null
for jdk in java17 java18
for jdk in java17 java21
do
JDK_URL=$( /get-jdk-url.sh $jdk )
mkdir $jdk
+1 -4
View File
@@ -4,11 +4,8 @@ sonatype-staging-profile: "org.springframework"
docker-hub-organization: "springci"
artifactory-server: "https://repo.spring.io"
branch: "main"
milestone: "6.0.x"
milestone: "6.1.x"
build-name: "spring-framework"
pipeline-name: "spring-framework"
concourse-url: "https://ci.spring.io"
registry-mirror-host: docker.repo.spring.io
registry-mirror-username: ((artifactory-username))
registry-mirror-password: ((artifactory-password))
task-timeout: 1h00m
+26 -67
View File
@@ -23,11 +23,6 @@ anchors:
docker-resource-source: &docker-resource-source
username: ((docker-hub-username))
password: ((docker-hub-password))
tag: ((milestone))
registry-mirror-vars: &registry-mirror-vars
registry-mirror-host: ((registry-mirror-host))
registry-mirror-username: ((registry-mirror-username))
registry-mirror-password: ((registry-mirror-password))
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!>
@@ -48,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.8.0
- 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:
@@ -94,6 +89,7 @@ resources:
source:
<<: *docker-resource-source
repository: ((docker-hub-organization))/spring-framework-ci
tag: ((milestone))
- name: every-morning
type: time
icon: alarm
@@ -109,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
@@ -125,14 +113,14 @@ resources:
access_token: ((github-ci-status-token))
branch: ((branch))
context: build
- name: repo-status-jdk18-build
- name: repo-status-jdk21-build
type: github-status-resource
icon: eye-check-outline
source:
repository: ((github-repo-name))
access_token: ((github-ci-status-token))
branch: ((branch))
context: jdk18-build
context: jdk21-build
- name: slack-alert
type: slack-notification
icon: slack
@@ -168,7 +156,7 @@ jobs:
image: ci-image
vars:
ci-image-name: ci-image
<<: *registry-mirror-vars
<<: *docker-resource-source
- put: ci-image
params:
image: ci-image/image.tar
@@ -210,26 +198,26 @@ jobs:
threads: 8
artifact_set:
- include:
- "/**/spring-*.zip"
- "/**/framework-docs-*.zip"
properties:
"zip.name": "spring-framework"
"zip.displayname": "Spring Framework"
"zip.deployed": "false"
- include:
- "/**/spring-*-docs.zip"
- "/**/framework-docs-*-docs.zip"
properties:
"zip.type": "docs"
- include:
- "/**/spring-*-dist.zip"
- "/**/framework-docs-*-dist.zip"
properties:
"zip.type": "dist"
- include:
- "/**/spring-*-schema.zip"
- "/**/framework-docs-*-schema.zip"
properties:
"zip.type": "schema"
get_params:
threads: 8
- name: jdk18-build
- name: jdk21-build
serial: true
public: true
plan:
@@ -237,7 +225,7 @@ jobs:
- get: git-repo
- get: every-morning
trigger: true
- put: repo-status-jdk18-build
- put: repo-status-jdk21-build
params: { state: "pending", commit: "git-repo" }
- do:
- task: check-project
@@ -246,48 +234,17 @@ jobs:
privileged: true
timeout: ((task-timeout))
params:
TEST_TOOLCHAIN: 18
TEST_TOOLCHAIN: 21
<<: *build-project-task-params
on_failure:
do:
- put: repo-status-jdk18-build
- put: repo-status-jdk21-build
params: { state: "failure", commit: "git-repo" }
- put: slack-alert
params:
<<: *slack-fail-params
- put: repo-status-jdk18-build
- put: repo-status-jdk21-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:
@@ -329,6 +286,7 @@ jobs:
params:
RELEASE_TYPE: M
<<: *github-task-params
<<: *docker-resource-source
- put: github-pre-release
params:
<<: *changelog-task-params
@@ -367,6 +325,7 @@ jobs:
file: git-repo/ci/tasks/promote-version.yml
params:
RELEASE_TYPE: RC
<<: *docker-resource-source
<<: *artifactory-task-params
- task: generate-changelog
file: git-repo/ci/tasks/generate-changelog.yml
@@ -411,6 +370,7 @@ jobs:
file: git-repo/ci/tasks/promote-version.yml
params:
RELEASE_TYPE: RELEASE
<<: *docker-resource-source
<<: *artifactory-task-params
<<: *sonatype-task-params
- name: create-github-release
@@ -428,6 +388,7 @@ jobs:
file: git-repo/ci/tasks/generate-changelog.yml
params:
RELEASE_TYPE: RELEASE
<<: *docker-resource-source
<<: *github-task-params
- put: github-release
params:
@@ -435,10 +396,8 @@ jobs:
groups:
- name: "builds"
jobs: ["build", "jdk18-build"]
jobs: ["build", "jdk21-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" ]
+2 -1
View File
@@ -4,5 +4,6 @@ set -e
source $(dirname $0)/common.sh
pushd git-repo > /dev/null
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false --no-daemon --max-workers=4 check
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK21 \
--no-daemon --max-workers=4 check
popd > /dev/null
+2 -1
View File
@@ -5,5 +5,6 @@ source $(dirname $0)/common.sh
repository=$(pwd)/distribution-repository
pushd git-repo > /dev/null
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false --no-daemon --max-workers=4 -PdeploymentRepository=${repository} build publishAllPublicationsToDeploymentRepository
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK21 \
--no-daemon --max-workers=4 -PdeploymentRepository=${repository} build publishAllPublicationsToDeploymentRepository
popd > /dev/null
+2 -2
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=JDK17,JDK18 \
-PmainToolchain=${MAIN_TOOLCHAIN} -PtestToolchain=${TEST_TOOLCHAIN} --no-daemon --max-workers=4 check
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK21 \
-PmainToolchain=${MAIN_TOOLCHAIN} -PtestToolchain=${TEST_TOOLCHAIN} --no-daemon --max-workers=4 check antora
popd > /dev/null
+2 -1
View File
@@ -35,7 +35,8 @@ git add gradle.properties > /dev/null
git commit -m"Release v$stageVersion" > /dev/null
git tag -a "v$stageVersion" -m"Release v$stageVersion" > /dev/null
./gradlew --no-daemon --max-workers=4 -PdeploymentRepository=${repository} build publishAllPublicationsToDeploymentRepository
./gradlew --no-daemon --max-workers=4 -PdeploymentRepository=${repository} -Porg.gradle.java.installations.fromEnv=JDK17,JDK21 \
build publishAllPublicationsToDeploymentRepository
git reset --hard HEAD^ > /dev/null
if [[ $nextVersion != $snapshotVersion ]]; then
+2 -4
View File
@@ -5,10 +5,8 @@ image_resource:
source:
repository: concourse/oci-build-task
tag: 0.10.0
registry_mirror:
host: ((registry-mirror-host))
username: ((registry-mirror-username))
password: ((registry-mirror-password))
username: ((docker-hub-username))
password: ((docker-hub-password))
inputs:
- name: ci-images-git-repo
outputs:
+3 -1
View File
@@ -4,7 +4,9 @@ image_resource:
type: registry-image
source:
repository: springio/github-changelog-generator
tag: '0.0.7'
tag: '0.0.8'
username: ((docker-hub-username))
password: ((docker-hub-password))
inputs:
- name: git-repo
- name: artifactory-repo
+2
View File
@@ -5,6 +5,8 @@ image_resource:
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
+1 -1
View File
@@ -7,7 +7,7 @@ group = "org.springframework"
dependencies {
constraints {
parent.moduleProjects.findAll{ it.name != 'spring-core-graalvm' }.sort { "$it.name" }.each {
parent.moduleProjects.sort { "$it.name" }.each {
api it
}
}
+32
View File
@@ -0,0 +1,32 @@
name: framework
version: true
title: Spring Framework
nav:
- modules/ROOT/nav.adoc
ext:
collector:
run:
command: gradlew -q -PbuildSrc.skipTests=true "-Dorg.gradle.jvmargs=-Xmx3g -XX:+HeapDumpOnOutOfMemoryError" :framework-docs:generateAntoraResources
local: true
scan:
dir: ./build/generated-antora-resources
asciidoc:
attributes:
attribute-missing: 'warn'
# FIXME: the copyright is not removed
# FIXME: The package is not renamed
chomp: 'all'
include-java: 'example$docs-src/main/java/org/springframework/docs'
spring-framework-main-code: 'https://github.com/spring-projects/spring-framework/tree/main'
docs-site: 'https://docs.spring.io'
docs-spring: "{docs-site}/spring-framework/docs/{spring-version}"
docs-spring-framework: '{docs-site}/spring-framework/docs/{spring-version}'
api-spring-framework: '{docs-spring-framework}/javadoc-api/org/springframework'
docs-graalvm: 'https://www.graalvm.org/22.3/reference-manual'
docs-spring-boot: '{docs-site}/spring-boot/docs/current/reference'
docs-spring-gemfire: '{docs-site}/spring-gemfire/docs/current/reference'
docs-spring-security: '{docs-site}/spring-security/reference'
gh-rsocket: 'https://github.com/rsocket'
gh-rsocket-extensions: '{gh-rsocket}/rsocket/blob/master/Extensions'
gh-rsocket-java: '{gh-rsocket}/rsocket-java{gh-rsocket}/rsocket-java'
@@ -1,24 +1,75 @@
ext {
documentedProjects = moduleProjects.findAll { it.name != 'spring-core-graalvm' }
plugins {
id 'kotlin'
id 'io.spring.antora.generate-antora-yml' version '0.0.1'
id 'org.antora' version '1.0.0'
}
configurations {
asciidoctorExt
description = "Spring Framework Docs"
apply from: "${rootDir}/gradle/publications.gradle"
antora {
version = '3.2.0-alpha.2'
playbook = 'cached-antora-playbook.yml'
playbookProvider {
repository = 'spring-projects/spring-framework'
branch = 'docs-build'
path = 'lib/antora/templates/per-branch-antora-playbook.yml'
checkLocalBranch = true
}
options = ['--clean', '--stacktrace']
environment = [
'ALGOLIA_API_KEY': '82c7ead946afbac3cf98c32446154691',
'ALGOLIA_APP_ID': '244V8V9FGG',
'ALGOLIA_INDEX_NAME': 'framework-docs'
]
dependencies = [
'@antora/atlas-extension': '1.0.0-alpha.1',
'@antora/collector-extension': '1.0.0-alpha.3',
'@asciidoctor/tabs': '1.0.0-beta.3',
'@opendevise/antora-release-line-extension': '1.0.0-alpha.2',
'@springio/antora-extensions': '1.3.0',
'@springio/asciidoctor-extensions': '1.0.0-alpha.9'
]
}
dependencies {
asciidoctorExt("io.spring.asciidoctor:spring-asciidoctor-extensions-block-switch:0.5.0")
tasks.named("generateAntoraYml") {
asciidocAttributes = project.provider( {
return ["spring-version": project.version ]
} )
}
tasks.create("generateAntoraResources") {
dependsOn 'generateAntoraYml'
}
jar {
enabled = false
}
javadoc {
enabled = false
}
repositories {
maven {
url "https://repo.spring.io/release"
mavenContent {
includeGroup "io.spring.asciidoctor"
}
}
}
dependencies {
api(project(":spring-context"))
api(project(":spring-jms"))
api(project(":spring-web"))
api("jakarta.jms:jakarta.jms-api")
api("jakarta.servlet:jakarta.servlet-api")
implementation(project(":spring-core-test"))
implementation("org.assertj:assertj-core")
}
/**
* Produce Javadoc for all Spring Framework modules in "build/docs/javadoc"
*/
@@ -28,7 +79,7 @@ task api(type: Javadoc) {
title = "${rootProject.description} ${version} API"
dependsOn {
documentedProjects.collect {
moduleProjects.collect {
it.tasks.getByName("jar")
}
}
@@ -37,7 +88,7 @@ task api(type: Javadoc) {
// ensure the javadoc process can resolve types compiled from .aj sources
project(":spring-aspects").sourceSets.main.output
)
classpath += files(documentedProjects.collect { it.sourceSets.main.compileClasspath })
classpath += files(moduleProjects.collect { it.sourceSets.main.compileClasspath })
}
options {
@@ -46,13 +97,13 @@ task api(type: Javadoc) {
author = true
header = rootProject.description
use = true
overview = "src/docs/api/overview.html"
overview = "framework-docs/src/docs/api/overview.html"
splitIndex = true
links(project.ext.javadocLinks)
addBooleanOption('Xdoclint:syntax', true) // only check syntax with doclint
addBooleanOption('Xdoclint:syntax,reference', true) // only check syntax and reference with doclint
addBooleanOption('Werror', true) // fail build on Javadoc warnings
}
source documentedProjects.collect { project ->
source moduleProjects.collect { project ->
project.sourceSets.main.allJava
}
maxMemory = "1024m"
@@ -62,98 +113,21 @@ task api(type: Javadoc) {
/**
* Produce KDoc for all Spring Framework modules in "build/docs/kdoc"
*/
pluginManager.withPlugin("kotlin") {
tasks.dokkaHtmlMultiModule.configure {
dependsOn {
tasks.getByName("api")
}
moduleName.set("spring-framework")
outputDirectory.set(project.file("$buildDir/docs/kdoc"))
rootProject.tasks.dokkaHtmlMultiModule.configure {
dependsOn {
tasks.getByName("api")
}
}
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"
dest project.file("$buildDir/docs/spring-doc-resources.zip")
onlyIfModified true
useETag "all"
}
task extractDocResources(type: Copy, dependsOn: downloadResources) {
from project.zipTree(downloadResources.dest);
into "$buildDir/docs/spring-docs-resources/"
}
asciidoctorj {
def docRoot = 'https://docs.spring.io'
def docsSpringFramework = "${docRoot}/spring-framework/docs/${project.version}"
version = '2.4.1'
fatalWarnings ".*"
options doctype: 'book', eruby: 'erubis'
attributes([
icons: 'font',
idprefix: '',
idseparator: '-',
docinfo: 'shared,private-header', // https://docs.asciidoctor.org/asciidoctor/latest/docinfo/
revnumber: project.version,
sectanchors: '',
sectnums: '',
'source-highlighter': 'highlight.js',
highlightjsdir: 'js/highlight',
'highlightjs-theme': 'googlecode',
stylesdir: 'css/',
stylesheet: 'stylesheet.css',
'spring-version': project.version,
'spring-framework-main-code': 'https://github.com/spring-projects/spring-framework/tree/main',
'doc-root': docRoot,
'docs-spring-framework': docsSpringFramework,
'api-spring-framework': "${docsSpringFramework}/javadoc-api/org/springframework"
])
moduleName.set("spring-framework")
outputDirectory.set(project.file("$buildDir/docs/kdoc"))
}
/**
* Generate the Spring Framework Reference documentation from "src/docs/asciidoc"
* in "build/docs/ref-docs/html5".
* Zip all Java docs (javadoc & kdoc) into a single archive
*/
asciidoctor {
baseDirFollowsSourceDir()
configurations 'asciidoctorExt'
sources {
include '*.adoc'
}
outputDir "$buildDir/docs/ref-docs/html5"
logDocuments = true
resources {
from(sourceDir) {
include 'images/*.png', 'css/**', 'js/**'
}
from extractDocResources
}
}
/**
* Generate the Spring Framework Reference documentation from "src/docs/asciidoc"
* in "build/docs/ref-docs/pdf".
*/
asciidoctorPdf {
baseDirFollowsSourceDir()
configurations 'asciidoctorExt'
sources {
include '*.adoc'
}
outputDir "$buildDir/docs/ref-docs/pdf"
logDocuments = true
}
/**
* Zip all docs (API and reference) into a single archive
*/
task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'asciidoctorPdf', 'dokkaHtmlMultiModule']) {
task docsZip(type: Zip, dependsOn: ['api', rootProject.tasks.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")
@@ -163,13 +137,7 @@ task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'asciidoctorPdf', 'dok
from (api) {
into "javadoc-api"
}
from ("$asciidoctor.outputDir") {
into "reference/html"
}
from ("$asciidoctorPdf.outputDir") {
into "reference/pdf"
}
from (dokkaHtmlMultiModule.outputDirectory) {
from (rootProject.tasks.dokkaHtmlMultiModule.outputDirectory) {
into "kdoc-api"
}
}
@@ -184,7 +152,7 @@ task schemaZip(type: Zip) {
description = "Builds -${archiveClassifier} archive containing all " +
"XSDs for deployment at https://springframework.org/schema."
duplicatesStrategy DuplicatesStrategy.EXCLUDE
documentedProjects.each { module ->
moduleProjects.each { module ->
def Properties schemas = new Properties();
module.sourceSets.main.resources.find {
@@ -234,7 +202,7 @@ task distZip(type: Zip, dependsOn: [docsZip, schemaZip]) {
into "${baseDir}/schema"
}
documentedProjects.each { module ->
moduleProjects.each { module ->
into ("${baseDir}/libs") {
from module.jar
if (module.tasks.findByPath("sourcesJar")) {
@@ -247,4 +215,14 @@ task distZip(type: Zip, dependsOn: [docsZip, schemaZip]) {
}
}
distZip.mustRunAfter documentedProjects.check
distZip.mustRunAfter moduleProjects.check
publishing {
publications {
mavenJava(MavenPublication) {
artifact docsZip
artifact schemaZip
artifact distZip
}
}
}

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

+1
View File
@@ -0,0 +1 @@
../../../src
+438
View File
@@ -0,0 +1,438 @@
* xref:overview.adoc[Overview]
* xref:core.adoc[]
** xref:core/beans.adoc[]
*** xref:core/beans/introduction.adoc[]
*** xref:core/beans/basics.adoc[]
*** xref:core/beans/definition.adoc[]
*** xref:core/beans/dependencies.adoc[]
**** xref:core/beans/dependencies/factory-collaborators.adoc[]
**** xref:core/beans/dependencies/factory-properties-detailed.adoc[]
**** xref:core/beans/dependencies/factory-dependson.adoc[]
**** xref:core/beans/dependencies/factory-lazy-init.adoc[]
**** xref:core/beans/dependencies/factory-autowire.adoc[]
**** xref:core/beans/dependencies/factory-method-injection.adoc[]
*** xref:core/beans/factory-scopes.adoc[]
*** xref:core/beans/factory-nature.adoc[]
*** xref:core/beans/child-bean-definitions.adoc[]
*** xref:core/beans/factory-extension.adoc[]
*** xref:core/beans/annotation-config.adoc[]
**** xref:core/beans/annotation-config/autowired.adoc[]
**** xref:core/beans/annotation-config/autowired-primary.adoc[]
**** xref:core/beans/annotation-config/autowired-qualifiers.adoc[]
**** xref:core/beans/annotation-config/generics-as-qualifiers.adoc[]
**** xref:core/beans/annotation-config/custom-autowire-configurer.adoc[]
**** xref:core/beans/annotation-config/resource.adoc[]
**** xref:core/beans/annotation-config/value-annotations.adoc[]
**** xref:core/beans/annotation-config/postconstruct-and-predestroy-annotations.adoc[]
*** xref:core/beans/classpath-scanning.adoc[]
*** xref:core/beans/standard-annotations.adoc[]
*** xref:core/beans/java.adoc[]
**** xref:core/beans/java/basic-concepts.adoc[]
**** xref:core/beans/java/instantiating-container.adoc[]
**** xref:core/beans/java/bean-annotation.adoc[]
**** xref:core/beans/java/configuration-annotation.adoc[]
**** xref:core/beans/java/composing-configuration-classes.adoc[]
*** xref:core/beans/environment.adoc[]
*** xref:core/beans/context-load-time-weaver.adoc[]
*** xref:core/beans/context-introduction.adoc[]
*** xref:core/beans/beanfactory.adoc[]
** xref:core/resources.adoc[]
** xref:core/validation.adoc[]
*** xref:core/validation/validator.adoc[]
*** xref:core/validation/conversion.adoc[]
*** xref:core/validation/beans-beans.adoc[]
*** xref:core/validation/convert.adoc[]
*** xref:core/validation/format.adoc[]
*** xref:core/validation/format-configuring-formatting-globaldatetimeformat.adoc[]
*** xref:core/validation/beanvalidation.adoc[]
** xref:core/expressions.adoc[]
*** xref:core/expressions/evaluation.adoc[]
*** xref:core/expressions/beandef.adoc[]
*** xref:core/expressions/language-ref.adoc[]
**** xref:core/expressions/language-ref/literal.adoc[]
**** xref:core/expressions/language-ref/properties-arrays.adoc[]
**** xref:core/expressions/language-ref/inline-lists.adoc[]
**** xref:core/expressions/language-ref/inline-maps.adoc[]
**** xref:core/expressions/language-ref/array-construction.adoc[]
**** xref:core/expressions/language-ref/methods.adoc[]
**** xref:core/expressions/language-ref/operators.adoc[]
**** xref:core/expressions/language-ref/types.adoc[]
**** xref:core/expressions/language-ref/constructors.adoc[]
**** xref:core/expressions/language-ref/variables.adoc[]
**** xref:core/expressions/language-ref/functions.adoc[]
**** xref:core/expressions/language-ref/bean-references.adoc[]
**** xref:core/expressions/language-ref/operator-ternary.adoc[]
**** xref:core/expressions/language-ref/operator-elvis.adoc[]
**** xref:core/expressions/language-ref/operator-safe-navigation.adoc[]
**** xref:core/expressions/language-ref/collection-selection.adoc[]
**** xref:core/expressions/language-ref/collection-projection.adoc[]
**** xref:core/expressions/language-ref/templating.adoc[]
*** xref:core/expressions/example-classes.adoc[]
** xref:core/aop.adoc[]
*** xref:core/aop/introduction-defn.adoc[]
*** xref:core/aop/introduction-spring-defn.adoc[]
*** xref:core/aop/introduction-proxies.adoc[]
*** xref:core/aop/ataspectj.adoc[]
**** xref:core/aop/ataspectj/aspectj-support.adoc[]
**** xref:core/aop/ataspectj/at-aspectj.adoc[]
**** xref:core/aop/ataspectj/pointcuts.adoc[]
**** xref:core/aop/ataspectj/advice.adoc[]
**** xref:core/aop/ataspectj/introductions.adoc[]
**** xref:core/aop/ataspectj/instantiation-models.adoc[]
**** xref:core/aop/ataspectj/example.adoc[]
*** xref:core/aop/schema.adoc[]
*** xref:core/aop/choosing.adoc[]
*** xref:core/aop/mixing-styles.adoc[]
*** xref:core/aop/proxying.adoc[]
*** xref:core/aop/aspectj-programmatic.adoc[]
*** xref:core/aop/using-aspectj.adoc[]
*** xref:core/aop/resources.adoc[]
** xref:core/aop-api.adoc[]
*** xref:core/aop-api/pointcuts.adoc[]
*** xref:core/aop-api/advice.adoc[]
*** xref:core/aop-api/advisor.adoc[]
*** xref:core/aop-api/pfb.adoc[]
*** xref:core/aop-api/concise-proxy.adoc[]
*** xref:core/aop-api/prog.adoc[]
*** xref:core/aop-api/advised.adoc[]
*** xref:core/aop-api/autoproxy.adoc[]
*** xref:core/aop-api/targetsource.adoc[]
*** xref:core/aop-api/extensibility.adoc[]
** xref:core/null-safety.adoc[]
** xref:core/databuffer-codec.adoc[]
** xref:core/spring-jcl.adoc[]
** xref:core/aot.adoc[]
** xref:core/appendix.adoc[]
*** xref:core/appendix/xsd-schemas.adoc[]
*** xref:core/appendix/xml-custom.adoc[]
*** xref:core/appendix/application-startup-steps.adoc[]
* xref:testing.adoc[]
** xref:testing/introduction.adoc[]
** xref:testing/unit.adoc[]
** xref:testing/integration.adoc[]
** xref:testing/support-jdbc.adoc[]
** xref:testing/testcontext-framework.adoc[]
*** xref:testing/testcontext-framework/key-abstractions.adoc[]
*** xref:testing/testcontext-framework/bootstrapping.adoc[]
*** xref:testing/testcontext-framework/tel-config.adoc[]
*** xref:testing/testcontext-framework/application-events.adoc[]
*** xref:testing/testcontext-framework/test-execution-events.adoc[]
*** xref:testing/testcontext-framework/ctx-management.adoc[]
**** xref:testing/testcontext-framework/ctx-management/xml.adoc[]
**** xref:testing/testcontext-framework/ctx-management/groovy.adoc[]
**** xref:testing/testcontext-framework/ctx-management/javaconfig.adoc[]
**** xref:testing/testcontext-framework/ctx-management/mixed-config.adoc[]
**** xref:testing/testcontext-framework/ctx-management/initializers.adoc[]
**** xref:testing/testcontext-framework/ctx-management/inheritance.adoc[]
**** xref:testing/testcontext-framework/ctx-management/env-profiles.adoc[]
**** xref:testing/testcontext-framework/ctx-management/property-sources.adoc[]
**** xref:testing/testcontext-framework/ctx-management/dynamic-property-sources.adoc[]
**** xref:testing/testcontext-framework/ctx-management/web.adoc[]
**** xref:testing/testcontext-framework/ctx-management/web-mocks.adoc[]
**** xref:testing/testcontext-framework/ctx-management/caching.adoc[]
**** xref:testing/testcontext-framework/ctx-management/failure-threshold.adoc[]
**** xref:testing/testcontext-framework/ctx-management/hierarchies.adoc[]
*** xref:testing/testcontext-framework/fixture-di.adoc[]
*** xref:testing/testcontext-framework/web-scoped-beans.adoc[]
*** xref:testing/testcontext-framework/tx.adoc[]
*** xref:testing/testcontext-framework/executing-sql.adoc[]
*** xref:testing/testcontext-framework/parallel-test-execution.adoc[]
*** xref:testing/testcontext-framework/support-classes.adoc[]
*** xref:testing/testcontext-framework/aot.adoc[]
** xref:testing/webtestclient.adoc[]
** xref:testing/spring-mvc-test-framework.adoc[]
*** xref:testing/spring-mvc-test-framework/server.adoc[]
*** xref:testing/spring-mvc-test-framework/server-static-imports.adoc[]
*** xref:testing/spring-mvc-test-framework/server-setup-options.adoc[]
*** xref:testing/spring-mvc-test-framework/server-setup-steps.adoc[]
*** xref:testing/spring-mvc-test-framework/server-performing-requests.adoc[]
*** xref:testing/spring-mvc-test-framework/server-defining-expectations.adoc[]
*** xref:testing/spring-mvc-test-framework/async-requests.adoc[]
*** xref:testing/spring-mvc-test-framework/vs-streaming-response.adoc[]
*** xref:testing/spring-mvc-test-framework/server-filters.adoc[]
*** xref:testing/spring-mvc-test-framework/vs-end-to-end-integration-tests.adoc[]
*** xref:testing/spring-mvc-test-framework/server-resources.adoc[]
*** xref:testing/spring-mvc-test-framework/server-htmlunit.adoc[]
**** xref:testing/spring-mvc-test-framework/server-htmlunit/why.adoc[]
**** xref:testing/spring-mvc-test-framework/server-htmlunit/mah.adoc[]
**** xref:testing/spring-mvc-test-framework/server-htmlunit/webdriver.adoc[]
**** xref:testing/spring-mvc-test-framework/server-htmlunit/geb.adoc[]
** xref:testing/spring-mvc-test-client.adoc[]
** xref:testing/appendix.adoc[]
*** xref:testing/annotations.adoc[]
**** xref:testing/annotations/integration-standard.adoc[]
**** xref:testing/annotations/integration-spring.adoc[]
***** xref:testing/annotations/integration-spring/annotation-bootstrapwith.adoc[]
***** xref:testing/annotations/integration-spring/annotation-contextconfiguration.adoc[]
***** xref:testing/annotations/integration-spring/annotation-webappconfiguration.adoc[]
***** xref:testing/annotations/integration-spring/annotation-contexthierarchy.adoc[]
***** xref:testing/annotations/integration-spring/annotation-activeprofiles.adoc[]
***** xref:testing/annotations/integration-spring/annotation-testpropertysource.adoc[]
***** xref:testing/annotations/integration-spring/annotation-dynamicpropertysource.adoc[]
***** xref:testing/annotations/integration-spring/annotation-dirtiescontext.adoc[]
***** xref:testing/annotations/integration-spring/annotation-testexecutionlisteners.adoc[]
***** xref:testing/annotations/integration-spring/annotation-recordapplicationevents.adoc[]
***** xref:testing/annotations/integration-spring/annotation-commit.adoc[]
***** xref:testing/annotations/integration-spring/annotation-rollback.adoc[]
***** xref:testing/annotations/integration-spring/annotation-beforetransaction.adoc[]
***** xref:testing/annotations/integration-spring/annotation-aftertransaction.adoc[]
***** xref:testing/annotations/integration-spring/annotation-sql.adoc[]
***** xref:testing/annotations/integration-spring/annotation-sqlconfig.adoc[]
***** xref:testing/annotations/integration-spring/annotation-sqlmergemode.adoc[]
***** xref:testing/annotations/integration-spring/annotation-sqlgroup.adoc[]
**** xref:testing/annotations/integration-junit4.adoc[]
**** xref:testing/annotations/integration-junit-jupiter.adoc[]
**** xref:testing/annotations/integration-meta.adoc[]
*** xref:testing/resources.adoc[]
* xref:data-access.adoc[]
** xref:data-access/transaction.adoc[]
*** xref:data-access/transaction/motivation.adoc[]
*** xref:data-access/transaction/strategies.adoc[]
*** xref:data-access/transaction/tx-resource-synchronization.adoc[]
*** xref:data-access/transaction/declarative.adoc[]
**** xref:data-access/transaction/declarative/tx-decl-explained.adoc[]
**** xref:data-access/transaction/declarative/first-example.adoc[]
**** xref:data-access/transaction/declarative/rolling-back.adoc[]
**** xref:data-access/transaction/declarative/diff-tx.adoc[]
**** xref:data-access/transaction/declarative/txadvice-settings.adoc[]
**** xref:data-access/transaction/declarative/annotations.adoc[]
**** xref:data-access/transaction/declarative/tx-propagation.adoc[]
**** xref:data-access/transaction/declarative/applying-more-than-just-tx-advice.adoc[]
**** xref:data-access/transaction/declarative/aspectj.adoc[]
*** xref:data-access/transaction/programmatic.adoc[]
*** xref:data-access/transaction/tx-decl-vs-prog.adoc[]
*** xref:data-access/transaction/event.adoc[]
*** xref:data-access/transaction/application-server-integration.adoc[]
*** xref:data-access/transaction/solutions-to-common-problems.adoc[]
*** xref:data-access/transaction/resources.adoc[]
** xref:data-access/dao.adoc[]
** xref:data-access/jdbc.adoc[]
*** xref:data-access/jdbc/choose-style.adoc[]
*** xref:data-access/jdbc/packages.adoc[]
*** xref:data-access/jdbc/core.adoc[]
*** xref:data-access/jdbc/connections.adoc[]
*** xref:data-access/jdbc/advanced.adoc[]
*** xref:data-access/jdbc/simple.adoc[]
*** xref:data-access/jdbc/object.adoc[]
*** xref:data-access/jdbc/parameter-handling.adoc[]
*** xref:data-access/jdbc/embedded-database-support.adoc[]
*** xref:data-access/jdbc/initializing-datasource.adoc[]
** xref:data-access/r2dbc.adoc[]
** xref:data-access/orm.adoc[]
*** xref:data-access/orm/introduction.adoc[]
*** xref:data-access/orm/general.adoc[]
*** xref:data-access/orm/hibernate.adoc[]
*** xref:data-access/orm/jpa.adoc[]
** xref:data-access/oxm.adoc[]
** xref:data-access/appendix.adoc[]
* xref:web.adoc[]
** xref:web/webmvc.adoc[]
*** xref:web/webmvc/mvc-servlet.adoc[]
**** xref:web/webmvc/mvc-servlet/context-hierarchy.adoc[]
**** xref:web/webmvc/mvc-servlet/special-bean-types.adoc[]
**** xref:web/webmvc/mvc-servlet/config.adoc[]
**** xref:web/webmvc/mvc-servlet/container-config.adoc[]
**** xref:web/webmvc/mvc-servlet/sequence.adoc[]
**** xref:web/webmvc/mvc-servlet/handlermapping-path.adoc[]
**** xref:web/webmvc/mvc-servlet/handlermapping-interceptor.adoc[]
**** xref:web/webmvc/mvc-servlet/exceptionhandlers.adoc[]
**** xref:web/webmvc/mvc-servlet/viewresolver.adoc[]
**** xref:web/webmvc/mvc-servlet/localeresolver.adoc[]
**** xref:web/webmvc/mvc-servlet/themeresolver.adoc[]
**** xref:web/webmvc/mvc-servlet/multipart.adoc[]
**** xref:web/webmvc/mvc-servlet/logging.adoc[]
*** xref:web/webmvc/filters.adoc[]
*** xref:web/webmvc/mvc-controller.adoc[]
**** xref:web/webmvc/mvc-controller/ann.adoc[]
**** xref:web/webmvc/mvc-controller/ann-requestmapping.adoc[]
**** xref:web/webmvc/mvc-controller/ann-methods.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/arguments.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/return-types.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/typeconversion.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/matrix-variables.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/requestparam.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/requestheader.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/cookievalue.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/modelattrib-method-args.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/sessionattributes.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/sessionattribute.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/requestattrib.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/redirecting-passing-data.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/flash-attributes.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/multipart-forms.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/requestbody.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/httpentity.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/responsebody.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/responseentity.adoc[]
***** xref:web/webmvc/mvc-controller/ann-methods/jackson.adoc[]
**** xref:web/webmvc/mvc-controller/ann-modelattrib-methods.adoc[]
**** xref:web/webmvc/mvc-controller/ann-initbinder.adoc[]
**** xref:web/webmvc/mvc-controller/ann-validation.adoc[]
**** xref:web/webmvc/mvc-controller/ann-exceptionhandler.adoc[]
**** xref:web/webmvc/mvc-controller/ann-advice.adoc[]
*** xref:web/webmvc-functional.adoc[]
*** xref:web/webmvc/mvc-uri-building.adoc[]
*** xref:web/webmvc/mvc-ann-async.adoc[]
*** xref:web/webmvc-cors.adoc[]
*** xref:web/webmvc/mvc-ann-rest-exceptions.adoc[]
*** xref:web/webmvc/mvc-security.adoc[]
*** xref:web/webmvc/mvc-caching.adoc[]
*** xref:web/webmvc-view.adoc[]
**** xref:web/webmvc-view/mvc-thymeleaf.adoc[]
**** xref:web/webmvc-view/mvc-freemarker.adoc[]
**** xref:web/webmvc-view/mvc-groovymarkup.adoc[]
**** xref:web/webmvc-view/mvc-script.adoc[]
**** xref:web/webmvc-view/mvc-jsp.adoc[]
**** xref:web/webmvc-view/mvc-feeds.adoc[]
**** xref:web/webmvc-view/mvc-document.adoc[]
**** xref:web/webmvc-view/mvc-jackson.adoc[]
**** xref:web/webmvc-view/mvc-xml-marshalling.adoc[]
**** xref:web/webmvc-view/mvc-xslt.adoc[]
*** xref:web/webmvc/mvc-config.adoc[]
**** xref:web/webmvc/mvc-config/enable.adoc[]
**** xref:web/webmvc/mvc-config/customize.adoc[]
**** xref:web/webmvc/mvc-config/conversion.adoc[]
**** xref:web/webmvc/mvc-config/validation.adoc[]
**** xref:web/webmvc/mvc-config/interceptors.adoc[]
**** xref:web/webmvc/mvc-config/content-negotiation.adoc[]
**** xref:web/webmvc/mvc-config/message-converters.adoc[]
**** xref:web/webmvc/mvc-config/view-controller.adoc[]
**** xref:web/webmvc/mvc-config/view-resolvers.adoc[]
**** xref:web/webmvc/mvc-config/static-resources.adoc[]
**** xref:web/webmvc/mvc-config/default-servlet-handler.adoc[]
**** xref:web/webmvc/mvc-config/path-matching.adoc[]
**** xref:web/webmvc/mvc-config/advanced-java.adoc[]
**** xref:web/webmvc/mvc-config/advanced-xml.adoc[]
*** xref:web/webmvc/mvc-http2.adoc[]
** xref:web/webmvc-client.adoc[]
** xref:web/webmvc-test.adoc[]
** xref:web/websocket.adoc[]
*** xref:web/websocket/server.adoc[]
*** xref:web/websocket/fallback.adoc[]
*** xref:web/websocket/stomp.adoc[]
**** xref:web/websocket/stomp/overview.adoc[]
**** xref:web/websocket/stomp/benefits.adoc[]
**** xref:web/websocket/stomp/enable.adoc[]
**** xref:web/websocket/stomp/server-config.adoc[]
**** xref:web/websocket/stomp/message-flow.adoc[]
**** xref:web/websocket/stomp/handle-annotations.adoc[]
**** xref:web/websocket/stomp/handle-send.adoc[]
**** xref:web/websocket/stomp/handle-simple-broker.adoc[]
**** xref:web/websocket/stomp/handle-broker-relay.adoc[]
**** xref:web/websocket/stomp/handle-broker-relay-configure.adoc[]
**** xref:web/websocket/stomp/destination-separator.adoc[]
**** xref:web/websocket/stomp/authentication.adoc[]
**** xref:web/websocket/stomp/authentication-token-based.adoc[]
**** xref:web/websocket/stomp/authorization.adoc[]
**** xref:web/websocket/stomp/user-destination.adoc[]
**** xref:web/websocket/stomp/ordered-messages.adoc[]
**** xref:web/websocket/stomp/application-context-events.adoc[]
**** xref:web/websocket/stomp/interceptors.adoc[]
**** xref:web/websocket/stomp/client.adoc[]
**** xref:web/websocket/stomp/scope.adoc[]
**** xref:web/websocket/stomp/configuration-performance.adoc[]
**** xref:web/websocket/stomp/stats.adoc[]
**** xref:web/websocket/stomp/testing.adoc[]
** xref:web/integration.adoc[]
* xref:web-reactive.adoc[]
** xref:web/webflux.adoc[]
*** xref:web/webflux/new-framework.adoc[]
*** xref:web/webflux/reactive-spring.adoc[]
*** xref:web/webflux/dispatcher-handler.adoc[]
*** xref:web/webflux/controller.adoc[]
**** xref:web/webflux/controller/ann.adoc[]
**** xref:web/webflux/controller/ann-requestmapping.adoc[]
**** xref:web/webflux/controller/ann-methods.adoc[]
***** xref:web/webflux/controller/ann-methods/arguments.adoc[]
***** xref:web/webflux/controller/ann-methods/return-types.adoc[]
***** xref:web/webflux/controller/ann-methods/typeconversion.adoc[]
***** xref:web/webflux/controller/ann-methods/matrix-variables.adoc[]
***** xref:web/webflux/controller/ann-methods/requestparam.adoc[]
***** xref:web/webflux/controller/ann-methods/requestheader.adoc[]
***** xref:web/webflux/controller/ann-methods/cookievalue.adoc[]
***** xref:web/webflux/controller/ann-methods/modelattrib-method-args.adoc[]
***** xref:web/webflux/controller/ann-methods/sessionattributes.adoc[]
***** xref:web/webflux/controller/ann-methods/sessionattribute.adoc[]
***** xref:web/webflux/controller/ann-methods/requestattrib.adoc[]
***** xref:web/webflux/controller/ann-methods/multipart-forms.adoc[]
***** xref:web/webflux/controller/ann-methods/requestbody.adoc[]
***** xref:web/webflux/controller/ann-methods/httpentity.adoc[]
***** xref:web/webflux/controller/ann-methods/responsebody.adoc[]
***** xref:web/webflux/controller/ann-methods/responseentity.adoc[]
***** xref:web/webflux/controller/ann-methods/jackson.adoc[]
**** xref:web/webflux/controller/ann-modelattrib-methods.adoc[]
**** xref:web/webflux/controller/ann-initbinder.adoc[]
**** xref:web/webflux/controller/ann-validation.adoc[]
**** xref:web/webflux/controller/ann-exceptions.adoc[]
**** xref:web/webflux/controller/ann-advice.adoc[]
*** xref:web/webflux-functional.adoc[]
*** xref:web/webflux/uri-building.adoc[]
*** xref:web/webflux-cors.adoc[]
*** xref:web/webflux/ann-rest-exceptions.adoc[]
*** xref:web/webflux/security.adoc[]
*** xref:web/webflux/caching.adoc[]
*** xref:web/webflux-view.adoc[]
*** xref:web/webflux/config.adoc[]
*** xref:web/webflux/http2.adoc[]
** xref:web/webflux-webclient.adoc[]
*** xref:web/webflux-webclient/client-builder.adoc[]
*** xref:web/webflux-webclient/client-retrieve.adoc[]
*** xref:web/webflux-webclient/client-exchange.adoc[]
*** xref:web/webflux-webclient/client-body.adoc[]
*** xref:web/webflux-webclient/client-filter.adoc[]
*** xref:web/webflux-webclient/client-attributes.adoc[]
*** xref:web/webflux-webclient/client-context.adoc[]
*** xref:web/webflux-webclient/client-synchronous.adoc[]
*** xref:web/webflux-webclient/client-testing.adoc[]
** xref:web/webflux-http-interface-client.adoc[]
** xref:web/webflux-websocket.adoc[]
** xref:web/webflux-test.adoc[]
** xref:rsocket.adoc[]
** xref:web/webflux-reactive-libraries.adoc[]
* xref:integration.adoc[]
** xref:integration/rest-clients.adoc[]
** xref:integration/jms.adoc[]
*** xref:integration/jms/using.adoc[]
*** xref:integration/jms/sending.adoc[]
*** xref:integration/jms/receiving.adoc[]
*** xref:integration/jms/jca-message-endpoint-manager.adoc[]
*** xref:integration/jms/annotated.adoc[]
*** xref:integration/jms/namespace.adoc[]
** xref:integration/jmx.adoc[]
*** xref:integration/jmx/exporting.adoc[]
*** xref:integration/jmx/interface.adoc[]
*** xref:integration/jmx/naming.adoc[]
*** xref:integration/jmx/jsr160.adoc[]
*** xref:integration/jmx/proxy.adoc[]
*** xref:integration/jmx/notifications.adoc[]
*** xref:integration/jmx/resources.adoc[]
** xref:integration/email.adoc[]
** xref:integration/scheduling.adoc[]
** xref:integration/cache.adoc[]
*** xref:integration/cache/strategies.adoc[]
*** xref:integration/cache/annotations.adoc[]
*** xref:integration/cache/jsr-107.adoc[]
*** xref:integration/cache/declarative-xml.adoc[]
*** xref:integration/cache/store-configuration.adoc[]
*** xref:integration/cache/plug.adoc[]
*** xref:integration/cache/specific-config.adoc[]
** xref:integration/observability.adoc[]
** xref:integration/checkpoint-restore.adoc[]
** xref:integration/appendix.adoc[]
* xref:languages.adoc[]
** xref:languages/kotlin.adoc[]
*** xref:languages/kotlin/requirements.adoc[]
*** xref:languages/kotlin/extensions.adoc[]
*** xref:languages/kotlin/null-safety.adoc[]
*** xref:languages/kotlin/classes-interfaces.adoc[]
*** xref:languages/kotlin/annotations.adoc[]
*** xref:languages/kotlin/bean-definition-dsl.adoc[]
*** xref:languages/kotlin/web.adoc[]
*** xref:languages/kotlin/coroutines.adoc[]
*** xref:languages/kotlin/spring-projects-in.adoc[]
*** xref:languages/kotlin/getting-started.adoc[]
*** xref:languages/kotlin/resources.adoc[]
** xref:languages/groovy.adoc[]
** xref:languages/dynamic.adoc[]
* xref:appendix.adoc[]
* https://github.com/spring-projects/spring-framework/wiki[Wiki]
@@ -1,9 +1,5 @@
[[appendix]]
= Appendix
:toc: left
:toclevels: 4
:tabsize: 4
:docinfo1:
This part of the reference documentation covers topics that apply to multiple modules
within the core Spring Framework.
@@ -29,12 +25,12 @@ The following table lists all currently supported Spring properties.
| `spring.beaninfo.ignore`
| Instructs Spring to use the `Introspector.IGNORE_ALL_BEANINFO` mode when calling the
JavaBeans `Introspector`. See
{api-spring-framework}++/beans/CachedIntrospectionResults.html#IGNORE_BEANINFO_PROPERTY_NAME++[`CachedIntrospectionResults`]
{api-spring-framework}++/beans/StandardBeanInfoFactory.html#IGNORE_BEANINFO_PROPERTY_NAME++[`CachedIntrospectionResults`]
for details.
| `spring.expression.compiler.mode`
| The mode to use when compiling expressions for the
<<core.adoc#expressions-compiler-configuration, Spring Expression Language>>.
xref:core/expressions/evaluation.adoc#expressions-compiler-configuration[Spring Expression Language].
| `spring.getenv.ignore`
| Instructs Spring to ignore operating system environment variables if a Spring
@@ -43,14 +39,9 @@ resolvable otherwise. See
{api-spring-framework}++/core/env/AbstractEnvironment.html#IGNORE_GETENV_PROPERTY_NAME++[`AbstractEnvironment`]
for details.
| `spring.index.ignore`
| Instructs Spring to ignore the components index located in
`META-INF/spring.components`. See <<core.adoc#beans-scanning-index, Generating an Index
of Candidate Components>>.
| `spring.jdbc.getParameterType.ignore`
| Instructs Spring to ignore `java.sql.ParameterMetaData.getParameterType` completely.
See the note in <<data-access.adoc#jdbc-batch-list, Batch Operations with a List of Objects>>.
See the note in xref:data-access/jdbc/advanced.adoc#jdbc-batch-list[Batch Operations with a List of Objects].
| `spring.jndi.ignore`
| Instructs Spring to ignore a default JNDI environment, as an optimization for scenarios
@@ -64,19 +55,27 @@ for details.
{api-spring-framework}++/objenesis/SpringObjenesis.html#IGNORE_OBJENESIS_PROPERTY_NAME++[`SpringObjenesis`]
for details.
| `spring.test.aot.processing.failOnError`
| A boolean flag that controls whether errors encountered during AOT processing in the
_Spring TestContext Framework_ should result in an exception that fails the overall process.
See xref:testing/testcontext-framework/aot.adoc[Ahead of Time Support for Tests].
| `spring.test.constructor.autowire.mode`
| The default _test constructor autowire mode_ to use if `@TestConstructor` is not present
on a test class. See <<testing.adoc#integration-testing-annotations-testconstructor,
Changing the default test constructor autowire mode>>.
on a test class. See xref:testing/annotations/integration-junit-jupiter.adoc#integration-testing-annotations-testconstructor[Changing the default test constructor autowire mode].
| `spring.test.context.cache.maxSize`
| The maximum size of the context cache in the _Spring TestContext Framework_. See
<<testing.adoc#testcontext-ctx-management-caching, Context Caching>>.
xref:testing/testcontext-framework/ctx-management/caching.adoc[Context Caching].
| `spring.test.context.failure.threshold`
| The failure threshold for errors encountered while attempting to load an `ApplicationContext`
in the _Spring TestContext Framework_. See
xref:testing/testcontext-framework/ctx-management/failure-threshold.adoc[Context Failure Threshold].
| `spring.test.enclosing.configuration`
| The default _enclosing configuration inheritance mode_ to use if
`@NestedTestConfiguration` is not present on a test class. See
<<testing.adoc#integration-testing-annotations-nestedtestconfiguration, Changing the
default enclosing configuration inheritance mode>>.
xref:testing/annotations/integration-junit-jupiter.adoc#integration-testing-annotations-nestedtestconfiguration[Changing the default enclosing configuration inheritance mode].
|===
@@ -0,0 +1,20 @@
// Spring Portfolio
:docs-site: https://docs.spring.io
:docs-spring-boot: {docs-site}/spring-boot/docs/current/reference
:docs-spring-gemfire: {docs-site}/spring-gemfire/docs/current/reference
:docs-spring-security: {docs-site}/spring-security/reference
// spring-asciidoctor-backends Settings
:chomp: default headers packages
:fold: all
// Spring Framework
:docs-spring-framework: {docs-site}/spring-framework/docs/{spring-version}
:api-spring-framework: {docs-spring-framework}/javadoc-api/org/springframework
:docs-java: {docdir}/../../main/java/org/springframework/docs
:docs-kotlin: {docdir}/../../main/kotlin/org/springframework/docs
:docs-resources: {docdir}/../../main/resources
:spring-framework-main-code: https://github.com/spring-projects/spring-framework/tree/main
// Third-party Links
:docs-graalvm: https://www.graalvm.org/22.3/reference-manual
:gh-rsocket: https://github.com/rsocket
:gh-rsocket-extensions: {gh-rsocket}/rsocket/blob/master/Extensions
:gh-rsocket-java: {gh-rsocket}/rsocket-java
@@ -1,9 +1,5 @@
[[spring-core]]
= Core Technologies
:toc: left
:toclevels: 4
:tabsize: 4
:docinfo1:
This part of the reference documentation covers all the technologies that are
absolutely integral to the Spring Framework.
@@ -19,22 +15,16 @@ Coverage of Spring's integration with AspectJ (currently the richest -- in terms
features -- and certainly most mature AOP implementation in the Java enterprise space)
is also provided.
include::core/core-beans.adoc[leveloffset=+1]
AOT processing can be used to optimize your application ahead-of-time. It is typically
used for native image deployment using GraalVM.
include::core/core-resources.adoc[leveloffset=+1]
include::core/core-validation.adoc[leveloffset=+1]
include::core/core-expressions.adoc[leveloffset=+1]
include::core/core-aop.adoc[leveloffset=+1]
include::core/core-aop-api.adoc[leveloffset=+1]
include::core/core-null-safety.adoc[leveloffset=+1]
include::core/core-databuffer-codec.adoc[leveloffset=+1]
include::core/core-spring-jcl.adoc[leveloffset=+1]
include::core/core-appendix.adoc[leveloffset=+1]
@@ -0,0 +1,12 @@
[[aop-api]]
= Spring AOP APIs
:page-section-summary-toc: 1
The previous chapter described the Spring's support for AOP with @AspectJ and schema-based
aspect definitions. In this chapter, we discuss the lower-level Spring AOP APIs. For common
applications, we recommend the use of Spring AOP with AspectJ pointcuts as described in the
previous chapter.
@@ -0,0 +1,592 @@
[[aop-api-advice]]
= Advice API in Spring
Now we can examine how Spring AOP handles advice.
[[aop-api-advice-lifecycle]]
== Advice Lifecycles
Each advice is a Spring bean. An advice instance can be shared across all advised
objects or be unique to each advised object. This corresponds to per-class or
per-instance advice.
Per-class advice is used most often. It is appropriate for generic advice, such as
transaction advisors. These do not depend on the state of the proxied object or add new
state. They merely act on the method and arguments.
Per-instance advice is appropriate for introductions, to support mixins. In this case,
the advice adds state to the proxied object.
You can use a mix of shared and per-instance advice in the same AOP proxy.
[[aop-api-advice-types]]
== Advice Types in Spring
Spring provides several advice types and is extensible to support
arbitrary advice types. This section describes the basic concepts and standard advice types.
[[aop-api-advice-around]]
=== Interception Around Advice
The most fundamental advice type in Spring is interception around advice.
Spring is compliant with the AOP `Alliance` interface for around advice that uses method
interception. Classes that implement `MethodInterceptor` and that implement around advice should also implement the
following interface:
[source,java,indent=0,subs="verbatim,quotes"]
----
public interface MethodInterceptor extends Interceptor {
Object invoke(MethodInvocation invocation) throws Throwable;
}
----
The `MethodInvocation` argument to the `invoke()` method exposes the method being
invoked, the target join point, the AOP proxy, and the arguments to the method. The
`invoke()` method should return the invocation's result: the return value of the join
point.
The following example shows a simple `MethodInterceptor` implementation:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class DebugInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Before: invocation=[" + invocation + "]");
Object rval = invocation.proceed();
System.out.println("Invocation returned");
return rval;
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class DebugInterceptor : MethodInterceptor {
override fun invoke(invocation: MethodInvocation): Any {
println("Before: invocation=[$invocation]")
val rval = invocation.proceed()
println("Invocation returned")
return rval
}
}
----
======
Note the call to the `proceed()` method of `MethodInvocation`. This proceeds down the
interceptor chain towards the join point. Most interceptors invoke this method and
return its return value. However, a `MethodInterceptor`, like any around advice, can
return a different value or throw an exception rather than invoke the proceed method.
However, you do not want to do this without good reason.
NOTE: `MethodInterceptor` implementations offer interoperability with other AOP Alliance-compliant AOP
implementations. The other advice types discussed in the remainder of this section
implement common AOP concepts but in a Spring-specific way. While there is an advantage
in using the most specific advice type, stick with `MethodInterceptor` around advice if
you are likely to want to run the aspect in another AOP framework. Note that pointcuts
are not currently interoperable between frameworks, and the AOP Alliance does not
currently define pointcut interfaces.
[[aop-api-advice-before]]
=== Before Advice
A simpler advice type is a before advice. This does not need a `MethodInvocation`
object, since it is called only before entering the method.
The main advantage of a before advice is that there is no need to invoke the `proceed()`
method and, therefore, no possibility of inadvertently failing to proceed down the
interceptor chain.
The following listing shows the `MethodBeforeAdvice` interface:
[source,java,indent=0,subs="verbatim,quotes"]
----
public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method m, Object[] args, Object target) throws Throwable;
}
----
(Spring's API design would allow for
field before advice, although the usual objects apply to field interception and it is
unlikely for Spring to ever implement it.)
Note that the return type is `void`. Before advice can insert custom behavior before the join
point runs but cannot change the return value. If a before advice throws an
exception, it stops further execution of the interceptor chain. The exception
propagates back up the interceptor chain. If it is unchecked or on the signature of
the invoked method, it is passed directly to the client. Otherwise, it is
wrapped in an unchecked exception by the AOP proxy.
The following example shows a before advice in Spring, which counts all method invocations:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class CountingBeforeAdvice implements MethodBeforeAdvice {
private int count;
public void before(Method m, Object[] args, Object target) throws Throwable {
++count;
}
public int getCount() {
return count;
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class CountingBeforeAdvice : MethodBeforeAdvice {
var count: Int = 0
override fun before(m: Method, args: Array<Any>, target: Any?) {
++count
}
}
----
======
TIP: Before advice can be used with any pointcut.
[[aop-api-advice-throws]]
=== Throws Advice
Throws advice is invoked after the return of the join point if the join point threw
an exception. Spring offers typed throws advice. Note that this means that the
`org.springframework.aop.ThrowsAdvice` interface does not contain any methods. It is a
tag interface identifying that the given object implements one or more typed throws
advice methods. These should be in the following form:
[source,java,indent=0,subs="verbatim,quotes"]
----
afterThrowing([Method, args, target], subclassOfThrowable)
----
Only the last argument is required. The method signatures may have either one or four
arguments, depending on whether the advice method is interested in the method and
arguments. The next two listing show classes that are examples of throws advice.
The following advice is invoked if a `RemoteException` is thrown (including from subclasses):
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class RemoteThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(RemoteException ex) throws Throwable {
// Do something with remote exception
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class RemoteThrowsAdvice : ThrowsAdvice {
fun afterThrowing(ex: RemoteException) {
// Do something with remote exception
}
}
----
======
Unlike the preceding
advice, the next example declares four arguments, so that it has access to the invoked method, method
arguments, and target object. The following advice is invoked if a `ServletException` is thrown:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class ServletThrowsAdviceWithArguments implements ThrowsAdvice {
public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
// Do something with all arguments
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class ServletThrowsAdviceWithArguments : ThrowsAdvice {
fun afterThrowing(m: Method, args: Array<Any>, target: Any, ex: ServletException) {
// Do something with all arguments
}
}
----
======
The final example illustrates how these two methods could be used in a single class
that handles both `RemoteException` and `ServletException`. Any number of throws advice
methods can be combined in a single class. The following listing shows the final example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public static class CombinedThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(RemoteException ex) throws Throwable {
// Do something with remote exception
}
public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
// Do something with all arguments
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class CombinedThrowsAdvice : ThrowsAdvice {
fun afterThrowing(ex: RemoteException) {
// Do something with remote exception
}
fun afterThrowing(m: Method, args: Array<Any>, target: Any, ex: ServletException) {
// Do something with all arguments
}
}
----
======
NOTE: If a throws-advice method throws an exception itself, it overrides the
original exception (that is, it changes the exception thrown to the user). The overriding
exception is typically a RuntimeException, which is compatible with any method
signature. However, if a throws-advice method throws a checked exception, it must
match the declared exceptions of the target method and is, hence, to some degree
coupled to specific target method signatures. _Do not throw an undeclared checked
exception that is incompatible with the target method's signature!_
TIP: Throws advice can be used with any pointcut.
[[aop-api-advice-after-returning]]
=== After Returning Advice
An after returning advice in Spring must implement the
`org.springframework.aop.AfterReturningAdvice` interface, which the following listing shows:
[source,java,indent=0,subs="verbatim,quotes"]
----
public interface AfterReturningAdvice extends Advice {
void afterReturning(Object returnValue, Method m, Object[] args, Object target)
throws Throwable;
}
----
An after returning advice has access to the return value (which it cannot modify),
the invoked method, the method's arguments, and the target.
The following after returning advice counts all successful method invocations that have
not thrown exceptions:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class CountingAfterReturningAdvice implements AfterReturningAdvice {
private int count;
public void afterReturning(Object returnValue, Method m, Object[] args, Object target)
throws Throwable {
++count;
}
public int getCount() {
return count;
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class CountingAfterReturningAdvice : AfterReturningAdvice {
var count: Int = 0
private set
override fun afterReturning(returnValue: Any?, m: Method, args: Array<Any>, target: Any?) {
++count
}
}
----
======
This advice does not change the execution path. If it throws an exception, it is
thrown up the interceptor chain instead of the return value.
TIP: After returning advice can be used with any pointcut.
[[aop-api-advice-introduction]]
=== Introduction Advice
Spring treats introduction advice as a special kind of interception advice.
Introduction requires an `IntroductionAdvisor` and an `IntroductionInterceptor` that
implement the following interface:
[source,java,indent=0,subs="verbatim,quotes"]
----
public interface IntroductionInterceptor extends MethodInterceptor {
boolean implementsInterface(Class intf);
}
----
The `invoke()` method inherited from the AOP Alliance `MethodInterceptor` interface must
implement the introduction. That is, if the invoked method is on an introduced
interface, the introduction interceptor is responsible for handling the method call -- it
cannot invoke `proceed()`.
Introduction advice cannot be used with any pointcut, as it applies only at the class,
rather than the method, level. You can only use introduction advice with the
`IntroductionAdvisor`, which has the following methods:
[source,java,indent=0,subs="verbatim,quotes"]
----
public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
ClassFilter getClassFilter();
void validateInterfaces() throws IllegalArgumentException;
}
public interface IntroductionInfo {
Class<?>[] getInterfaces();
}
----
There is no `MethodMatcher` and, hence, no `Pointcut` associated with introduction
advice. Only class filtering is logical.
The `getInterfaces()` method returns the interfaces introduced by this advisor.
The `validateInterfaces()` method is used internally to see whether or not the
introduced interfaces can be implemented by the configured `IntroductionInterceptor`.
Consider an example from the Spring test suite and suppose we want to
introduce the following interface to one or more objects:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public interface Lockable {
void lock();
void unlock();
boolean locked();
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
interface Lockable {
fun lock()
fun unlock()
fun locked(): Boolean
}
----
======
This illustrates a mixin. We want to be able to cast advised objects to `Lockable`,
whatever their type and call lock and unlock methods. If we call the `lock()` method, we
want all setter methods to throw a `LockedException`. Thus, we can add an aspect that
provides the ability to make objects immutable without them having any knowledge of it:
a good example of AOP.
First, we need an `IntroductionInterceptor` that does the heavy lifting. In this
case, we extend the `org.springframework.aop.support.DelegatingIntroductionInterceptor`
convenience class. We could implement `IntroductionInterceptor` directly, but using
`DelegatingIntroductionInterceptor` is best for most cases.
The `DelegatingIntroductionInterceptor` is designed to delegate an introduction to an
actual implementation of the introduced interfaces, concealing the use of interception
to do so. You can set the delegate to any object using a constructor argument. The
default delegate (when the no-argument constructor is used) is `this`. Thus, in the next example,
the delegate is the `LockMixin` subclass of `DelegatingIntroductionInterceptor`.
Given a delegate (by default, itself), a `DelegatingIntroductionInterceptor` instance
looks for all interfaces implemented by the delegate (other than
`IntroductionInterceptor`) and supports introductions against any of them.
Subclasses such as `LockMixin` can call the `suppressInterface(Class intf)`
method to suppress interfaces that should not be exposed. However, no matter how many
interfaces an `IntroductionInterceptor` is prepared to support, the
`IntroductionAdvisor` used controls which interfaces are actually exposed. An
introduced interface conceals any implementation of the same interface by the target.
Thus, `LockMixin` extends `DelegatingIntroductionInterceptor` and implements `Lockable`
itself. The superclass automatically picks up that `Lockable` can be supported for
introduction, so we do not need to specify that. We could introduce any number of
interfaces in this way.
Note the use of the `locked` instance variable. This effectively adds additional state
to that held in the target object.
The following example shows the example `LockMixin` class:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class LockMixin extends DelegatingIntroductionInterceptor implements Lockable {
private boolean locked;
public void lock() {
this.locked = true;
}
public void unlock() {
this.locked = false;
}
public boolean locked() {
return this.locked;
}
public Object invoke(MethodInvocation invocation) throws Throwable {
if (locked() && invocation.getMethod().getName().indexOf("set") == 0) {
throw new LockedException();
}
return super.invoke(invocation);
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class LockMixin : DelegatingIntroductionInterceptor(), Lockable {
private var locked: Boolean = false
fun lock() {
this.locked = true
}
fun unlock() {
this.locked = false
}
fun locked(): Boolean {
return this.locked
}
override fun invoke(invocation: MethodInvocation): Any? {
if (locked() && invocation.method.name.indexOf("set") == 0) {
throw LockedException()
}
return super.invoke(invocation)
}
}
----
======
Often, you need not override the `invoke()` method. The
`DelegatingIntroductionInterceptor` implementation (which calls the `delegate` method if
the method is introduced, otherwise proceeds towards the join point) usually
suffices. In the present case, we need to add a check: no setter method can be invoked
if in locked mode.
The required introduction only needs to hold a distinct
`LockMixin` instance and specify the introduced interfaces (in this case, only
`Lockable`). A more complex example might take a reference to the introduction
interceptor (which would be defined as a prototype). In this case, there is no
configuration relevant for a `LockMixin`, so we create it by using `new`.
The following example shows our `LockMixinAdvisor` class:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class LockMixinAdvisor extends DefaultIntroductionAdvisor {
public LockMixinAdvisor() {
super(new LockMixin(), Lockable.class);
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class LockMixinAdvisor : DefaultIntroductionAdvisor(LockMixin(), Lockable::class.java)
----
======
We can apply this advisor very simply, because it requires no configuration. (However, it
is impossible to use an `IntroductionInterceptor` without an
`IntroductionAdvisor`.) As usual with introductions, the advisor must be per-instance,
as it is stateful. We need a different instance of `LockMixinAdvisor`, and hence
`LockMixin`, for each advised object. The advisor comprises part of the advised object's
state.
We can apply this advisor programmatically by using the `Advised.addAdvisor()` method or
(the recommended way) in XML configuration, as any other advisor. All proxy creation
choices discussed below, including "`auto proxy creators,`" correctly handle introductions
and stateful mixins.
@@ -0,0 +1,148 @@
[[aop-api-advised]]
= Manipulating Advised Objects
However you create AOP proxies, you can manipulate them BY using the
`org.springframework.aop.framework.Advised` interface. Any AOP proxy can be cast to this
interface, no matter which other interfaces it implements. This interface includes the
following methods:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
Advisor[] getAdvisors();
void addAdvice(Advice advice) throws AopConfigException;
void addAdvice(int pos, Advice advice) throws AopConfigException;
void addAdvisor(Advisor advisor) throws AopConfigException;
void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
int indexOf(Advisor advisor);
boolean removeAdvisor(Advisor advisor) throws AopConfigException;
void removeAdvisor(int index) throws AopConfigException;
boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
boolean isFrozen();
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
fun getAdvisors(): Array<Advisor>
@Throws(AopConfigException::class)
fun addAdvice(advice: Advice)
@Throws(AopConfigException::class)
fun addAdvice(pos: Int, advice: Advice)
@Throws(AopConfigException::class)
fun addAdvisor(advisor: Advisor)
@Throws(AopConfigException::class)
fun addAdvisor(pos: Int, advisor: Advisor)
fun indexOf(advisor: Advisor): Int
@Throws(AopConfigException::class)
fun removeAdvisor(advisor: Advisor): Boolean
@Throws(AopConfigException::class)
fun removeAdvisor(index: Int)
@Throws(AopConfigException::class)
fun replaceAdvisor(a: Advisor, b: Advisor): Boolean
fun isFrozen(): Boolean
----
======
The `getAdvisors()` method returns an `Advisor` for every advisor, interceptor, or
other advice type that has been added to the factory. If you added an `Advisor`, the
returned advisor at this index is the object that you added. If you added an
interceptor or other advice type, Spring wrapped this in an advisor with a
pointcut that always returns `true`. Thus, if you added a `MethodInterceptor`, the advisor
returned for this index is a `DefaultPointcutAdvisor` that returns your
`MethodInterceptor` and a pointcut that matches all classes and methods.
The `addAdvisor()` methods can be used to add any `Advisor`. Usually, the advisor holding
pointcut and advice is the generic `DefaultPointcutAdvisor`, which you can use with
any advice or pointcut (but not for introductions).
By default, it is possible to add or remove advisors or interceptors even once a proxy
has been created. The only restriction is that it is impossible to add or remove an
introduction advisor, as existing proxies from the factory do not show the interface
change. (You can obtain a new proxy from the factory to avoid this problem.)
The following example shows casting an AOP proxy to the `Advised` interface and examining and
manipulating its advice:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
Advised advised = (Advised) myObject;
Advisor[] advisors = advised.getAdvisors();
int oldAdvisorCount = advisors.length;
System.out.println(oldAdvisorCount + " advisors");
// Add an advice like an interceptor without a pointcut
// Will match all proxied methods
// Can use for interceptors, before, after returning or throws advice
advised.addAdvice(new DebugInterceptor());
// Add selective advice using a pointcut
advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice));
assertEquals("Added two advisors", oldAdvisorCount + 2, advised.getAdvisors().length);
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
val advised = myObject as Advised
val advisors = advised.advisors
val oldAdvisorCount = advisors.size
println("$oldAdvisorCount advisors")
// Add an advice like an interceptor without a pointcut
// Will match all proxied methods
// Can use for interceptors, before, after returning or throws advice
advised.addAdvice(DebugInterceptor())
// Add selective advice using a pointcut
advised.addAdvisor(DefaultPointcutAdvisor(mySpecialPointcut, myAdvice))
assertEquals("Added two advisors", oldAdvisorCount + 2, advised.advisors.size)
----
======
NOTE: It is questionable whether it is advisable (no pun intended) to modify advice on a
business object in production, although there are, no doubt, legitimate usage cases.
However, it can be very useful in development (for example, in tests). We have sometimes
found it very useful to be able to add test code in the form of an interceptor or other
advice, getting inside a method invocation that we want to test. (For example, the advice can
get inside a transaction created for that method, perhaps to run SQL to check that
a database was correctly updated, before marking the transaction for roll back.)
Depending on how you created the proxy, you can usually set a `frozen` flag. In that
case, the `Advised` `isFrozen()` method returns `true`, and any attempts to modify
advice through addition or removal results in an `AopConfigException`. The ability
to freeze the state of an advised object is useful in some cases (for example, to
prevent calling code removing a security interceptor).
@@ -0,0 +1,20 @@
[[aop-api-advisor]]
= The Advisor API in Spring
:page-section-summary-toc: 1
In Spring, an Advisor is an aspect that contains only a single advice object associated
with a pointcut expression.
Apart from the special case of introductions, any advisor can be used with any advice.
`org.springframework.aop.support.DefaultPointcutAdvisor` is the most commonly used
advisor class. It can be used with a `MethodInterceptor`, `BeforeAdvice`, or
`ThrowsAdvice`.
It is possible to mix advisor and advice types in Spring in the same AOP proxy. For
example, you could use an interception around advice, throws advice, and before advice in
one proxy configuration. Spring automatically creates the necessary interceptor
chain.
@@ -0,0 +1,131 @@
[[aop-autoproxy]]
= Using the "auto-proxy" facility
So far, we have considered explicit creation of AOP proxies by using a `ProxyFactoryBean` or
similar factory bean.
Spring also lets us use "`auto-proxy`" bean definitions, which can automatically
proxy selected bean definitions. This is built on Spring's "`bean post processor`"
infrastructure, which enables modification of any bean definition as the container loads.
In this model, you set up some special bean definitions in your XML bean definition file
to configure the auto-proxy infrastructure. This lets you declare the targets
eligible for auto-proxying. You need not use `ProxyFactoryBean`.
There are two ways to do this:
* By using an auto-proxy creator that refers to specific beans in the current context.
* A special case of auto-proxy creation that deserves to be considered separately:
auto-proxy creation driven by source-level metadata attributes.
[[aop-autoproxy-choices]]
== Auto-proxy Bean Definitions
This section covers the auto-proxy creators provided by the
`org.springframework.aop.framework.autoproxy` package.
[[aop-api-autoproxy]]
=== `BeanNameAutoProxyCreator`
The `BeanNameAutoProxyCreator` class is a `BeanPostProcessor` that automatically creates
AOP proxies for beans with names that match literal values or wildcards. The following
example shows how to create a `BeanNameAutoProxyCreator` bean:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="jdk*,onlyJdk"/>
<property name="interceptorNames">
<list>
<value>myInterceptor</value>
</list>
</property>
</bean>
----
As with `ProxyFactoryBean`, there is an `interceptorNames` property rather than a list
of interceptors, to allow correct behavior for prototype advisors. Named "`interceptors`"
can be advisors or any advice type.
As with auto-proxying in general, the main point of using `BeanNameAutoProxyCreator` is
to apply the same configuration consistently to multiple objects, with minimal volume of
configuration. It is a popular choice for applying declarative transactions to multiple
objects.
Bean definitions whose names match, such as `jdkMyBean` and `onlyJdk` in the preceding
example, are plain old bean definitions with the target class. An AOP proxy is
automatically created by the `BeanNameAutoProxyCreator`. The same advice is applied
to all matching beans. Note that, if advisors are used (rather than the interceptor in
the preceding example), the pointcuts may apply differently to different beans.
[[aop-api-autoproxy-default]]
=== `DefaultAdvisorAutoProxyCreator`
A more general and extremely powerful auto-proxy creator is
`DefaultAdvisorAutoProxyCreator`. This automagically applies eligible advisors in the
current context, without the need to include specific bean names in the auto-proxy
advisor's bean definition. It offers the same merit of consistent configuration and
avoidance of duplication as `BeanNameAutoProxyCreator`.
Using this mechanism involves:
* Specifying a `DefaultAdvisorAutoProxyCreator` bean definition.
* Specifying any number of advisors in the same or related contexts. Note that these
must be advisors, not interceptors or other advice. This is necessary,
because there must be a pointcut to evaluate, to check the eligibility of each advice
to candidate bean definitions.
The `DefaultAdvisorAutoProxyCreator` automatically evaluates the pointcut contained
in each advisor, to see what (if any) advice it should apply to each business object
(such as `businessObject1` and `businessObject2` in the example).
This means that any number of advisors can be applied automatically to each business
object. If no pointcut in any of the advisors matches any method in a business object,
the object is not proxied. As bean definitions are added for new business objects,
they are automatically proxied if necessary.
Auto-proxying in general has the advantage of making it impossible for callers or
dependencies to obtain an un-advised object. Calling `getBean("businessObject1")` on this
`ApplicationContext` returns an AOP proxy, not the target business object. (The "`inner
bean`" idiom shown earlier also offers this benefit.)
The following example creates a `DefaultAdvisorAutoProxyCreator` bean and the other
elements discussed in this section:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
<property name="transactionInterceptor" ref="transactionInterceptor"/>
</bean>
<bean id="customAdvisor" class="com.mycompany.MyAdvisor"/>
<bean id="businessObject1" class="com.mycompany.BusinessObject1">
<!-- Properties omitted -->
</bean>
<bean id="businessObject2" class="com.mycompany.BusinessObject2"/>
----
The `DefaultAdvisorAutoProxyCreator` is very useful if you want to apply the same advice
consistently to many business objects. Once the infrastructure definitions are in place,
you can add new business objects without including specific proxy configuration.
You can also easily drop in additional aspects (for example, tracing or
performance monitoring aspects) with minimal change to configuration.
The `DefaultAdvisorAutoProxyCreator` offers support for filtering (by using a naming
convention so that only certain advisors are evaluated, which allows the use of multiple,
differently configured, AdvisorAutoProxyCreators in the same factory) and ordering.
Advisors can implement the `org.springframework.core.Ordered` interface to ensure
correct ordering if this is an issue. The `TransactionAttributeSourceAdvisor` used in the
preceding example has a configurable order value. The default setting is unordered.
@@ -0,0 +1,71 @@
[[aop-concise-proxy]]
= Concise Proxy Definitions
Especially when defining transactional proxies, you may end up with many similar proxy
definitions. The use of parent and child bean definitions, along with inner bean
definitions, can result in much cleaner and more concise proxy definitions.
First, we create a parent, template, bean definition for the proxy, as follows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
----
This is never instantiated itself, so it can actually be incomplete. Then, each proxy
that needs to be created is a child bean definition, which wraps the target of the
proxy as an inner bean definition, since the target is never used on its own anyway.
The following example shows such a child bean:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="myService" parent="txProxyTemplate">
<property name="target">
<bean class="org.springframework.samples.MyServiceImpl">
</bean>
</property>
</bean>
----
You can override properties from the parent template. In the following example,
we override the transaction propagation settings:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="mySpecialService" parent="txProxyTemplate">
<property name="target">
<bean class="org.springframework.samples.MySpecialServiceImpl">
</bean>
</property>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="store*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
----
Note that in the parent bean example, we explicitly marked the parent bean definition as
being abstract by setting the `abstract` attribute to `true`, as described
xref:core/beans/child-bean-definitions.adoc[previously], so that it may not actually ever be
instantiated. Application contexts (but not simple bean factories), by default,
pre-instantiate all singletons. Therefore, it is important (at least for singleton beans)
that, if you have a (parent) bean definition that you intend to use only as a template,
and this definition specifies a class, you must make sure to set the `abstract`
attribute to `true`. Otherwise, the application context actually tries to
pre-instantiate it.
@@ -0,0 +1,16 @@
[[aop-extensibility]]
= Defining New Advice Types
:page-section-summary-toc: 1
Spring AOP is designed to be extensible. While the interception implementation strategy
is presently used internally, it is possible to support arbitrary advice types in
addition to the interception around advice, before, throws advice, and
after returning advice.
The `org.springframework.aop.framework.adapter` package is an SPI package that lets
support for new custom advice types be added without changing the core framework.
The only constraint on a custom `Advice` type is that it must implement the
`org.aopalliance.aop.Advice` marker interface.
See the {api-spring-framework}/aop/framework/adapter/package-summary.html[`org.springframework.aop.framework.adapter`]
javadoc for further information.
@@ -0,0 +1,329 @@
[[aop-pfb]]
= Using the `ProxyFactoryBean` to Create AOP Proxies
If you use the Spring IoC container (an `ApplicationContext` or `BeanFactory`) for your
business objects (and you should be!), you want to use one of Spring's AOP
`FactoryBean` implementations. (Remember that a factory bean introduces a layer of indirection, letting
it create objects of a different type.)
NOTE: The Spring AOP support also uses factory beans under the covers.
The basic way to create an AOP proxy in Spring is to use the
`org.springframework.aop.framework.ProxyFactoryBean`. This gives complete control over
the pointcuts, any advice that applies, and their ordering. However, there are simpler
options that are preferable if you do not need such control.
[[aop-pfb-1]]
== Basics
The `ProxyFactoryBean`, like other Spring `FactoryBean` implementations, introduces a
level of indirection. If you define a `ProxyFactoryBean` named `foo`, objects that
reference `foo` do not see the `ProxyFactoryBean` instance itself but an object
created by the implementation of the `getObject()` method in the `ProxyFactoryBean` . This
method creates an AOP proxy that wraps a target object.
One of the most important benefits of using a `ProxyFactoryBean` or another IoC-aware
class to create AOP proxies is that advice and pointcuts can also be
managed by IoC. This is a powerful feature, enabling certain approaches that are hard to
achieve with other AOP frameworks. For example, an advice may itself reference
application objects (besides the target, which should be available in any AOP
framework), benefiting from all the pluggability provided by Dependency Injection.
[[aop-pfb-2]]
== JavaBean Properties
In common with most `FactoryBean` implementations provided with Spring, the
`ProxyFactoryBean` class is itself a JavaBean. Its properties are used to:
* Specify the target you want to proxy.
* Specify whether to use CGLIB (described later and see also xref:core/aop-api/pfb.adoc#aop-pfb-proxy-types[JDK- and CGLIB-based proxies]).
Some key properties are inherited from `org.springframework.aop.framework.ProxyConfig`
(the superclass for all AOP proxy factories in Spring). These key properties include
the following:
* `proxyTargetClass`: `true` if the target class is to be proxied, rather than the
target class's interfaces. If this property value is set to `true`, then CGLIB proxies
are created (but see also xref:core/aop-api/pfb.adoc#aop-pfb-proxy-types[JDK- and CGLIB-based proxies]).
* `optimize`: Controls whether or not aggressive optimizations are applied to proxies
created through CGLIB. You should not blithely use this setting unless you fully
understand how the relevant AOP proxy handles optimization. This is currently used
only for CGLIB proxies. It has no effect with JDK dynamic proxies.
* `frozen`: If a proxy configuration is `frozen`, changes to the configuration are
no longer allowed. This is useful both as a slight optimization and for those cases
when you do not want callers to be able to manipulate the proxy (through the `Advised`
interface) after the proxy has been created. The default value of this property is
`false`, so changes (such as adding additional advice) are allowed.
* `exposeProxy`: Determines whether or not the current proxy should be exposed in a
`ThreadLocal` so that it can be accessed by the target. If a target needs to obtain
the proxy and the `exposeProxy` property is set to `true`, the target can use the
`AopContext.currentProxy()` method.
Other properties specific to `ProxyFactoryBean` include the following:
* `proxyInterfaces`: An array of `String` interface names. If this is not supplied, a CGLIB
proxy for the target class is used (but see also xref:core/aop-api/pfb.adoc#aop-pfb-proxy-types[JDK- and CGLIB-based proxies]).
* `interceptorNames`: A `String` array of `Advisor`, interceptor, or other advice names to
apply. Ordering is significant, on a first come-first served basis. That is to say
that the first interceptor in the list is the first to be able to intercept the
invocation.
+
The names are bean names in the current factory, including bean names from ancestor
factories. You cannot mention bean references here, since doing so results in the
`ProxyFactoryBean` ignoring the singleton setting of the advice.
+
You can append an interceptor name with an asterisk (`*`). Doing so results in the
application of all advisor beans with names that start with the part before the asterisk
to be applied. You can find an example of using this feature in xref:core/aop-api/pfb.adoc#aop-global-advisors[Using "`Global`" Advisors].
* singleton: Whether or not the factory should return a single object, no matter how
often the `getObject()` method is called. Several `FactoryBean` implementations offer
such a method. The default value is `true`. If you want to use stateful advice - for
example, for stateful mixins - use prototype advice along with a singleton value of
`false`.
[[aop-pfb-proxy-types]]
== JDK- and CGLIB-based proxies
This section serves as the definitive documentation on how the `ProxyFactoryBean`
chooses to create either a JDK-based proxy or a CGLIB-based proxy for a particular target
object (which is to be proxied).
NOTE: The behavior of the `ProxyFactoryBean` with regard to creating JDK- or CGLIB-based
proxies changed between versions 1.2.x and 2.0 of Spring. The `ProxyFactoryBean` now
exhibits similar semantics with regard to auto-detecting interfaces as those of the
`TransactionProxyFactoryBean` class.
If the class of a target object that is to be proxied (hereafter simply referred to as
the target class) does not implement any interfaces, a CGLIB-based proxy is
created. This is the easiest scenario, because JDK proxies are interface-based, and no
interfaces means JDK proxying is not even possible. You can plug in the target bean
and specify the list of interceptors by setting the `interceptorNames` property. Note that a
CGLIB-based proxy is created even if the `proxyTargetClass` property of the
`ProxyFactoryBean` has been set to `false`. (Doing so makes no sense and is best
removed from the bean definition, because it is, at best, redundant, and, at worst
confusing.)
If the target class implements one (or more) interfaces, the type of proxy that is
created depends on the configuration of the `ProxyFactoryBean`.
If the `proxyTargetClass` property of the `ProxyFactoryBean` has been set to `true`,
a CGLIB-based proxy is created. This makes sense and is in keeping with the
principle of least surprise. Even if the `proxyInterfaces` property of the
`ProxyFactoryBean` has been set to one or more fully qualified interface names, the fact
that the `proxyTargetClass` property is set to `true` causes CGLIB-based
proxying to be in effect.
If the `proxyInterfaces` property of the `ProxyFactoryBean` has been set to one or more
fully qualified interface names, a JDK-based proxy is created. The created
proxy implements all of the interfaces that were specified in the `proxyInterfaces`
property. If the target class happens to implement a whole lot more interfaces than
those specified in the `proxyInterfaces` property, that is all well and good, but those
additional interfaces are not implemented by the returned proxy.
If the `proxyInterfaces` property of the `ProxyFactoryBean` has not been set, but
the target class does implement one (or more) interfaces, the
`ProxyFactoryBean` auto-detects the fact that the target class does actually
implement at least one interface, and a JDK-based proxy is created. The interfaces
that are actually proxied are all of the interfaces that the target class
implements. In effect, this is the same as supplying a list of each and every
interface that the target class implements to the `proxyInterfaces` property. However,
it is significantly less work and less prone to typographical errors.
[[aop-api-proxying-intf]]
== Proxying Interfaces
Consider a simple example of `ProxyFactoryBean` in action. This example involves:
* A target bean that is proxied. This is the `personTarget` bean definition in
the example.
* An `Advisor` and an `Interceptor` used to provide advice.
* An AOP proxy bean definition to specify the target object (the `personTarget` bean),
the interfaces to proxy, and the advice to apply.
The following listing shows the example:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="personTarget" class="com.mycompany.PersonImpl">
<property name="name" value="Tony"/>
<property name="age" value="51"/>
</bean>
<bean id="myAdvisor" class="com.mycompany.MyAdvisor">
<property name="someProperty" value="Custom string property value"/>
</bean>
<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor">
</bean>
<bean id="person"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.mycompany.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>myAdvisor</value>
<value>debugInterceptor</value>
</list>
</property>
</bean>
----
Note that the `interceptorNames` property takes a list of `String`, which holds the bean names of the
interceptors or advisors in the current factory. You can use advisors, interceptors, before, after
returning, and throws advice objects. The ordering of advisors is significant.
NOTE: You might be wondering why the list does not hold bean references. The reason for this is
that, if the singleton property of the `ProxyFactoryBean` is set to `false`, it must be able to
return independent proxy instances. If any of the advisors is itself a prototype, an
independent instance would need to be returned, so it is necessary to be able to obtain
an instance of the prototype from the factory. Holding a reference is not sufficient.
The `person` bean definition shown earlier can be used in place of a `Person` implementation, as
follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
Person person = (Person) factory.getBean("person");
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
val person = factory.getBean("person") as Person;
----
======
Other beans in the same IoC context can express a strongly typed dependency on it, as
with an ordinary Java object. The following example shows how to do so:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="personUser" class="com.mycompany.PersonUser">
<property name="person"><ref bean="person"/></property>
</bean>
----
The `PersonUser` class in this example exposes a property of type `Person`. As far as
it is concerned, the AOP proxy can be used transparently in place of a "`real`" person
implementation. However, its class would be a dynamic proxy class. It would be possible
to cast it to the `Advised` interface (discussed later).
You can conceal the distinction between target and proxy by using an anonymous
inner bean. Only the `ProxyFactoryBean` definition is different. The
advice is included only for completeness. The following example shows how to use an
anonymous inner bean:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="myAdvisor" class="com.mycompany.MyAdvisor">
<property name="someProperty" value="Custom string property value"/>
</bean>
<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"/>
<bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.mycompany.Person"/>
<!-- Use inner bean, not local reference to target -->
<property name="target">
<bean class="com.mycompany.PersonImpl">
<property name="name" value="Tony"/>
<property name="age" value="51"/>
</bean>
</property>
<property name="interceptorNames">
<list>
<value>myAdvisor</value>
<value>debugInterceptor</value>
</list>
</property>
</bean>
----
Using an anonymous inner bean has the advantage that there is only one object of type `Person`. This is useful if we want
to prevent users of the application context from obtaining a reference to the un-advised
object or need to avoid any ambiguity with Spring IoC autowiring. There is also,
arguably, an advantage in that the `ProxyFactoryBean` definition is self-contained.
However, there are times when being able to obtain the un-advised target from the
factory might actually be an advantage (for example, in certain test scenarios).
[[aop-api-proxying-class]]
== Proxying Classes
What if you need to proxy a class, rather than one or more interfaces?
Imagine that in our earlier example, there was no `Person` interface. We needed to advise
a class called `Person` that did not implement any business interface. In this case, you
can configure Spring to use CGLIB proxying rather than dynamic proxies. To do so, set the
`proxyTargetClass` property on the `ProxyFactoryBean` shown earlier to `true`. While it is best to
program to interfaces rather than classes, the ability to advise classes that do not
implement interfaces can be useful when working with legacy code. (In general, Spring
is not prescriptive. While it makes it easy to apply good practices, it avoids forcing a
particular approach.)
If you want to, you can force the use of CGLIB in any case, even if you do have
interfaces.
CGLIB proxying works by generating a subclass of the target class at runtime. Spring
configures this generated subclass to delegate method calls to the original target. The
subclass is used to implement the Decorator pattern, weaving in the advice.
CGLIB proxying should generally be transparent to users. However, there are some issues
to consider:
* `final` classes cannot be proxied, because they cannot be extended.
* `final` methods cannot be advised, because they cannot be overridden.
* `private` methods cannot be advised, because they cannot be overridden.
NOTE: There is no need to add CGLIB to your classpath. CGLIB is repackaged and included
in the `spring-core` JAR. In other words, CGLIB-based AOP works "out of the box", as do
JDK dynamic proxies.
There is little performance difference between CGLIB proxies and dynamic proxies.
Performance should not be a decisive consideration in this case.
[[aop-global-advisors]]
== Using "`Global`" Advisors
By appending an asterisk to an interceptor name, all advisors with bean names that match
the part before the asterisk are added to the advisor chain. This can come in handy
if you need to add a standard set of "`global`" advisors. The following example defines
two global advisors:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="service"/>
<property name="interceptorNames">
<list>
<value>global*</value>
</list>
</property>
</bean>
<bean id="global_debug" class="org.springframework.aop.interceptor.DebugInterceptor"/>
<bean id="global_performance" class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/>
----
@@ -0,0 +1,256 @@
[[aop-api-pointcuts]]
= Pointcut API in Spring
This section describes how Spring handles the crucial pointcut concept.
[[aop-api-concepts]]
== Concepts
Spring's pointcut model enables pointcut reuse independent of advice types. You can
target different advice with the same pointcut.
The `org.springframework.aop.Pointcut` interface is the central interface, used to
target advice to particular classes and methods. The complete interface follows:
[source,java,indent=0,subs="verbatim,quotes"]
----
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
----
Splitting the `Pointcut` interface into two parts allows reuse of class and method
matching parts and fine-grained composition operations (such as performing a "`union`"
with another method matcher).
The `ClassFilter` interface is used to restrict the pointcut to a given set of target
classes. If the `matches()` method always returns true, all target classes are
matched. The following listing shows the `ClassFilter` interface definition:
[source,java,indent=0,subs="verbatim,quotes"]
----
public interface ClassFilter {
boolean matches(Class clazz);
}
----
The `MethodMatcher` interface is normally more important. The complete interface follows:
[source,java,indent=0,subs="verbatim,quotes"]
----
public interface MethodMatcher {
boolean matches(Method m, Class<?> targetClass);
boolean isRuntime();
boolean matches(Method m, Class<?> targetClass, Object... args);
}
----
The `matches(Method, Class)` method is used to test whether this pointcut ever
matches a given method on a target class. This evaluation can be performed when an AOP
proxy is created to avoid the need for a test on every method invocation. If the
two-argument `matches` method returns `true` for a given method, and the `isRuntime()`
method for the MethodMatcher returns `true`, the three-argument matches method is
invoked on every method invocation. This lets a pointcut look at the arguments passed
to the method invocation immediately before the target advice starts.
Most `MethodMatcher` implementations are static, meaning that their `isRuntime()` method
returns `false`. In this case, the three-argument `matches` method is never invoked.
TIP: If possible, try to make pointcuts static, allowing the AOP framework to cache the
results of pointcut evaluation when an AOP proxy is created.
[[aop-api-pointcut-ops]]
== Operations on Pointcuts
Spring supports operations (notably, union and intersection) on pointcuts.
Union means the methods that either pointcut matches.
Intersection means the methods that both pointcuts match.
Union is usually more useful.
You can compose pointcuts by using the static methods in the
`org.springframework.aop.support.Pointcuts` class or by using the
`ComposablePointcut` class in the same package. However, using AspectJ pointcut
expressions is usually a simpler approach.
[[aop-api-pointcuts-aspectj]]
== AspectJ Expression Pointcuts
Since 2.0, the most important type of pointcut used by Spring is
`org.springframework.aop.aspectj.AspectJExpressionPointcut`. This is a pointcut that
uses an AspectJ-supplied library to parse an AspectJ pointcut expression string.
See the xref:core/aop.adoc[previous chapter] for a discussion of supported AspectJ pointcut primitives.
[[aop-api-pointcuts-impls]]
== Convenience Pointcut Implementations
Spring provides several convenient pointcut implementations. You can use some of them
directly; others are intended to be subclassed in application-specific pointcuts.
[[aop-api-pointcuts-static]]
=== Static Pointcuts
Static pointcuts are based on the method and the target class and cannot take into account
the method's arguments. Static pointcuts suffice -- and are best -- for most usages.
Spring can evaluate a static pointcut only once, when a method is first invoked.
After that, there is no need to evaluate the pointcut again with each method invocation.
The rest of this section describes some of the static pointcut implementations that are
included with Spring.
[[aop-api-pointcuts-regex]]
==== Regular Expression Pointcuts
One obvious way to specify static pointcuts is regular expressions. Several AOP
frameworks besides Spring make this possible.
`org.springframework.aop.support.JdkRegexpMethodPointcut` is a generic regular
expression pointcut that uses the regular expression support in the JDK.
With the `JdkRegexpMethodPointcut` class, you can provide a list of pattern strings.
If any of these is a match, the pointcut evaluates to `true`. (As a consequence,
the resulting pointcut is effectively the union of the specified patterns.)
The following example shows how to use `JdkRegexpMethodPointcut`:
[source,xml,indent=0,subs="verbatim"]
----
<bean id="settersAndAbsquatulatePointcut"
class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="patterns">
<list>
<value>.*set.*</value>
<value>.*absquatulate</value>
</list>
</property>
</bean>
----
Spring provides a convenience class named `RegexpMethodPointcutAdvisor`, which lets us
also reference an `Advice` (remember that an `Advice` can be an interceptor, before advice,
throws advice, and others). Behind the scenes, Spring uses a `JdkRegexpMethodPointcut`.
Using `RegexpMethodPointcutAdvisor` simplifies wiring, as the one bean encapsulates both
pointcut and advice, as the following example shows:
[source,xml,indent=0,subs="verbatim"]
----
<bean id="settersAndAbsquatulateAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref bean="beanNameOfAopAllianceInterceptor"/>
</property>
<property name="patterns">
<list>
<value>.*set.*</value>
<value>.*absquatulate</value>
</list>
</property>
</bean>
----
You can use `RegexpMethodPointcutAdvisor` with any `Advice` type.
[[aop-api-pointcuts-attribute-driven]]
==== Attribute-driven Pointcuts
An important type of static pointcut is a metadata-driven pointcut. This uses the
values of metadata attributes (typically, source-level metadata).
[[aop-api-pointcuts-dynamic]]
=== Dynamic pointcuts
Dynamic pointcuts are costlier to evaluate than static pointcuts. They take into account
method arguments as well as static information. This means that they must be
evaluated with every method invocation and that the result cannot be cached, as arguments will
vary.
The main example is the `control flow` pointcut.
[[aop-api-pointcuts-cflow]]
==== Control Flow Pointcuts
Spring control flow pointcuts are conceptually similar to AspectJ `cflow` pointcuts,
although less powerful. (There is currently no way to specify that a pointcut runs
below a join point matched by another pointcut.) A control flow pointcut matches the
current call stack. For example, it might fire if the join point was invoked by a method
in the `com.mycompany.web` package or by the `SomeCaller` class. Control flow pointcuts
are specified by using the `org.springframework.aop.support.ControlFlowPointcut` class.
NOTE: Control flow pointcuts are significantly more expensive to evaluate at runtime than even
other dynamic pointcuts. In Java 1.4, the cost is about five times that of other dynamic
pointcuts.
[[aop-api-pointcuts-superclasses]]
== Pointcut Superclasses
Spring provides useful pointcut superclasses to help you to implement your own pointcuts.
Because static pointcuts are most useful, you should probably subclass
`StaticMethodMatcherPointcut`. This requires implementing only one
abstract method (although you can override other methods to customize behavior). The
following example shows how to subclass `StaticMethodMatcherPointcut`:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
class TestStaticPointcut extends StaticMethodMatcherPointcut {
public boolean matches(Method m, Class targetClass) {
// return true if custom criteria match
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class TestStaticPointcut : StaticMethodMatcherPointcut() {
override fun matches(method: Method, targetClass: Class<*>): Boolean {
// return true if custom criteria match
}
}
----
======
There are also superclasses for dynamic pointcuts.
You can use custom pointcuts with any advice type.
[[aop-api-pointcuts-custom]]
== Custom Pointcuts
Because pointcuts in Spring AOP are Java classes rather than language features (as in
AspectJ), you can declare custom pointcuts, whether static or dynamic. Custom
pointcuts in Spring can be arbitrarily complex. However, we recommend using the AspectJ pointcut
expression language, if you can.
NOTE: Later versions of Spring may offer support for "`semantic pointcuts`" as offered by JAC --
for example, "`all methods that change instance variables in the target object.`"
@@ -0,0 +1,54 @@
[[aop-prog]]
= Creating AOP Proxies Programmatically with the `ProxyFactory`
It is easy to create AOP proxies programmatically with Spring. This lets you use
Spring AOP without dependency on Spring IoC.
The interfaces implemented by the target object are
automatically proxied. The following listing shows creation of a proxy for a target object, with one
interceptor and one advisor:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl);
factory.addAdvice(myMethodInterceptor);
factory.addAdvisor(myAdvisor);
MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy();
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
val factory = ProxyFactory(myBusinessInterfaceImpl)
factory.addAdvice(myMethodInterceptor)
factory.addAdvisor(myAdvisor)
val tb = factory.proxy as MyBusinessInterface
----
======
The first step is to construct an object of type
`org.springframework.aop.framework.ProxyFactory`. You can create this with a target
object, as in the preceding example, or specify the interfaces to be proxied in an alternate
constructor.
You can add advice (with interceptors as a specialized kind of advice), advisors, or both
and manipulate them for the life of the `ProxyFactory`. If you add an
`IntroductionInterceptionAroundAdvisor`, you can cause the proxy to implement additional
interfaces.
There are also convenience methods on `ProxyFactory` (inherited from `AdvisedSupport`)
that let you add other advice types, such as before and throws advice.
`AdvisedSupport` is the superclass of both `ProxyFactory` and `ProxyFactoryBean`.
TIP: Integrating AOP proxy creation with the IoC framework is best practice in most
applications. We recommend that you externalize configuration from Java code with AOP,
as you should in general.
@@ -0,0 +1,232 @@
[[aop-targetsource]]
= Using `TargetSource` Implementations
Spring offers the concept of a `TargetSource`, expressed in the
`org.springframework.aop.TargetSource` interface. This interface is responsible for
returning the "`target object`" that implements the join point. The `TargetSource`
implementation is asked for a target instance each time the AOP proxy handles a method
invocation.
Developers who use Spring AOP do not normally need to work directly with `TargetSource` implementations, but
this provides a powerful means of supporting pooling, hot swappable, and other
sophisticated targets. For example, a pooling `TargetSource` can return a different target
instance for each invocation, by using a pool to manage instances.
If you do not specify a `TargetSource`, a default implementation is used to wrap a
local object. The same target is returned for each invocation (as you would expect).
The rest of this section describes the standard target sources provided with Spring and how you can use them.
TIP: When using a custom target source, your target will usually need to be a prototype
rather than a singleton bean definition. This allows Spring to create a new target
instance when required.
[[aop-ts-swap]]
== Hot-swappable Target Sources
The `org.springframework.aop.target.HotSwappableTargetSource` exists to let the target
of an AOP proxy be switched while letting callers keep their references to it.
Changing the target source's target takes effect immediately. The
`HotSwappableTargetSource` is thread-safe.
You can change the target by using the `swap()` method on HotSwappableTargetSource, as the follow example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper");
Object oldTarget = swapper.swap(newTarget);
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
val swapper = beanFactory.getBean("swapper") as HotSwappableTargetSource
val oldTarget = swapper.swap(newTarget)
----
======
The following example shows the required XML definitions:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="initialTarget" class="mycompany.OldTarget"/>
<bean id="swapper" class="org.springframework.aop.target.HotSwappableTargetSource">
<constructor-arg ref="initialTarget"/>
</bean>
<bean id="swappable" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource" ref="swapper"/>
</bean>
----
The preceding `swap()` call changes the target of the swappable bean. Clients that hold a
reference to that bean are unaware of the change but immediately start hitting
the new target.
Although this example does not add any advice (it is not necessary to add advice to
use a `TargetSource`), any `TargetSource` can be used in conjunction with
arbitrary advice.
[[aop-ts-pool]]
== Pooling Target Sources
Using a pooling target source provides a similar programming model to stateless session
EJBs, in which a pool of identical instances is maintained, with method invocations
going to free objects in the pool.
A crucial difference between Spring pooling and SLSB pooling is that Spring pooling can
be applied to any POJO. As with Spring in general, this service can be applied in a
non-invasive way.
Spring provides support for Commons Pool 2.2, which provides a
fairly efficient pooling implementation. You need the `commons-pool` Jar on your
application's classpath to use this feature. You can also subclass
`org.springframework.aop.target.AbstractPoolingTargetSource` to support any other
pooling API.
NOTE: Commons Pool 1.5+ is also supported but is deprecated as of Spring Framework 4.2.
The following listing shows an example configuration:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="businessObjectTarget" class="com.mycompany.MyBusinessObject"
scope="prototype">
... properties omitted
</bean>
<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPool2TargetSource">
<property name="targetBeanName" value="businessObjectTarget"/>
<property name="maxSize" value="25"/>
</bean>
<bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource" ref="poolTargetSource"/>
<property name="interceptorNames" value="myInterceptor"/>
</bean>
----
Note that the target object (`businessObjectTarget` in the preceding example) must be a
prototype. This lets the `PoolingTargetSource` implementation create new instances
of the target to grow the pool as necessary. See the {api-spring-framework}/aop/target/AbstractPoolingTargetSource.html[javadoc of
`AbstractPoolingTargetSource`] and the concrete subclass you wish to use for information
about its properties. `maxSize` is the most basic and is always guaranteed to be present.
In this case, `myInterceptor` is the name of an interceptor that would need to be
defined in the same IoC context. However, you need not specify interceptors to
use pooling. If you want only pooling and no other advice, do not set the
`interceptorNames` property at all.
You can configure Spring to be able to cast any pooled object to the
`org.springframework.aop.target.PoolingConfig` interface, which exposes information
about the configuration and current size of the pool through an introduction. You
need to define an advisor similar to the following:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="poolConfigAdvisor" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="poolTargetSource"/>
<property name="targetMethod" value="getPoolingConfigMixin"/>
</bean>
----
This advisor is obtained by calling a convenience method on the
`AbstractPoolingTargetSource` class, hence the use of `MethodInvokingFactoryBean`. This
advisor's name (`poolConfigAdvisor`, here) must be in the list of interceptors names in
the `ProxyFactoryBean` that exposes the pooled object.
The cast is defined as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject");
System.out.println("Max pool size is " + conf.getMaxSize());
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
val conf = beanFactory.getBean("businessObject") as PoolingConfig
println("Max pool size is " + conf.maxSize)
----
======
NOTE: Pooling stateless service objects is not usually necessary. We do not believe it should
be the default choice, as most stateless objects are naturally thread safe, and instance
pooling is problematic if resources are cached.
Simpler pooling is available by using auto-proxying. You can set the `TargetSource` implementations
used by any auto-proxy creator.
[[aop-ts-prototype]]
== Prototype Target Sources
Setting up a "`prototype`" target source is similar to setting up a pooling `TargetSource`. In this
case, a new instance of the target is created on every method invocation. Although
the cost of creating a new object is not high in a modern JVM, the cost of wiring up the
new object (satisfying its IoC dependencies) may be more expensive. Thus, you should not
use this approach without very good reason.
To do this, you could modify the `poolTargetSource` definition shown earlier as follows
(we also changed the name, for clarity):
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="prototypeTargetSource" class="org.springframework.aop.target.PrototypeTargetSource">
<property name="targetBeanName" ref="businessObjectTarget"/>
</bean>
----
The only property is the name of the target bean. Inheritance is used in the
`TargetSource` implementations to ensure consistent naming. As with the pooling target
source, the target bean must be a prototype bean definition.
[[aop-ts-threadlocal]]
== `ThreadLocal` Target Sources
`ThreadLocal` target sources are useful if you need an object to be created for each
incoming request (per thread that is). The concept of a `ThreadLocal` provides a JDK-wide
facility to transparently store a resource alongside a thread. Setting up a
`ThreadLocalTargetSource` is pretty much the same as was explained for the other types
of target source, as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="threadlocalTargetSource" class="org.springframework.aop.target.ThreadLocalTargetSource">
<property name="targetBeanName" value="businessObjectTarget"/>
</bean>
----
NOTE: `ThreadLocal` instances come with serious issues (potentially resulting in memory leaks) when
incorrectly using them in multi-threaded and multi-classloader environments. You
should always consider wrapping a `ThreadLocal` in some other class and never directly use
the `ThreadLocal` itself (except in the wrapper class). Also, you should
always remember to correctly set and unset (where the latter simply involves a call to
`ThreadLocal.set(null)`) the resource local to the thread. Unsetting should be done in
any case, since not unsetting it might result in problematic behavior. Spring's
`ThreadLocal` support does this for you and should always be considered in favor of using
`ThreadLocal` instances without other proper handling code.
@@ -0,0 +1,38 @@
[[aop]]
= Aspect Oriented Programming with Spring
Aspect-oriented Programming (AOP) complements Object-oriented Programming (OOP) by
providing another way of thinking about program structure. The key unit of modularity
in OOP is the class, whereas in AOP the unit of modularity is the aspect. Aspects
enable the modularization of concerns (such as transaction management) that cut across
multiple types and objects. (Such concerns are often termed "crosscutting" concerns
in AOP literature.)
One of the key components of Spring is the AOP framework. While the Spring IoC
container does not depend on AOP (meaning you do not need to use AOP if you don't want
to), AOP complements Spring IoC to provide a very capable middleware solution.
.Spring AOP with AspectJ pointcuts
****
Spring provides simple and powerful ways of writing custom aspects by using either a
xref:core/aop/schema.adoc[schema-based approach] or the xref:core/aop/ataspectj.adoc[@AspectJ annotation style].
Both of these styles offer fully typed advice and use of the AspectJ pointcut language
while still using Spring AOP for weaving.
This chapter discusses the schema- and @AspectJ-based AOP support.
The lower-level AOP support is discussed in xref:core/aop-api.adoc[the following chapter].
****
AOP is used in the Spring Framework to:
* Provide declarative enterprise services. The most important such service is
xref:data-access/transaction/declarative.adoc[declarative transaction management].
* Let users implement custom aspects, complementing their use of OOP with AOP.
NOTE: If you are interested only in generic declarative services or other pre-packaged
declarative middleware services such as pooling, you do not need to work directly with
Spring AOP, and can skip most of this chapter.
@@ -0,0 +1,59 @@
[[aop-aspectj-programmatic]]
= Programmatic Creation of @AspectJ Proxies
In addition to declaring aspects in your configuration by using either `<aop:config>`
or `<aop:aspectj-autoproxy>`, it is also possible to programmatically create proxies
that advise target objects. For the full details of Spring's AOP API, see the
xref:core/aop-api.adoc[next chapter]. Here, we want to focus on the ability to automatically
create proxies by using @AspectJ aspects.
You can use the `org.springframework.aop.aspectj.annotation.AspectJProxyFactory` class
to create a proxy for a target object that is advised by one or more @AspectJ aspects.
The basic usage for this class is very simple, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
// create a factory that can generate a proxy for the given target object
AspectJProxyFactory factory = new AspectJProxyFactory(targetObject);
// add an aspect, the class must be an @AspectJ aspect
// you can call this as many times as you need with different aspects
factory.addAspect(SecurityManager.class);
// you can also add existing aspect instances, the type of the object supplied
// must be an @AspectJ aspect
factory.addAspect(usageTracker);
// now get the proxy object...
MyInterfaceType proxy = factory.getProxy();
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
// create a factory that can generate a proxy for the given target object
val factory = AspectJProxyFactory(targetObject)
// add an aspect, the class must be an @AspectJ aspect
// you can call this as many times as you need with different aspects
factory.addAspect(SecurityManager::class.java)
// you can also add existing aspect instances, the type of the object supplied
// must be an @AspectJ aspect
factory.addAspect(usageTracker)
// now get the proxy object...
val proxy = factory.getProxy<Any>()
----
======
See the {api-spring-framework}/aop/aspectj/annotation/AspectJProxyFactory.html[javadoc] for more information.
@@ -0,0 +1,16 @@
[[aop-ataspectj]]
= @AspectJ support
:page-section-summary-toc: 1
@AspectJ refers to a style of declaring aspects as regular Java classes annotated with
annotations. The @AspectJ style was introduced by the
https://www.eclipse.org/aspectj[AspectJ project] as part of the AspectJ 5 release. Spring
interprets the same annotations as AspectJ 5, using a library supplied by AspectJ
for pointcut parsing and matching. The AOP runtime is still pure Spring AOP, though, and
there is no dependency on the AspectJ compiler or weaver.
NOTE: Using the AspectJ compiler and weaver enables use of the full AspectJ language and
is discussed in xref:core/aop/using-aspectj.adoc[Using AspectJ with Spring Applications].
@@ -0,0 +1,941 @@
[[aop-advice]]
= Declaring Advice
Advice is associated with a pointcut expression and runs before, after, or around method
executions matched by the pointcut. The pointcut expression may be either an _inline
pointcut_ or a reference to a xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[_named pointcut_].
[[aop-advice-before]]
== Before Advice
You can declare before advice in an aspect by using the `@Before` annotation.
The following example uses an inline pointcut expression.
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class BeforeExample {
@Before("execution(* com.xyz.dao.*.*(..))")
public void doAccessCheck() {
// ...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Before
@Aspect
class BeforeExample {
@Before("execution(* com.xyz.dao.*.*(..))")
fun doAccessCheck() {
// ...
}
}
----
======
If we use a xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[named pointcut], we can rewrite the preceding example
as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class BeforeExample {
@Before("com.xyz.CommonPointcuts.dataAccessOperation()")
public void doAccessCheck() {
// ...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Before
@Aspect
class BeforeExample {
@Before("com.xyz.CommonPointcuts.dataAccessOperation()")
fun doAccessCheck() {
// ...
}
}
----
======
[[aop-advice-after-returning]]
== After Returning Advice
After returning advice runs when a matched method execution returns normally.
You can declare it by using the `@AfterReturning` annotation.
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;
@Aspect
public class AfterReturningExample {
@AfterReturning("execution(* com.xyz.dao.*.*(..))")
public void doAccessCheck() {
// ...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.AfterReturning
@Aspect
class AfterReturningExample {
@AfterReturning("execution(* com.xyz.dao.*.*(..))")
fun doAccessCheck() {
// ...
}
}
----
======
NOTE: You can have multiple advice declarations (and other members as well),
all inside the same aspect. We show only a single advice declaration in these
examples to focus the effect of each one.
Sometimes, you need access in the advice body to the actual value that was returned.
You can use the form of `@AfterReturning` that binds the return value to get that
access, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;
@Aspect
public class AfterReturningExample {
@AfterReturning(
pointcut="execution(* com.xyz.dao.*.*(..))",
returning="retVal")
public void doAccessCheck(Object retVal) {
// ...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.AfterReturning
@Aspect
class AfterReturningExample {
@AfterReturning(
pointcut = "execution(* com.xyz.dao.*.*(..))",
returning = "retVal")
fun doAccessCheck(retVal: Any?) {
// ...
}
}
----
======
The name used in the `returning` attribute must correspond to the name of a parameter
in the advice method. When a method execution returns, the return value is passed to
the advice method as the corresponding argument value. A `returning` clause also
restricts matching to only those method executions that return a value of the
specified type (in this case, `Object`, which matches any return value).
Please note that it is not possible to return a totally different reference when
using after returning advice.
[[aop-advice-after-throwing]]
== After Throwing Advice
After throwing advice runs when a matched method execution exits by throwing an
exception. You can declare it by using the `@AfterThrowing` annotation, as the
following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
@Aspect
public class AfterThrowingExample {
@AfterThrowing("execution(* com.xyz.dao.*.*(..))")
public void doRecoveryActions() {
// ...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.AfterThrowing
@Aspect
class AfterThrowingExample {
@AfterThrowing("execution(* com.xyz.dao.*.*(..))")
fun doRecoveryActions() {
// ...
}
}
----
======
Often, you want the advice to run only when exceptions of a given type are thrown,
and you also often need access to the thrown exception in the advice body. You can
use the `throwing` attribute to both restrict matching (if desired -- use `Throwable`
as the exception type otherwise) and bind the thrown exception to an advice parameter.
The following example shows how to do so:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
@Aspect
public class AfterThrowingExample {
@AfterThrowing(
pointcut="execution(* com.xyz.dao.*.*(..))",
throwing="ex")
public void doRecoveryActions(DataAccessException ex) {
// ...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.AfterThrowing
@Aspect
class AfterThrowingExample {
@AfterThrowing(
pointcut = "execution(* com.xyz.dao.*.*(..))",
throwing = "ex")
fun doRecoveryActions(ex: DataAccessException) {
// ...
}
}
----
======
The name used in the `throwing` attribute must correspond to the name of a parameter in
the advice method. When a method execution exits by throwing an exception, the exception
is passed to the advice method as the corresponding argument value. A `throwing` clause
also restricts matching to only those method executions that throw an exception of the
specified type (`DataAccessException`, in this case).
[NOTE]
====
Note that `@AfterThrowing` does not indicate a general exception handling callback.
Specifically, an `@AfterThrowing` advice method is only supposed to receive exceptions
from the join point (user-declared target method) itself but not from an accompanying
`@After`/`@AfterReturning` method.
====
[[aop-advice-after-finally]]
== After (Finally) Advice
After (finally) advice runs when a matched method execution exits. It is declared by
using the `@After` annotation. After advice must be prepared to handle both normal and
exception return conditions. It is typically used for releasing resources and similar
purposes. The following example shows how to use after finally advice:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.After;
@Aspect
public class AfterFinallyExample {
@After("execution(* com.xyz.dao.*.*(..))")
public void doReleaseLock() {
// ...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.After
@Aspect
class AfterFinallyExample {
@After("execution(* com.xyz.dao.*.*(..))")
fun doReleaseLock() {
// ...
}
}
----
======
[NOTE]
====
Note that `@After` advice in AspectJ is defined as "after finally advice", analogous
to a finally block in a try-catch statement. It will be invoked for any outcome,
normal return or exception thrown from the join point (user-declared target method),
in contrast to `@AfterReturning` which only applies to successful normal returns.
====
[[aop-ataspectj-around-advice]]
== Around Advice
The last kind of advice is _around_ advice. Around advice runs "around" a matched
method's execution. It has the opportunity to do work both before and after the method
runs and to determine when, how, and even if the method actually gets to run at all.
Around advice is often used if you need to share state before and after a method
execution in a thread-safe manner for example, starting and stopping a timer.
[TIP]
====
Always use the least powerful form of advice that meets your requirements.
For example, do not use _around_ advice if _before_ advice is sufficient for your needs.
====
Around advice is declared by annotating a method with the `@Around` annotation. The
method should declare `Object` as its return type, and the first parameter of the method
must be of type `ProceedingJoinPoint`. Within the body of the advice method, you must
invoke `proceed()` on the `ProceedingJoinPoint` in order for the underlying method to
run. Invoking `proceed()` without arguments will result in the caller's original
arguments being supplied to the underlying method when it is invoked. For advanced use
cases, there is an overloaded variant of the `proceed()` method which accepts an array of
arguments (`Object[]`). The values in the array will be used as the arguments to the
underlying method when it is invoked.
[NOTE]
====
The behavior of `proceed` when called with an `Object[]` is a little different than the
behavior of `proceed` for around advice compiled by the AspectJ compiler. For around
advice written using the traditional AspectJ language, the number of arguments passed to
`proceed` must match the number of arguments passed to the around advice (not the number
of arguments taken by the underlying join point), and the value passed to proceed in a
given argument position supplants the original value at the join point for the entity the
value was bound to (do not worry if this does not make sense right now).
The approach taken by Spring is simpler and a better match to its proxy-based,
execution-only semantics. You only need to be aware of this difference if you compile
`@AspectJ` aspects written for Spring and use `proceed` with arguments with the AspectJ
compiler and weaver. There is a way to write such aspects that is 100% compatible across
both Spring AOP and AspectJ, and this is discussed in the
xref:core/aop/ataspectj/advice.adoc#aop-ataspectj-advice-proceeding-with-the-call[following section on advice parameters].
====
The value returned by the around advice is the return value seen by the caller of the
method. For example, a simple caching aspect could return a value from a cache if it has
one or invoke `proceed()` (and return that value) if it does not. Note that `proceed`
may be invoked once, many times, or not at all within the body of the around advice. All
of these are legal.
WARNING: If you declare the return type of your around advice method as `void`, `null`
will always be returned to the caller, effectively ignoring the result of any invocation
of `proceed()`. It is therefore recommended that an around advice method declare a return
type of `Object`. The advice method should typically return the value returned from an
invocation of `proceed()`, even if the underlying method has a `void` return type.
However, the advice may optionally return a cached value, a wrapped value, or some other
value depending on the use case.
The following example shows how to use around advice:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
@Aspect
public class AroundExample {
@Around("execution(* com.xyz..service.*.*(..))")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
Object retVal = pjp.proceed();
// stop stopwatch
return retVal;
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.ProceedingJoinPoint
@Aspect
class AroundExample {
@Around("execution(* com.xyz..service.*.*(..))")
fun doBasicProfiling(pjp: ProceedingJoinPoint): Any? {
// start stopwatch
val retVal = pjp.proceed()
// stop stopwatch
return retVal
}
}
----
======
[[aop-ataspectj-advice-params]]
== Advice Parameters
Spring offers fully typed advice, meaning that you declare the parameters you need in the
advice signature (as we saw earlier for the returning and throwing examples) rather than
work with `Object[]` arrays all the time. We see how to make argument and other contextual
values available to the advice body later in this section. First, we take a look at how to
write generic advice that can find out about the method the advice is currently advising.
[[aop-ataspectj-advice-params-the-joinpoint]]
=== Access to the Current `JoinPoint`
Any advice method may declare, as its first parameter, a parameter of type
`org.aspectj.lang.JoinPoint`. Note that around advice is required to declare a first
parameter of type `ProceedingJoinPoint`, which is a subclass of `JoinPoint`.
The `JoinPoint` interface provides a number of useful methods:
* `getArgs()`: Returns the method arguments.
* `getThis()`: Returns the proxy object.
* `getTarget()`: Returns the target object.
* `getSignature()`: Returns a description of the method that is being advised.
* `toString()`: Prints a useful description of the method being advised.
See the https://www.eclipse.org/aspectj/doc/released/runtime-api/org/aspectj/lang/JoinPoint.html[javadoc] for more detail.
[[aop-ataspectj-advice-params-passing]]
=== Passing Parameters to Advice
We have already seen how to bind the returned value or exception value (using after
returning and after throwing advice). To make argument values available to the advice
body, you can use the binding form of `args`. If you use a parameter name in place of a
type name in an `args` expression, the value of the corresponding argument is passed as
the parameter value when the advice is invoked. An example should make this clearer.
Suppose you want to advise the execution of DAO operations that take an `Account`
object as the first parameter, and you need access to the account in the advice body.
You could write the following:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Before("execution(* com.xyz.dao.*.*(..)) && args(account,..)")
public void validateAccount(Account account) {
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Before("execution(* com.xyz.dao.*.*(..)) && args(account,..)")
fun validateAccount(account: Account) {
// ...
}
----
======
The `args(account,..)` part of the pointcut expression serves two purposes. First, it
restricts matching to only those method executions where the method takes at least one
parameter, and the argument passed to that parameter is an instance of `Account`.
Second, it makes the actual `Account` object available to the advice through the `account`
parameter.
Another way of writing this is to declare a pointcut that "provides" the `Account`
object value when it matches a join point, and then refer to the named pointcut
from the advice. This would look as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Pointcut("execution(* com.xyz.dao.*.*(..)) && args(account,..)")
private void accountDataAccessOperation(Account account) {}
@Before("accountDataAccessOperation(account)")
public void validateAccount(Account account) {
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Pointcut("execution(* com.xyz.dao.*.*(..)) && args(account,..)")
private fun accountDataAccessOperation(account: Account) {
}
@Before("accountDataAccessOperation(account)")
fun validateAccount(account: Account) {
// ...
}
----
======
See the AspectJ programming guide for more details.
The proxy object (`this`), target object (`target`), and annotations (`@within`,
`@target`, `@annotation`, and `@args`) can all be bound in a similar fashion. The next
set of examples shows how to match the execution of methods annotated with an
`@Auditable` annotation and extract the audit code:
The following shows the definition of the `@Auditable` annotation:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Auditable {
AuditCode value();
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class Auditable(val value: AuditCode)
----
======
The following shows the advice that matches the execution of `@Auditable` methods:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Before("com.xyz.Pointcuts.publicMethod() && @annotation(auditable)") // <1>
public void audit(Auditable auditable) {
AuditCode code = auditable.value();
// ...
}
----
<1> References the `publicMethod` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-pointcuts-combining[Combining Pointcut Expressions].
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Before("com.xyz.Pointcuts.publicMethod() && @annotation(auditable)") // <1>
fun audit(auditable: Auditable) {
val code = auditable.value()
// ...
}
----
<1> References the `publicMethod` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-pointcuts-combining[Combining Pointcut Expressions].
======
[[aop-ataspectj-advice-params-generics]]
=== Advice Parameters and Generics
Spring AOP can handle generics used in class declarations and method parameters. Suppose
you have a generic type like the following:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
public interface Sample<T> {
void sampleGenericMethod(T param);
void sampleGenericCollectionMethod(Collection<T> param);
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
interface Sample<T> {
fun sampleGenericMethod(param: T)
fun sampleGenericCollectionMethod(param: Collection<T>)
}
----
======
You can restrict interception of method types to certain parameter types by
tying the advice parameter to the parameter type for which you want to intercept the method:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Before("execution(* ..Sample+.sampleGenericMethod(*)) && args(param)")
public void beforeSampleMethod(MyType param) {
// Advice implementation
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Before("execution(* ..Sample+.sampleGenericMethod(*)) && args(param)")
fun beforeSampleMethod(param: MyType) {
// Advice implementation
}
----
======
This approach does not work for generic collections. So you cannot define a
pointcut as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Before("execution(* ..Sample+.sampleGenericCollectionMethod(*)) && args(param)")
public void beforeSampleMethod(Collection<MyType> param) {
// Advice implementation
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Before("execution(* ..Sample+.sampleGenericCollectionMethod(*)) && args(param)")
fun beforeSampleMethod(param: Collection<MyType>) {
// Advice implementation
}
----
======
To make this work, we would have to inspect every element of the collection, which is not
reasonable, as we also cannot decide how to treat `null` values in general. To achieve
something similar to this, you have to type the parameter to `Collection<?>` and manually
check the type of the elements.
[[aop-ataspectj-advice-params-names]]
=== Determining Argument Names
Parameter binding in advice invocations relies on matching the names used in pointcut
expressions to the parameter names declared in advice and pointcut method signatures.
NOTE: This section uses the terms _argument_ and _parameter_ interchangeably, since
AspectJ APIs refer to parameter names as argument names.
Spring AOP uses the following `ParameterNameDiscoverer` implementations to determine
parameter names. Each discoverer will be given a chance to discover parameter names, and
the first successful discoverer wins. If none of the registered discoverers is capable
of determining parameter names, an exception will be thrown.
`AspectJAnnotationParameterNameDiscoverer` :: Uses parameter names that have been explicitly
specified by the user via the `argNames` attribute in the corresponding advice or
pointcut annotation. See xref:core/aop/ataspectj/advice.adoc#aop-ataspectj-advice-params-names-explicit[Explicit Argument Names] for details.
`KotlinReflectionParameterNameDiscoverer` :: Uses Kotlin reflection APIs to determine
parameter names. This discoverer is only used if such APIs are present on the classpath.
`StandardReflectionParameterNameDiscoverer` :: Uses the standard `java.lang.reflect.Parameter`
API to determine parameter names. Requires that code be compiled with the `-parameters`
flag for `javac`. Recommended approach on Java 8+.
`AspectJAdviceParameterNameDiscoverer` :: Deduces parameter names from the pointcut
expression, `returning`, and `throwing` clauses. See the
{api-spring-framework}/aop/aspectj/AspectJAdviceParameterNameDiscoverer.html[javadoc]
for details on the algorithm used.
[[aop-ataspectj-advice-params-names-explicit]]
=== Explicit Argument Names
@AspectJ advice and pointcut annotations have an optional `argNames` attribute that you
can use to specify the argument names of the annotated method.
[TIP]
====
If an @AspectJ aspect has been compiled by the AspectJ compiler (`ajc`) even without
debug information, you do not need to add the `argNames` attribute, since the compiler
retains the needed information.
Similarly, if an @AspectJ aspect has been compiled with `javac` using the `-parameters`
flag, you do not need to add the `argNames` attribute, since the compiler retains the
needed information.
====
The following example shows how to use the `argNames` attribute:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Before(
value = "com.xyz.Pointcuts.publicMethod() && target(bean) && @annotation(auditable)", // <1>
argNames = "bean,auditable") // <2>
public void audit(Object bean, Auditable auditable) {
AuditCode code = auditable.value();
// ... use code and bean
}
----
<1> References the `publicMethod` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-pointcuts-combining[Combining Pointcut Expressions].
<2> Declares `bean` and `auditable` as the argument names.
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Before(
value = "com.xyz.Pointcuts.publicMethod() && target(bean) && @annotation(auditable)", // <1>
argNames = "bean,auditable") // <2>
fun audit(bean: Any, auditable: Auditable) {
val code = auditable.value()
// ... use code and bean
}
----
<1> References the `publicMethod` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-pointcuts-combining[Combining Pointcut Expressions].
<2> Declares `bean` and `auditable` as the argument names.
======
If the first parameter is of type `JoinPoint`, `ProceedingJoinPoint`, or
`JoinPoint.StaticPart`, you can omit the name of the parameter from the value of the
`argNames` attribute. For example, if you modify the preceding advice to receive the join
point object, the `argNames` attribute does not need to include it:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Before(
value = "com.xyz.Pointcuts.publicMethod() && target(bean) && @annotation(auditable)", // <1>
argNames = "bean,auditable") // <2>
public void audit(JoinPoint jp, Object bean, Auditable auditable) {
AuditCode code = auditable.value();
// ... use code, bean, and jp
}
----
<1> References the `publicMethod` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-pointcuts-combining[Combining Pointcut Expressions].
<2> Declares `bean` and `auditable` as the argument names.
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Before(
value = "com.xyz.Pointcuts.publicMethod() && target(bean) && @annotation(auditable)", // <1>
argNames = "bean,auditable") // <2>
fun audit(jp: JoinPoint, bean: Any, auditable: Auditable) {
val code = auditable.value()
// ... use code, bean, and jp
}
----
<1> References the `publicMethod` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-pointcuts-combining[Combining Pointcut Expressions].
<2> Declares `bean` and `auditable` as the argument names.
======
The special treatment given to the first parameter of type `JoinPoint`,
`ProceedingJoinPoint`, or `JoinPoint.StaticPart` is particularly convenient for advice
methods that do not collect any other join point context. In such situations, you may
omit the `argNames` attribute. For example, the following advice does not need to declare
the `argNames` attribute:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Before("com.xyz.Pointcuts.publicMethod()") // <1>
public void audit(JoinPoint jp) {
// ... use jp
}
----
<1> References the `publicMethod` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-pointcuts-combining[Combining Pointcut Expressions].
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Before("com.xyz.Pointcuts.publicMethod()") // <1>
fun audit(jp: JoinPoint) {
// ... use jp
}
----
<1> References the `publicMethod` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-pointcuts-combining[Combining Pointcut Expressions].
======
[[aop-ataspectj-advice-proceeding-with-the-call]]
=== Proceeding with Arguments
We remarked earlier that we would describe how to write a `proceed` call with
arguments that works consistently across Spring AOP and AspectJ. The solution is
to ensure that the advice signature binds each of the method parameters in order.
The following example shows how to do so:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Around("execution(List<Account> find*(..)) && " +
"com.xyz.CommonPointcuts.inDataAccessLayer() && " +
"args(accountHolderNamePattern)") // <1>
public Object preProcessQueryPattern(ProceedingJoinPoint pjp,
String accountHolderNamePattern) throws Throwable {
String newPattern = preProcess(accountHolderNamePattern);
return pjp.proceed(new Object[] {newPattern});
}
----
<1> References the `inDataAccessLayer` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Around("execution(List<Account> find*(..)) && " +
"com.xyz.CommonPointcuts.inDataAccessLayer() && " +
"args(accountHolderNamePattern)") // <1>
fun preProcessQueryPattern(pjp: ProceedingJoinPoint,
accountHolderNamePattern: String): Any? {
val newPattern = preProcess(accountHolderNamePattern)
return pjp.proceed(arrayOf<Any>(newPattern))
}
----
<1> References the `inDataAccessLayer` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
======
In many cases, you do this binding anyway (as in the preceding example).
[[aop-ataspectj-advice-ordering]]
== Advice Ordering
What happens when multiple pieces of advice all want to run at the same join point?
Spring AOP follows the same precedence rules as AspectJ to determine the order of advice
execution. The highest precedence advice runs first "on the way in" (so, given two pieces
of before advice, the one with highest precedence runs first). "On the way out" from a
join point, the highest precedence advice runs last (so, given two pieces of after
advice, the one with the highest precedence will run second).
When two pieces of advice defined in different aspects both need to run at the same
join point, unless you specify otherwise, the order of execution is undefined. You can
control the order of execution by specifying precedence. This is done in the normal
Spring way by either implementing the `org.springframework.core.Ordered` interface in
the aspect class or annotating it with the `@Order` annotation. Given two aspects, the
aspect returning the lower value from `Ordered.getOrder()` (or the annotation value) has
the higher precedence.
[NOTE]
====
Each of the distinct advice types of a particular aspect is conceptually meant to apply
to the join point directly. As a consequence, an `@AfterThrowing` advice method is not
supposed to receive an exception from an accompanying `@After`/`@AfterReturning` method.
As of Spring Framework 5.2.7, advice methods defined in the same `@Aspect` class that
need to run at the same join point are assigned precedence based on their advice type in
the following order, from highest to lowest precedence: `@Around`, `@Before`, `@After`,
`@AfterReturning`, `@AfterThrowing`. Note, however, that an `@After` advice method will
effectively be invoked after any `@AfterReturning` or `@AfterThrowing` advice methods
in the same aspect, following AspectJ's "after finally advice" semantics for `@After`.
When two pieces of the same type of advice (for example, two `@After` advice methods)
defined in the same `@Aspect` class both need to run at the same join point, the ordering
is undefined (since there is no way to retrieve the source code declaration order through
reflection for javac-compiled classes). Consider collapsing such advice methods into one
advice method per join point in each `@Aspect` class or refactor the pieces of advice into
separate `@Aspect` classes that you can order at the aspect level via `Ordered` or `@Order`.
====
@@ -0,0 +1,61 @@
[[aop-aspectj-support]]
= Enabling @AspectJ Support
To use @AspectJ aspects in a Spring configuration, you need to enable Spring support for
configuring Spring AOP based on @AspectJ aspects and auto-proxying beans based on
whether or not they are advised by those aspects. By auto-proxying, we mean that, if Spring
determines that a bean is advised by one or more aspects, it automatically generates
a proxy for that bean to intercept method invocations and ensures that advice is run
as needed.
The @AspectJ support can be enabled with XML- or Java-style configuration. In either
case, you also need to ensure that AspectJ's `aspectjweaver.jar` library is on the
classpath of your application (version 1.9 or later). This library is available in the
`lib` directory of an AspectJ distribution or from the Maven Central repository.
[[aop-enable-aspectj-java]]
== Enabling @AspectJ Support with Java Configuration
To enable @AspectJ support with Java `@Configuration`, add the `@EnableAspectJAutoProxy`
annotation, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Configuration
@EnableAspectJAutoProxy
class AppConfig
----
======
[[aop-enable-aspectj-xml]]
== Enabling @AspectJ Support with XML Configuration
To enable @AspectJ support with XML-based configuration, use the `aop:aspectj-autoproxy`
element, as the following example shows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:aspectj-autoproxy/>
----
This assumes that you use schema support as described in
xref:core/appendix/xsd-schemas.adoc[XML Schema-based configuration].
See xref:core/appendix/xsd-schemas.adoc#aop[the AOP schema] for how to
import the tags in the `aop` namespace.
@@ -0,0 +1,68 @@
[[aop-at-aspectj]]
= Declaring an Aspect
With @AspectJ support enabled, any bean defined in your application context with a
class that is an @AspectJ aspect (has the `@Aspect` annotation) is automatically
detected by Spring and used to configure Spring AOP. The next two examples show the
minimal steps required for a not-very-useful aspect.
The first of the two examples shows a regular bean definition in the application context
that points to a bean class that is annotated with `@Aspect`:
[source,xml,indent=0,subs="verbatim"]
----
<bean id="myAspect" class="com.xyz.NotVeryUsefulAspect">
<!-- configure properties of the aspect here -->
</bean>
----
The second of the two examples shows the `NotVeryUsefulAspect` class definition, which is
annotated with `@Aspect`:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages",fold="none"]
----
package com.xyz;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class NotVeryUsefulAspect {
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages",fold="none"]
----
package com.xyz
import org.aspectj.lang.annotation.Aspect
@Aspect
class NotVeryUsefulAspect
----
======
Aspects (classes annotated with `@Aspect`) can have methods and fields, the same as any
other class. They can also contain pointcut, advice, and introduction (inter-type)
declarations.
.Autodetecting aspects through component scanning
NOTE: You can register aspect classes as regular beans in your Spring XML configuration,
via `@Bean` methods in `@Configuration` classes, or have Spring autodetect them through
classpath scanning -- the same as any other Spring-managed bean. However, note that the
`@Aspect` annotation is not sufficient for autodetection in the classpath. For that
purpose, you need to add a separate `@Component` annotation (or, alternatively, a custom
stereotype annotation that qualifies, as per the rules of Spring's component scanner).
.Advising aspects with other aspects?
NOTE: In Spring AOP, aspects themselves cannot be the targets of advice from other
aspects. The `@Aspect` annotation on a class marks it as an aspect and, hence, excludes
it from auto-proxying.
@@ -0,0 +1,183 @@
[[aop-ataspectj-example]]
= An AOP Example
Now that you have seen how all the constituent parts work, we can put them together to do
something useful.
The execution of business services can sometimes fail due to concurrency issues (for
example, a deadlock loser). If the operation is retried, it is likely to succeed
on the next try. For business services where it is appropriate to retry in such
conditions (idempotent operations that do not need to go back to the user for conflict
resolution), we want to transparently retry the operation to avoid the client seeing a
`PessimisticLockingFailureException`. This is a requirement that clearly cuts across
multiple services in the service layer and, hence, is ideal for implementing through an
aspect.
Because we want to retry the operation, we need to use around advice so that we can
call `proceed` multiple times. The following listing shows the basic aspect implementation:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Aspect
public class ConcurrentOperationExecutor implements Ordered {
private static final int DEFAULT_MAX_RETRIES = 2;
private int maxRetries = DEFAULT_MAX_RETRIES;
private int order = 1;
public void setMaxRetries(int maxRetries) {
this.maxRetries = maxRetries;
}
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
@Around("com.xyz.CommonPointcuts.businessService()") // <1>
public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
int numAttempts = 0;
PessimisticLockingFailureException lockFailureException;
do {
numAttempts++;
try {
return pjp.proceed();
}
catch(PessimisticLockingFailureException ex) {
lockFailureException = ex;
}
} while(numAttempts <= this.maxRetries);
throw lockFailureException;
}
}
----
<1> References the `businessService` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Aspect
class ConcurrentOperationExecutor : Ordered {
private val DEFAULT_MAX_RETRIES = 2
private var maxRetries = DEFAULT_MAX_RETRIES
private var order = 1
fun setMaxRetries(maxRetries: Int) {
this.maxRetries = maxRetries
}
override fun getOrder(): Int {
return this.order
}
fun setOrder(order: Int) {
this.order = order
}
@Around("com.xyz.CommonPointcuts.businessService()") // <1>
fun doConcurrentOperation(pjp: ProceedingJoinPoint): Any? {
var numAttempts = 0
var lockFailureException: PessimisticLockingFailureException
do {
numAttempts++
try {
return pjp.proceed()
} catch (ex: PessimisticLockingFailureException) {
lockFailureException = ex
}
} while (numAttempts <= this.maxRetries)
throw lockFailureException
}
}
----
<1> References the `businessService` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
======
Note that the aspect implements the `Ordered` interface so that we can set the precedence of
the aspect higher than the transaction advice (we want a fresh transaction each time we
retry). The `maxRetries` and `order` properties are both configured by Spring. The
main action happens in the `doConcurrentOperation` around advice. Notice that, for the
moment, we apply the retry logic to each `businessService`. We try to proceed,
and if we fail with a `PessimisticLockingFailureException`, we try again, unless
we have exhausted all of our retry attempts.
The corresponding Spring configuration follows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:aspectj-autoproxy/>
<bean id="concurrentOperationExecutor"
class="com.xyz.service.impl.ConcurrentOperationExecutor">
<property name="maxRetries" value="3"/>
<property name="order" value="100"/>
</bean>
----
To refine the aspect so that it retries only idempotent operations, we might define the following
`Idempotent` annotation:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Retention(RetentionPolicy.RUNTIME)
// marker annotation
public @interface Idempotent {
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Retention(AnnotationRetention.RUNTIME)
// marker annotation
annotation class Idempotent
----
======
We can then use the annotation to annotate the implementation of service operations. The change
to the aspect to retry only idempotent operations involves refining the pointcut
expression so that only `@Idempotent` operations match, as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Around("execution(* com.xyz..service.*.*(..)) && " +
"@annotation(com.xyz.service.Idempotent)")
public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Around("execution(* com.xyz..service.*.*(..)) && " +
"@annotation(com.xyz.service.Idempotent)")
fun doConcurrentOperation(pjp: ProceedingJoinPoint): Any? {
// ...
}
----
======
@@ -0,0 +1,65 @@
[[aop-instantiation-models]]
= Aspect Instantiation Models
NOTE: This is an advanced topic. If you are just starting out with AOP, you can safely skip
it until later.
By default, there is a single instance of each aspect within the application
context. AspectJ calls this the singleton instantiation model. It is possible to define
aspects with alternate lifecycles. Spring supports AspectJ's `perthis` and `pertarget`
instantiation models; `percflow`, `percflowbelow`, and `pertypewithin` are not currently
supported.
You can declare a `perthis` aspect by specifying a `perthis` clause in the `@Aspect`
annotation. Consider the following example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Aspect("perthis(execution(* com.xyz..service.*.*(..)))")
public class MyAspect {
private int someState;
@Before("execution(* com.xyz..service.*.*(..))")
public void recordServiceUsage() {
// ...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Aspect("perthis(execution(* com.xyz..service.*.*(..)))")
class MyAspect {
private val someState: Int = 0
@Before("execution(* com.xyz..service.*.*(..))")
fun recordServiceUsage() {
// ...
}
}
----
======
In the preceding example, the effect of the `perthis` clause is that one aspect instance
is created for each unique service object that performs a business service (each unique
object bound to `this` at join points matched by the pointcut expression). The aspect
instance is created the first time that a method is invoked on the service object. The
aspect goes out of scope when the service object goes out of scope. Before the aspect
instance is created, none of the advice within it runs. As soon as the aspect instance
has been created, the advice declared within it runs at matched join points, but only
when the service object is the one with which this aspect is associated. See the AspectJ
Programming Guide for more information on `per` clauses.
The `pertarget` instantiation model works in exactly the same way as `perthis`, but it
creates one aspect instance for each unique target object at matched join points.
@@ -0,0 +1,79 @@
[[aop-introductions]]
= Introductions
Introductions (known as inter-type declarations in AspectJ) enable an aspect to declare
that advised objects implement a given interface, and to provide an implementation of
that interface on behalf of those objects.
You can make an introduction by using the `@DeclareParents` annotation. This annotation
is used to declare that matching types have a new parent (hence the name). For example,
given an interface named `UsageTracked` and an implementation of that interface named
`DefaultUsageTracked`, the following aspect declares that all implementors of service
interfaces also implement the `UsageTracked` interface (e.g. for statistics via JMX):
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Aspect
public class UsageTracking {
@DeclareParents(value="com.xyz.service.*+", defaultImpl=DefaultUsageTracked.class)
public static UsageTracked mixin;
@Before("execution(* com.xyz..service.*.*(..)) && this(usageTracked)")
public void recordUsage(UsageTracked usageTracked) {
usageTracked.incrementUseCount();
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Aspect
class UsageTracking {
companion object {
@DeclareParents(value = "com.xyz.service.*+",
defaultImpl = DefaultUsageTracked::class)
lateinit var mixin: UsageTracked
}
@Before("execution(* com.xyz..service.*.*(..)) && this(usageTracked)")
fun recordUsage(usageTracked: UsageTracked) {
usageTracked.incrementUseCount()
}
}
----
======
The interface to be implemented is determined by the type of the annotated field. The
`value` attribute of the `@DeclareParents` annotation is an AspectJ type pattern. Any
bean of a matching type implements the `UsageTracked` interface. Note that, in the
before advice of the preceding example, service beans can be directly used as
implementations of the `UsageTracked` interface. If accessing a bean programmatically,
you would write the following:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
UsageTracked usageTracked = context.getBean("myService", UsageTracked.class);
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
val usageTracked = context.getBean("myService", UsageTracked.class)
----
======
@@ -0,0 +1,586 @@
[[aop-pointcuts]]
= Declaring a Pointcut
Pointcuts determine join points of interest and thus enable us to control
when advice runs. Spring AOP only supports method execution join points for Spring
beans, so you can think of a pointcut as matching the execution of methods on Spring
beans. A pointcut declaration has two parts: a signature comprising a name and any
parameters and a pointcut expression that determines exactly which method
executions we are interested in. In the @AspectJ annotation-style of AOP, a pointcut
signature is provided by a regular method definition, and the pointcut expression is
indicated by using the `@Pointcut` annotation (the method serving as the pointcut signature
must have a `void` return type).
An example may help make this distinction between a pointcut signature and a pointcut
expression clear. The following example defines a pointcut named `anyOldTransfer` that
matches the execution of any method named `transfer`:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Pointcut("execution(* transfer(..))") // the pointcut expression
private void anyOldTransfer() {} // the pointcut signature
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Pointcut("execution(* transfer(..))") // the pointcut expression
private fun anyOldTransfer() {} // the pointcut signature
----
======
The pointcut expression that forms the value of the `@Pointcut` annotation is a regular
AspectJ pointcut expression. For a full discussion of AspectJ's pointcut language, see
the https://www.eclipse.org/aspectj/doc/released/progguide/index.html[AspectJ
Programming Guide] (and, for extensions, the
https://www.eclipse.org/aspectj/doc/released/adk15notebook/index.html[AspectJ 5
Developer's Notebook]) or one of the books on AspectJ (such as _Eclipse AspectJ_, by Colyer
et al., or _AspectJ in Action_, by Ramnivas Laddad).
[[aop-pointcuts-designators]]
== Supported Pointcut Designators
Spring AOP supports the following AspectJ pointcut designators (PCD) for use in pointcut
expressions:
* `execution`: For matching method execution join points. This is the primary
pointcut designator to use when working with Spring AOP.
* `within`: Limits matching to join points within certain types (the execution
of a method declared within a matching type when using Spring AOP).
* `this`: Limits matching to join points (the execution of methods when using Spring
AOP) where the bean reference (Spring AOP proxy) is an instance of the given type.
* `target`: Limits matching to join points (the execution of methods when using
Spring AOP) where the target object (application object being proxied) is an instance
of the given type.
* `args`: Limits matching to join points (the execution of methods when using Spring
AOP) where the arguments are instances of the given types.
* `@target`: Limits matching to join points (the execution of methods when using
Spring AOP) where the class of the executing object has an annotation of the given type.
* `@args`: Limits matching to join points (the execution of methods when using Spring
AOP) where the runtime type of the actual arguments passed have annotations of the
given types.
* `@within`: Limits matching to join points within types that have the given
annotation (the execution of methods declared in types with the given annotation when
using Spring AOP).
* `@annotation`: Limits matching to join points where the subject of the join point
(the method being run in Spring AOP) has the given annotation.
.Other pointcut types
****
The full AspectJ pointcut language supports additional pointcut designators that are not
supported in Spring: `call`, `get`, `set`, `preinitialization`,
`staticinitialization`, `initialization`, `handler`, `adviceexecution`, `withincode`, `cflow`,
`cflowbelow`, `if`, `@this`, and `@withincode`. Use of these pointcut designators in pointcut
expressions interpreted by Spring AOP results in an `IllegalArgumentException` being
thrown.
The set of pointcut designators supported by Spring AOP may be extended in future
releases to support more of the AspectJ pointcut designators.
****
Because Spring AOP limits matching to only method execution join points, the preceding discussion
of the pointcut designators gives a narrower definition than you can find in the
AspectJ programming guide. In addition, AspectJ itself has type-based semantics and, at
an execution join point, both `this` and `target` refer to the same object: the
object executing the method. Spring AOP is a proxy-based system and differentiates
between the proxy object itself (which is bound to `this`) and the target object behind the
proxy (which is bound to `target`).
[NOTE]
====
Due to the proxy-based nature of Spring's AOP framework, calls within the target object
are, by definition, not intercepted. For JDK proxies, only public interface method
calls on the proxy can be intercepted. With CGLIB, public and protected method calls on
the proxy are intercepted (and even package-visible methods, if necessary). However,
common interactions through proxies should always be designed through public signatures.
Note that pointcut definitions are generally matched against any intercepted method.
If a pointcut is strictly meant to be public-only, even in a CGLIB proxy scenario with
potential non-public interactions through proxies, it needs to be defined accordingly.
If your interception needs include method calls or even constructors within the target
class, consider the use of Spring-driven xref:core/aop/using-aspectj.adoc#aop-aj-ltw[native AspectJ weaving] instead
of Spring's proxy-based AOP framework. This constitutes a different mode of AOP usage
with different characteristics, so be sure to make yourself familiar with weaving
before making a decision.
====
Spring AOP also supports an additional PCD named `bean`. This PCD lets you limit
the matching of join points to a particular named Spring bean or to a set of named
Spring beans (when using wildcards). The `bean` PCD has the following form:
[source,indent=0,subs="verbatim"]
----
bean(idOrNameOfBean)
----
The `idOrNameOfBean` token can be the name of any Spring bean. Limited wildcard
support that uses the `*` character is provided, so, if you establish some naming
conventions for your Spring beans, you can write a `bean` PCD expression
to select them. As is the case with other pointcut designators, the `bean` PCD can
be used with the `&&` (and), `||` (or), and `!` (negation) operators, too.
[NOTE]
====
The `bean` PCD is supported only in Spring AOP and not in
native AspectJ weaving. It is a Spring-specific extension to the standard PCDs that
AspectJ defines and is, therefore, not available for aspects declared in the `@Aspect` model.
The `bean` PCD operates at the instance level (building on the Spring bean name
concept) rather than at the type level only (to which weaving-based AOP is limited).
Instance-based pointcut designators are a special capability of Spring's
proxy-based AOP framework and its close integration with the Spring bean factory, where
it is natural and straightforward to identify specific beans by name.
====
[[aop-pointcuts-combining]]
== Combining Pointcut Expressions
You can combine pointcut expressions by using `&&,` `||` and `!`. You can also refer to
pointcut expressions by name. The following example shows three pointcut expressions:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
----
package com.xyz;
public class Pointcuts {
@Pointcut("execution(public * *(..))")
public void publicMethod() {} // <1>
@Pointcut("within(com.xyz.trading..*)")
public void inTrading() {} // <2>
@Pointcut("publicMethod() && inTrading()")
public void tradingOperation() {} // <3>
}
----
<1> `publicMethod` matches if a method execution join point represents the execution
of any public method.
<2> `inTrading` matches if a method execution is in the trading module.
<3> `tradingOperation` matches if a method execution represents any public method in the
trading module.
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
----
package com.xyz
class Pointcuts {
@Pointcut("execution(public * *(..))")
fun publicMethod() {} // <1>
@Pointcut("within(com.xyz.trading..*)")
fun inTrading() {} // <2>
@Pointcut("publicMethod() && inTrading()")
fun tradingOperation() {} // <3>
}
----
<1> `publicMethod` matches if a method execution join point represents the execution
of any public method.
<2> `inTrading` matches if a method execution is in the trading module.
<3> `tradingOperation` matches if a method execution represents any public method in the
trading module.
======
It is a best practice to build more complex pointcut expressions out of smaller _named
pointcuts_, as shown above. When referring to pointcuts by name, normal Java visibility
rules apply (you can see `private` pointcuts in the same type, `protected` pointcuts in
the hierarchy, `public` pointcuts anywhere, and so on). Visibility does not affect
pointcut matching.
[[aop-common-pointcuts]]
== Sharing Named Pointcut Definitions
When working with enterprise applications, developers often have the need to refer to
modules of the application and particular sets of operations from within several aspects.
We recommend defining a dedicated class that captures commonly used _named pointcut_
expressions for this purpose. Such a class typically resembles the following
`CommonPointcuts` example (though what you name the class is up to you):
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages",fold="none"]
----
package com.xyz;
import org.aspectj.lang.annotation.Pointcut;
public class CommonPointcuts {
/**
* A join point is in the web layer if the method is defined
* in a type in the com.xyz.web package or any sub-package
* under that.
*/
@Pointcut("within(com.xyz.web..*)")
public void inWebLayer() {}
/**
* A join point is in the service layer if the method is defined
* in a type in the com.xyz.service package or any sub-package
* under that.
*/
@Pointcut("within(com.xyz.service..*)")
public void inServiceLayer() {}
/**
* A join point is in the data access layer if the method is defined
* in a type in the com.xyz.dao package or any sub-package
* under that.
*/
@Pointcut("within(com.xyz.dao..*)")
public void inDataAccessLayer() {}
/**
* A business service is the execution of any method defined on a service
* interface. This definition assumes that interfaces are placed in the
* "service" package, and that implementation types are in sub-packages.
*
* If you group service interfaces by functional area (for example,
* in packages com.xyz.abc.service and com.xyz.def.service) then
* the pointcut expression "execution(* com.xyz..service.*.*(..))"
* could be used instead.
*
* Alternatively, you can write the expression using the 'bean'
* PCD, like so "bean(*Service)". (This assumes that you have
* named your Spring service beans in a consistent fashion.)
*/
@Pointcut("execution(* com.xyz..service.*.*(..))")
public void businessService() {}
/**
* A data access operation is the execution of any method defined on a
* DAO interface. This definition assumes that interfaces are placed in the
* "dao" package, and that implementation types are in sub-packages.
*/
@Pointcut("execution(* com.xyz.dao.*.*(..))")
public void dataAccessOperation() {}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages",fold="none"]
----
package com.xyz
import org.aspectj.lang.annotation.Pointcut
class CommonPointcuts {
/**
* A join point is in the web layer if the method is defined
* in a type in the com.xyz.web package or any sub-package
* under that.
*/
@Pointcut("within(com.xyz.web..*)")
fun inWebLayer() {}
/**
* A join point is in the service layer if the method is defined
* in a type in the com.xyz.service package or any sub-package
* under that.
*/
@Pointcut("within(com.xyz.service..*)")
fun inServiceLayer() {}
/**
* A join point is in the data access layer if the method is defined
* in a type in the com.xyz.dao package or any sub-package
* under that.
*/
@Pointcut("within(com.xyz.dao..*)")
fun inDataAccessLayer() {}
/**
* A business service is the execution of any method defined on a service
* interface. This definition assumes that interfaces are placed in the
* "service" package, and that implementation types are in sub-packages.
*
* If you group service interfaces by functional area (for example,
* in packages com.xyz.abc.service and com.xyz.def.service) then
* the pointcut expression "execution(* com.xyz..service.*.*(..))"
* could be used instead.
*
* Alternatively, you can write the expression using the 'bean'
* PCD, like so "bean(*Service)". (This assumes that you have
* named your Spring service beans in a consistent fashion.)
*/
@Pointcut("execution(* com.xyz..service.*.*(..))")
fun businessService() {}
/**
* A data access operation is the execution of any method defined on a
* DAO interface. This definition assumes that interfaces are placed in the
* "dao" package, and that implementation types are in sub-packages.
*/
@Pointcut("execution(* com.xyz.dao.*.*(..))")
fun dataAccessOperation() {}
}
----
======
You can refer to the pointcuts defined in such a class anywhere you need a pointcut
expression by referencing the fully-qualified name of the class combined with the
`@Pointcut` method's name. For example, to make the service layer transactional, you
could write the following which references the
`com.xyz.CommonPointcuts.businessService()` _named pointcut_:
[source,xml,indent=0,subs="verbatim"]
----
<aop:config>
<aop:advisor
pointcut="com.xyz.CommonPointcuts.businessService()"
advice-ref="tx-advice"/>
</aop:config>
<tx:advice id="tx-advice">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
----
The `<aop:config>` and `<aop:advisor>` elements are discussed in xref:core/aop/schema.adoc[Schema-based AOP Support]. The
transaction elements are discussed in xref:data-access/transaction.adoc[Transaction Management].
[[aop-pointcuts-examples]]
== Examples
Spring AOP users are likely to use the `execution` pointcut designator the most often.
The format of an execution expression follows:
[literal,indent=0,subs="verbatim"]
----
execution(modifiers-pattern?
ret-type-pattern
declaring-type-pattern?name-pattern(param-pattern)
throws-pattern?)
----
All parts except the returning type pattern (`ret-type-pattern` in the preceding snippet),
the name pattern, and the parameters pattern are optional. The returning type pattern determines
what the return type of the method must be in order for a join point to be matched.
`{asterisk}` is most frequently used as the returning type pattern. It matches any return
type. A fully-qualified type name matches only when the method returns the given
type. The name pattern matches the method name. You can use the `{asterisk}` wildcard as all or
part of a name pattern. If you specify a declaring type pattern,
include a trailing `.` to join it to the name pattern component.
The parameters pattern is slightly more complex: `()` matches a
method that takes no parameters, whereas `(..)` matches any number (zero or more) of parameters.
The `({asterisk})` pattern matches a method that takes one parameter of any type.
`(*,String)` matches a method that takes two parameters. The first can be of any type, while the
second must be a `String`. Consult the
https://www.eclipse.org/aspectj/doc/released/progguide/semantics-pointcuts.html[Language
Semantics] section of the AspectJ Programming Guide for more information.
The following examples show some common pointcut expressions:
* The execution of any public method:
+
[literal,indent=0,subs="verbatim"]
----
execution(public * *(..))
----
* The execution of any method with a name that begins with `set`:
+
[literal,indent=0,subs="verbatim"]
----
execution(* set*(..))
----
* The execution of any method defined by the `AccountService` interface:
+
[literal,indent=0,subs="verbatim"]
----
execution(* com.xyz.service.AccountService.*(..))
----
* The execution of any method defined in the `service` package:
+
[literal,indent=0,subs="verbatim"]
----
execution(* com.xyz.service.*.*(..))
----
* The execution of any method defined in the service package or one of its sub-packages:
+
[literal,indent=0,subs="verbatim"]
----
execution(* com.xyz.service..*.*(..))
----
* Any join point (method execution only in Spring AOP) within the service package:
+
[literal,indent=0,subs="verbatim"]
----
within(com.xyz.service.*)
----
* Any join point (method execution only in Spring AOP) within the service package or one of its
sub-packages:
+
[literal,indent=0,subs="verbatim"]
----
within(com.xyz.service..*)
----
* Any join point (method execution only in Spring AOP) where the proxy implements the
`AccountService` interface:
+
[literal,indent=0,subs="verbatim"]
----
this(com.xyz.service.AccountService)
----
+
NOTE: `this` is more commonly used in a binding form. See the section on xref:core/aop/ataspectj/advice.adoc[Declaring Advice]
for how to make the proxy object available in the advice body.
* Any join point (method execution only in Spring AOP) where the target object
implements the `AccountService` interface:
+
[literal,indent=0,subs="verbatim"]
----
target(com.xyz.service.AccountService)
----
+
NOTE: `target` is more commonly used in a binding form. See the xref:core/aop/ataspectj/advice.adoc[Declaring Advice] section
for how to make the target object available in the advice body.
* Any join point (method execution only in Spring AOP) that takes a single parameter
and where the argument passed at runtime is `Serializable`:
+
[literal,indent=0,subs="verbatim"]
----
args(java.io.Serializable)
----
+
NOTE: `args` is more commonly used in a binding form. See the xref:core/aop/ataspectj/advice.adoc[Declaring Advice] section
for how to make the method arguments available in the advice body.
+
Note that the pointcut given in this example is different from `execution(*
*(java.io.Serializable))`. The args version matches if the argument passed at runtime is
`Serializable`, and the execution version matches if the method signature declares a single
parameter of type `Serializable`.
* Any join point (method execution only in Spring AOP) where the target object has a
`@Transactional` annotation:
+
[literal,indent=0,subs="verbatim"]
----
@target(org.springframework.transaction.annotation.Transactional)
----
+
NOTE: You can also use `@target` in a binding form. See the xref:core/aop/ataspectj/advice.adoc[Declaring Advice] section for
how to make the annotation object available in the advice body.
* Any join point (method execution only in Spring AOP) where the declared type of the
target object has an `@Transactional` annotation:
+
[literal,indent=0,subs="verbatim"]
----
@within(org.springframework.transaction.annotation.Transactional)
----
+
NOTE: You can also use `@within` in a binding form. See the xref:core/aop/ataspectj/advice.adoc[Declaring Advice] section for
how to make the annotation object available in the advice body.
* Any join point (method execution only in Spring AOP) where the executing method has an
`@Transactional` annotation:
+
[literal,indent=0,subs="verbatim"]
----
@annotation(org.springframework.transaction.annotation.Transactional)
----
+
NOTE: You can also use `@annotation` in a binding form. See the xref:core/aop/ataspectj/advice.adoc[Declaring Advice] section
for how to make the annotation object available in the advice body.
* Any join point (method execution only in Spring AOP) which takes a single parameter,
and where the runtime type of the argument passed has the `@Classified` annotation:
+
[literal,indent=0,subs="verbatim"]
----
@args(com.xyz.security.Classified)
----
+
NOTE: You can also use `@args` in a binding form. See the xref:core/aop/ataspectj/advice.adoc[Declaring Advice] section
how to make the annotation object(s) available in the advice body.
* Any join point (method execution only in Spring AOP) on a Spring bean named
`tradeService`:
+
[literal,indent=0,subs="verbatim"]
----
bean(tradeService)
----
* Any join point (method execution only in Spring AOP) on Spring beans having names that
match the wildcard expression `*Service`:
+
[literal,indent=0,subs="verbatim"]
----
bean(*Service)
----
[[writing-good-pointcuts]]
== Writing Good Pointcuts
During compilation, AspectJ processes pointcuts in order to optimize matching
performance. Examining code and determining if each join point matches (statically or
dynamically) a given pointcut is a costly process. (A dynamic match means the match
cannot be fully determined from static analysis and that a test is placed in the code to
determine if there is an actual match when the code is running). On first encountering a
pointcut declaration, AspectJ rewrites it into an optimal form for the matching
process. What does this mean? Basically, pointcuts are rewritten in DNF (Disjunctive
Normal Form) and the components of the pointcut are sorted such that those components
that are cheaper to evaluate are checked first. This means you do not have to worry
about understanding the performance of various pointcut designators and may supply them
in any order in a pointcut declaration.
However, AspectJ can work only with what it is told. For optimal performance of
matching, you should think about what you are trying to achieve and narrow the search
space for matches as much as possible in the definition. The existing designators
naturally fall into one of three groups: kinded, scoping, and contextual:
* Kinded designators select a particular kind of join point:
`execution`, `get`, `set`, `call`, and `handler`.
* Scoping designators select a group of join points of interest
(probably of many kinds): `within` and `withincode`
* Contextual designators match (and optionally bind) based on context:
`this`, `target`, and `@annotation`
A well written pointcut should include at least the first two types (kinded and
scoping). You can include the contextual designators to match based on
join point context or bind that context for use in the advice. Supplying only a
kinded designator or only a contextual designator works but could affect weaving
performance (time and memory used), due to extra processing and analysis. Scoping
designators are very fast to match, and using them means AspectJ can very quickly
dismiss groups of join points that should not be further processed. A good
pointcut should always include one if possible.
@@ -0,0 +1,113 @@
[[aop-choosing]]
= Choosing which AOP Declaration Style to Use
Once you have decided that an aspect is the best approach for implementing a given
requirement, how do you decide between using Spring AOP or AspectJ and between the
Aspect language (code) style, the @AspectJ annotation style, or the Spring XML style? These
decisions are influenced by a number of factors including application requirements,
development tools, and team familiarity with AOP.
[[aop-spring-or-aspectj]]
== Spring AOP or Full AspectJ?
Use the simplest thing that can work. Spring AOP is simpler than using full AspectJ, as
there is no requirement to introduce the AspectJ compiler / weaver into your development
and build processes. If you only need to advise the execution of operations on Spring
beans, Spring AOP is the right choice. If you need to advise objects not managed by
the Spring container (such as domain objects, typically), you need to use
AspectJ. You also need to use AspectJ if you wish to advise join points other than
simple method executions (for example, field get or set join points and so on).
When you use AspectJ, you have the choice of the AspectJ language syntax (also known as
the "code style") or the @AspectJ annotation style. If aspects play a large
role in your design, and you are able to use the https://www.eclipse.org/ajdt/[AspectJ
Development Tools (AJDT)] plugin for Eclipse, the AspectJ language syntax is the
preferred option. It is cleaner and simpler because the language was purposefully
designed for writing aspects. If you do not use Eclipse or have only a few aspects
that do not play a major role in your application, you may want to consider using
the @AspectJ style, sticking with regular Java compilation in your IDE, and adding
an aspect weaving phase to your build script.
[[aop-ataspectj-or-xml]]
== @AspectJ or XML for Spring AOP?
If you have chosen to use Spring AOP, you have a choice of @AspectJ or XML style.
There are various tradeoffs to consider.
The XML style may be most familiar to existing Spring users, and it is backed by genuine
POJOs. When using AOP as a tool to configure enterprise services, XML can be a good
choice (a good test is whether you consider the pointcut expression to be a part of your
configuration that you might want to change independently). With the XML style, it is
arguably clearer from your configuration which aspects are present in the system.
The XML style has two disadvantages. First, it does not fully encapsulate the
implementation of the requirement it addresses in a single place. The DRY principle says
that there should be a single, unambiguous, authoritative representation of any piece of
knowledge within a system. When using the XML style, the knowledge of how a requirement
is implemented is split across the declaration of the backing bean class and the XML in
the configuration file. When you use the @AspectJ style, this information is encapsulated
in a single module: the aspect. Secondly, the XML style is slightly more limited in what
it can express than the @AspectJ style: Only the "singleton" aspect instantiation model
is supported, and it is not possible to combine named pointcuts declared in XML.
For example, in the @AspectJ style you can write something like the following:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Pointcut("execution(* get*())")
public void propertyAccess() {}
@Pointcut("execution(com.xyz.Account+ *(..))")
public void operationReturningAnAccount() {}
@Pointcut("propertyAccess() && operationReturningAnAccount()")
public void accountPropertyAccess() {}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Pointcut("execution(* get*())")
fun propertyAccess() {}
@Pointcut("execution(com.xyz.Account+ *(..))")
fun operationReturningAnAccount() {}
@Pointcut("propertyAccess() && operationReturningAnAccount()")
fun accountPropertyAccess() {}
----
======
In the XML style you can declare the first two pointcuts:
[source,xml,indent=0,subs="verbatim"]
----
<aop:pointcut id="propertyAccess"
expression="execution(* get*())"/>
<aop:pointcut id="operationReturningAnAccount"
expression="execution(com.xyz.Account+ *(..))"/>
----
The downside of the XML approach is that you cannot define the
`accountPropertyAccess` pointcut by combining these definitions.
The @AspectJ style supports additional instantiation models and richer pointcut
composition. It has the advantage of keeping the aspect as a modular unit. It also has
the advantage that the @AspectJ aspects can be understood (and thus consumed) both by
Spring AOP and by AspectJ. So, if you later decide you need the capabilities of AspectJ
to implement additional requirements, you can easily migrate to a classic AspectJ setup.
In general, the Spring team prefers the @AspectJ style for custom aspects beyond simple
configuration of enterprise services.
@@ -0,0 +1,79 @@
[[aop-introduction-defn]]
= AOP Concepts
Let us begin by defining some central AOP concepts and terminology. These terms are not
Spring-specific. Unfortunately, AOP terminology is not particularly intuitive.
However, it would be even more confusing if Spring used its own terminology.
* Aspect: A modularization of a concern that cuts across multiple classes.
Transaction management is a good example of a crosscutting concern in enterprise Java
applications. In Spring AOP, aspects are implemented by using regular classes
(the xref:core/aop/schema.adoc[schema-based approach]) or regular classes annotated with the
`@Aspect` annotation (the xref:core/aop/ataspectj.adoc[@AspectJ style]).
* Join point: A point during the execution of a program, such as the execution of a
method or the handling of an exception. In Spring AOP, a join point always
represents a method execution.
* Advice: Action taken by an aspect at a particular join point. Different types of
advice include "around", "before", and "after" advice. (Advice types are discussed
later.) Many AOP frameworks, including Spring, model an advice as an interceptor and
maintain a chain of interceptors around the join point.
* Pointcut: A predicate that matches join points. Advice is associated with a
pointcut expression and runs at any join point matched by the pointcut (for example,
the execution of a method with a certain name). The concept of join points as matched
by pointcut expressions is central to AOP, and Spring uses the AspectJ pointcut
expression language by default.
* Introduction: Declaring additional methods or fields on behalf of a type. Spring
AOP lets you introduce new interfaces (and a corresponding implementation) to any
advised object. For example, you could use an introduction to make a bean implement an
`IsModified` interface, to simplify caching. (An introduction is known as an
inter-type declaration in the AspectJ community.)
* Target object: An object being advised by one or more aspects. Also referred to as
the "advised object". Since Spring AOP is implemented by using runtime proxies, this
object is always a proxied object.
* AOP proxy: An object created by the AOP framework in order to implement the aspect
contracts (advise method executions and so on). In the Spring Framework, an AOP proxy
is a JDK dynamic proxy or a CGLIB proxy.
* Weaving: linking aspects with other application types or objects to create an
advised object. This can be done at compile time (using the AspectJ compiler, for
example), load time, or at runtime. Spring AOP, like other pure Java AOP frameworks,
performs weaving at runtime.
Spring AOP includes the following types of advice:
* Before advice: Advice that runs before a join point but that does not have
the ability to prevent execution flow proceeding to the join point (unless it throws
an exception).
* After returning advice: Advice to be run after a join point completes
normally (for example, if a method returns without throwing an exception).
* After throwing advice: Advice to be run if a method exits by throwing an
exception.
* After (finally) advice: Advice to be run regardless of the means by which a
join point exits (normal or exceptional return).
* Around advice: Advice that surrounds a join point such as a method invocation.
This is the most powerful kind of advice. Around advice can perform custom behavior
before and after the method invocation. It is also responsible for choosing whether to
proceed to the join point or to shortcut the advised method execution by returning its
own return value or throwing an exception.
Around advice is the most general kind of advice. Since Spring AOP, like AspectJ,
provides a full range of advice types, we recommend that you use the least powerful
advice type that can implement the required behavior. For example, if you need only to
update a cache with the return value of a method, you are better off implementing an
after returning advice than an around advice, although an around advice can accomplish
the same thing. Using the most specific advice type provides a simpler programming model
with less potential for errors. For example, you do not need to invoke the `proceed()`
method on the `JoinPoint` used for around advice, and, hence, you cannot fail to invoke it.
All advice parameters are statically typed so that you work with advice parameters of
the appropriate type (e.g. the type of the return value from a method execution) rather
than `Object` arrays.
The concept of join points matched by pointcuts is the key to AOP, which distinguishes
it from older technologies offering only interception. Pointcuts enable advice to be
targeted independently of the object-oriented hierarchy. For example, you can apply an
around advice providing declarative transaction management to a set of methods that span
multiple objects (such as all business operations in the service layer).
@@ -0,0 +1,22 @@
[[aop-introduction-proxies]]
= AOP Proxies
:page-section-summary-toc: 1
Spring AOP defaults to using standard JDK dynamic proxies for AOP proxies. This
enables any interface (or set of interfaces) to be proxied.
Spring AOP can also use CGLIB proxies. This is necessary to proxy classes rather than
interfaces. By default, CGLIB is used if a business object does not implement an
interface. As it is good practice to program to interfaces rather than classes, business
classes normally implement one or more business interfaces. It is possible to
xref:core/aop/proxying.adoc[force the use of CGLIB], in those (hopefully rare) cases where you
need to advise a method that is not declared on an interface or where you need to
pass a proxied object to a method as a concrete type.
It is important to grasp the fact that Spring AOP is proxy-based. See
xref:core/aop/proxying.adoc#aop-understanding-aop-proxies[Understanding AOP Proxies] for a thorough examination of exactly what this
implementation detail actually means.
@@ -0,0 +1,61 @@
[[aop-introduction-spring-defn]]
= Spring AOP Capabilities and Goals
Spring AOP is implemented in pure Java. There is no need for a special compilation
process. Spring AOP does not need to control the class loader hierarchy and is thus
suitable for use in a servlet container or application server.
Spring AOP currently supports only method execution join points (advising the execution
of methods on Spring beans). Field interception is not implemented, although support for
field interception could be added without breaking the core Spring AOP APIs. If you need
to advise field access and update join points, consider a language such as AspectJ.
Spring AOP's approach to AOP differs from that of most other AOP frameworks. The aim is
not to provide the most complete AOP implementation (although Spring AOP is quite
capable). Rather, the aim is to provide a close integration between AOP implementation and
Spring IoC, to help solve common problems in enterprise applications.
Thus, for example, the Spring Framework's AOP functionality is normally used in
conjunction with the Spring IoC container. Aspects are configured by using normal bean
definition syntax (although this allows powerful "auto-proxying" capabilities). This is a
crucial difference from other AOP implementations. You cannot do some things
easily or efficiently with Spring AOP, such as advise very fine-grained objects (typically,
domain objects). AspectJ is the best choice in such cases. However, our
experience is that Spring AOP provides an excellent solution to most problems in
enterprise Java applications that are amenable to AOP.
Spring AOP never strives to compete with AspectJ to provide a comprehensive AOP
solution. We believe that both proxy-based frameworks such as Spring AOP and full-blown
frameworks such as AspectJ are valuable and that they are complementary, rather than in
competition. Spring seamlessly integrates Spring AOP and IoC with AspectJ, to enable
all uses of AOP within a consistent Spring-based application
architecture. This integration does not affect the Spring AOP API or the AOP Alliance
API. Spring AOP remains backward-compatible. See xref:core/aop-api.adoc[the following chapter]
for a discussion of the Spring AOP APIs.
[NOTE]
====
One of the central tenets of the Spring Framework is that of non-invasiveness. This
is the idea that you should not be forced to introduce framework-specific classes and
interfaces into your business or domain model. However, in some places, the Spring Framework
does give you the option to introduce Spring Framework-specific dependencies into your
codebase. The rationale in giving you such options is because, in certain scenarios, it
might be just plain easier to read or code some specific piece of functionality in such
a way. However, the Spring Framework (almost) always offers you the choice: You have the
freedom to make an informed decision as to which option best suits your particular use
case or scenario.
One such choice that is relevant to this chapter is that of which AOP framework (and
which AOP style) to choose. You have the choice of AspectJ, Spring AOP, or both. You
also have the choice of either the @AspectJ annotation-style approach or the Spring XML
configuration-style approach. The fact that this chapter chooses to introduce the
@AspectJ-style approach first should not be taken as an indication that the Spring team
favors the @AspectJ annotation-style approach over the Spring XML configuration-style.
See xref:core/aop/choosing.adoc[Choosing which AOP Declaration Style to Use] for a more complete discussion of the advantages and disadvantages of
each style.
====
@@ -0,0 +1,12 @@
[[aop-mixing-styles]]
= Mixing Aspect Types
:page-section-summary-toc: 1
It is perfectly possible to mix @AspectJ style aspects by using the auto-proxying support,
schema-defined `<aop:aspect>` aspects, `<aop:advisor>` declared advisors, and even proxies
and interceptors in other styles in the same configuration. All of these are implemented
by using the same underlying support mechanism and can co-exist without any difficulty.
@@ -0,0 +1,281 @@
[[aop-proxying]]
= Proxying Mechanisms
Spring AOP uses either JDK dynamic proxies or CGLIB to create the proxy for a given
target object. JDK dynamic proxies are built into the JDK, whereas CGLIB is a common
open-source class definition library (repackaged into `spring-core`).
If the target object to be proxied implements at least one interface, a JDK dynamic
proxy is used. All of the interfaces implemented by the target type are proxied.
If the target object does not implement any interfaces, a CGLIB proxy is created.
If you want to force the use of CGLIB proxying (for example, to proxy every method
defined for the target object, not only those implemented by its interfaces),
you can do so. However, you should consider the following issues:
* With CGLIB, `final` methods cannot be advised, as they cannot be overridden in
runtime-generated subclasses.
* As of Spring 4.0, the constructor of your proxied object is NOT called twice anymore,
since the CGLIB proxy instance is created through Objenesis. Only if your JVM does
not allow for constructor bypassing, you might see double invocations and
corresponding debug log entries from Spring's AOP support.
To force the use of CGLIB proxies, set the value of the `proxy-target-class` attribute
of the `<aop:config>` element to true, as follows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:config proxy-target-class="true">
<!-- other beans defined here... -->
</aop:config>
----
To force CGLIB proxying when you use the @AspectJ auto-proxy support, set the
`proxy-target-class` attribute of the `<aop:aspectj-autoproxy>` element to `true`,
as follows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:aspectj-autoproxy proxy-target-class="true"/>
----
[NOTE]
====
Multiple `<aop:config/>` sections are collapsed into a single unified auto-proxy creator
at runtime, which applies the _strongest_ proxy settings that any of the
`<aop:config/>` sections (typically from different XML bean definition files) specified.
This also applies to the `<tx:annotation-driven/>` and `<aop:aspectj-autoproxy/>`
elements.
To be clear, using `proxy-target-class="true"` on `<tx:annotation-driven/>`,
`<aop:aspectj-autoproxy/>`, or `<aop:config/>` elements forces the use of CGLIB
proxies _for all three of them_.
====
[[aop-understanding-aop-proxies]]
== Understanding AOP Proxies
Spring AOP is proxy-based. It is vitally important that you grasp the semantics of
what that last statement actually means before you write your own aspects or use any of
the Spring AOP-based aspects supplied with the Spring Framework.
Consider first the scenario where you have a plain-vanilla, un-proxied,
nothing-special-about-it, straight object reference, as the following
code snippet shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
public class SimplePojo implements Pojo {
public void foo() {
// this next method invocation is a direct call on the 'this' reference
this.bar();
}
public void bar() {
// some logic...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
class SimplePojo : Pojo {
fun foo() {
// this next method invocation is a direct call on the 'this' reference
this.bar()
}
fun bar() {
// some logic...
}
}
----
======
If you invoke a method on an object reference, the method is invoked directly on
that object reference, as the following image and listing show:
image::aop-proxy-plain-pojo-call.png[]
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
public class Main {
public static void main(String[] args) {
Pojo pojo = new SimplePojo();
// this is a direct method call on the 'pojo' reference
pojo.foo();
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
fun main() {
val pojo = SimplePojo()
// this is a direct method call on the 'pojo' reference
pojo.foo()
}
----
======
Things change slightly when the reference that client code has is a proxy. Consider the
following diagram and code snippet:
image::aop-proxy-call.png[]
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
public class Main {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice(new RetryAdvice());
Pojo pojo = (Pojo) factory.getProxy();
// this is a method call on the proxy!
pojo.foo();
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
fun main() {
val factory = ProxyFactory(SimplePojo())
factory.addInterface(Pojo::class.java)
factory.addAdvice(RetryAdvice())
val pojo = factory.proxy as Pojo
// this is a method call on the proxy!
pojo.foo()
}
----
======
The key thing to understand here is that the client code inside the `main(..)` method
of the `Main` class has a reference to the proxy. This means that method calls on that
object reference are calls on the proxy. As a result, the proxy can delegate to all of
the interceptors (advice) that are relevant to that particular method call. However,
once the call has finally reached the target object (the `SimplePojo` reference in
this case), any method calls that it may make on itself, such as `this.bar()` or
`this.foo()`, are going to be invoked against the `this` reference, and not the proxy.
This has important implications. It means that self-invocation is not going to result
in the advice associated with a method invocation getting a chance to run.
Okay, so what is to be done about this? The best approach (the term "best" is used
loosely here) is to refactor your code such that the self-invocation does not happen.
This does entail some work on your part, but it is the best, least-invasive approach.
The next approach is absolutely horrendous, and we hesitate to point it out, precisely
because it is so horrendous. You can (painful as it is to us) totally tie the logic
within your class to Spring AOP, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
public class SimplePojo implements Pojo {
public void foo() {
// this works, but... gah!
((Pojo) AopContext.currentProxy()).bar();
}
public void bar() {
// some logic...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
class SimplePojo : Pojo {
fun foo() {
// this works, but... gah!
(AopContext.currentProxy() as Pojo).bar()
}
fun bar() {
// some logic...
}
}
----
======
This totally couples your code to Spring AOP, and it makes the class itself aware of
the fact that it is being used in an AOP context, which flies in the face of AOP. It
also requires some additional configuration when the proxy is being created, as the
following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
public class Main {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice(new RetryAdvice());
factory.setExposeProxy(true);
Pojo pojo = (Pojo) factory.getProxy();
// this is a method call on the proxy!
pojo.foo();
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
fun main() {
val factory = ProxyFactory(SimplePojo())
factory.addInterface(Pojo::class.java)
factory.addAdvice(RetryAdvice())
factory.isExposeProxy = true
val pojo = factory.proxy as Pojo
// this is a method call on the proxy!
pojo.foo()
}
----
======
Finally, it must be noted that AspectJ does not have this self-invocation issue because
it is not a proxy-based AOP framework.
@@ -0,0 +1,12 @@
[[aop-resources]]
= Further Resources
:page-section-summary-toc: 1
More information on AspectJ can be found on the https://www.eclipse.org/aspectj[AspectJ website].
_Eclipse AspectJ_ by Adrian Colyer et. al. (Addison-Wesley, 2005) provides a
comprehensive introduction and reference for the AspectJ language.
_AspectJ in Action_, Second Edition by Ramnivas Laddad (Manning, 2009) comes highly
recommended. The focus of the book is on AspectJ, but a lot of general AOP themes are
explored (in some depth).
@@ -0,0 +1,987 @@
[[aop-schema]]
= Schema-based AOP Support
If you prefer an XML-based format, Spring also offers support for defining aspects
using the `aop` namespace tags. The exact same pointcut expressions and advice kinds
as when using the @AspectJ style are supported. Hence, in this section we focus on
that syntax and refer the reader to the discussion in the previous section
(xref:core/aop/ataspectj.adoc[@AspectJ support]) for an understanding of writing pointcut expressions and the binding
of advice parameters.
To use the aop namespace tags described in this section, you need to import the
`spring-aop` schema, as described in xref:core/appendix/xsd-schemas.adoc[XML Schema-based configuration]
. See xref:core/appendix/xsd-schemas.adoc#aop[the AOP schema]
for how to import the tags in the `aop` namespace.
Within your Spring configurations, all aspect and advisor elements must be placed within
an `<aop:config>` element (you can have more than one `<aop:config>` element in an
application context configuration). An `<aop:config>` element can contain pointcut,
advisor, and aspect elements (note that these must be declared in that order).
WARNING: The `<aop:config>` style of configuration makes heavy use of Spring's
xref:core/aop-api/autoproxy.adoc[auto-proxying] mechanism. This can cause issues (such as advice
not being woven) if you already use explicit auto-proxying through the use of
`BeanNameAutoProxyCreator` or something similar. The recommended usage pattern is to
use either only the `<aop:config>` style or only the `AutoProxyCreator` style and
never mix them.
[[aop-schema-declaring-an-aspect]]
== Declaring an Aspect
When you use the schema support, an aspect is a regular Java object defined as a bean in
your Spring application context. The state and behavior are captured in the fields and
methods of the object, and the pointcut and advice information are captured in the XML.
You can declare an aspect by using the `<aop:aspect>` element, and reference the backing bean
by using the `ref` attribute, as the following example shows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
...
</aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>
----
The bean that backs the aspect (`aBean` in this case) can of course be configured and
dependency injected just like any other Spring bean.
[[aop-schema-pointcuts]]
== Declaring a Pointcut
You can declare a _named pointcut_ inside an `<aop:config>` element, letting the pointcut
definition be shared across several aspects and advisors.
A pointcut that represents the execution of any business service in the service layer can
be defined as follows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:config>
<aop:pointcut id="businessService"
expression="execution(* com.xyz.service.*.*(..))" />
</aop:config>
----
Note that the pointcut expression itself uses the same AspectJ pointcut expression
language as described in xref:core/aop/ataspectj.adoc[@AspectJ support]. If you use the schema based declaration
style, you can also refer to _named pointcuts_ defined in `@Aspect` types within the
pointcut expression. Thus, another way of defining the above pointcut would be as follows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:config>
<aop:pointcut id="businessService"
expression="com.xyz.CommonPointcuts.businessService()" /> <1>
</aop:config>
----
<1> References the `businessService` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
Declaring a pointcut _inside_ an aspect is very similar to declaring a top-level pointcut,
as the following example shows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
<aop:pointcut id="businessService"
expression="execution(* com.xyz.service.*.*(..))"/>
...
</aop:aspect>
</aop:config>
----
In much the same way as an @AspectJ aspect, pointcuts declared by using the schema based
definition style can collect join point context. For example, the following pointcut
collects the `this` object as the join point context and passes it to the advice:
[source,xml,indent=0,subs="verbatim"]
----
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
<aop:pointcut id="businessService"
expression="execution(* com.xyz.service.*.*(..)) &amp;&amp; this(service)"/>
<aop:before pointcut-ref="businessService" method="monitor"/>
...
</aop:aspect>
</aop:config>
----
The advice must be declared to receive the collected join point context by including
parameters of the matching names, as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
public void monitor(Object service) {
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
fun monitor(service: Any) {
// ...
}
----
======
When combining pointcut sub-expressions, `+&amp;&amp;+` is awkward within an XML
document, so you can use the `and`, `or`, and `not` keywords in place of `+&amp;&amp;+`,
`||`, and `!`, respectively. For example, the previous pointcut can be better written as
follows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
<aop:pointcut id="businessService"
expression="execution(* com.xyz.service.*.*(..)) and this(service)"/>
<aop:before pointcut-ref="businessService" method="monitor"/>
...
</aop:aspect>
</aop:config>
----
Note that pointcuts defined in this way are referred to by their XML `id` and cannot be
used as named pointcuts to form composite pointcuts. The named pointcut support in the
schema-based definition style is thus more limited than that offered by the @AspectJ
style.
[[aop-schema-advice]]
== Declaring Advice
The schema-based AOP support uses the same five kinds of advice as the @AspectJ style, and they have
exactly the same semantics.
[[aop-schema-advice-before]]
=== Before Advice
Before advice runs before a matched method execution. It is declared inside an
`<aop:aspect>` by using the `<aop:before>` element, as the following example shows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:aspect id="beforeExample" ref="aBean">
<aop:before
pointcut-ref="dataAccessOperation"
method="doAccessCheck"/>
...
</aop:aspect>
----
In the example above, `dataAccessOperation` is the `id` of a _named pointcut_ defined at
the top (`<aop:config>`) level (see xref:core/aop/schema.adoc#aop-schema-pointcuts[Declaring a Pointcut]).
NOTE: As we noted in the discussion of the @AspectJ style, using _named pointcuts_ can
significantly improve the readability of your code. See xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions] for
details.
To define the pointcut inline instead, replace the `pointcut-ref` attribute with a
`pointcut` attribute, as follows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:aspect id="beforeExample" ref="aBean">
<aop:before
pointcut="execution(* com.xyz.dao.*.*(..))"
method="doAccessCheck"/>
...
</aop:aspect>
----
The `method` attribute identifies a method (`doAccessCheck`) that provides the body of
the advice. This method must be defined for the bean referenced by the aspect element
that contains the advice. Before a data access operation is performed (a method execution
join point matched by the pointcut expression), the `doAccessCheck` method on the aspect
bean is invoked.
[[aop-schema-advice-after-returning]]
=== After Returning Advice
After returning advice runs when a matched method execution completes normally. It is
declared inside an `<aop:aspect>` in the same way as before advice. The following example
shows how to declare it:
[source,xml,indent=0,subs="verbatim"]
----
<aop:aspect id="afterReturningExample" ref="aBean">
<aop:after-returning
pointcut="execution(* com.xyz.dao.*.*(..))"
method="doAccessCheck"/>
...
</aop:aspect>
----
As in the @AspectJ style, you can get the return value within the advice body.
To do so, use the `returning` attribute to specify the name of the parameter to which
the return value should be passed, as the following example shows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:aspect id="afterReturningExample" ref="aBean">
<aop:after-returning
pointcut="execution(* com.xyz.dao.*.*(..))"
returning="retVal"
method="doAccessCheck"/>
...
</aop:aspect>
----
The `doAccessCheck` method must declare a parameter named `retVal`. The type of this
parameter constrains matching in the same way as described for `@AfterReturning`. For
example, you can declare the method signature as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
public void doAccessCheck(Object retVal) {...
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
fun doAccessCheck(retVal: Any) {...
----
======
[[aop-schema-advice-after-throwing]]
=== After Throwing Advice
After throwing advice runs when a matched method execution exits by throwing an
exception. It is declared inside an `<aop:aspect>` by using the `after-throwing` element,
as the following example shows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:aspect id="afterThrowingExample" ref="aBean">
<aop:after-throwing
pointcut="execution(* com.xyz.dao.*.*(..))"
method="doRecoveryActions"/>
...
</aop:aspect>
----
As in the @AspectJ style, you can get the thrown exception within the advice body.
To do so, use the `throwing` attribute to specify the name of the parameter to
which the exception should be passed as the following example shows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:aspect id="afterThrowingExample" ref="aBean">
<aop:after-throwing
pointcut="execution(* com.xyz.dao.*.*(..))"
throwing="dataAccessEx"
method="doRecoveryActions"/>
...
</aop:aspect>
----
The `doRecoveryActions` method must declare a parameter named `dataAccessEx`.
The type of this parameter constrains matching in the same way as described for
`@AfterThrowing`. For example, the method signature may be declared as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
public void doRecoveryActions(DataAccessException dataAccessEx) {...
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
fun doRecoveryActions(dataAccessEx: DataAccessException) {...
----
======
[[aop-schema-advice-after-finally]]
=== After (Finally) Advice
After (finally) advice runs no matter how a matched method execution exits.
You can declare it by using the `after` element, as the following example shows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:aspect id="afterFinallyExample" ref="aBean">
<aop:after
pointcut="execution(* com.xyz.dao.*.*(..))"
method="doReleaseLock"/>
...
</aop:aspect>
----
[[aop-schema-advice-around]]
=== Around Advice
The last kind of advice is _around_ advice. Around advice runs "around" a matched
method's execution. It has the opportunity to do work both before and after the method
runs and to determine when, how, and even if the method actually gets to run at all.
Around advice is often used if you need to share state before and after a method
execution in a thread-safe manner for example, starting and stopping a timer.
[TIP]
====
Always use the least powerful form of advice that meets your requirements.
For example, do not use _around_ advice if _before_ advice is sufficient for your needs.
====
You can declare around advice by using the `aop:around` element. The advice method should
declare `Object` as its return type, and the first parameter of the method must be of
type `ProceedingJoinPoint`. Within the body of the advice method, you must invoke
`proceed()` on the `ProceedingJoinPoint` in order for the underlying method to run.
Invoking `proceed()` without arguments will result in the caller's original arguments
being supplied to the underlying method when it is invoked. For advanced use cases, there
is an overloaded variant of the `proceed()` method which accepts an array of arguments
(`Object[]`). The values in the array will be used as the arguments to the underlying
method when it is invoked. See xref:core/aop/ataspectj/advice.adoc#aop-ataspectj-around-advice[Around Advice] for notes on calling
`proceed` with an `Object[]`.
The following example shows how to declare around advice in XML:
[source,xml,indent=0,subs="verbatim"]
----
<aop:aspect id="aroundExample" ref="aBean">
<aop:around
pointcut="execution(* com.xyz.service.*.*(..))"
method="doBasicProfiling"/>
...
</aop:aspect>
----
The implementation of the `doBasicProfiling` advice can be exactly the same as in the
@AspectJ example (minus the annotation, of course), as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
Object retVal = pjp.proceed();
// stop stopwatch
return retVal;
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
fun doBasicProfiling(pjp: ProceedingJoinPoint): Any? {
// start stopwatch
val retVal = pjp.proceed()
// stop stopwatch
return pjp.proceed()
}
----
======
[[aop-schema-params]]
=== Advice Parameters
The schema-based declaration style supports fully typed advice in the same way as
described for the @AspectJ support -- by matching pointcut parameters by name against
advice method parameters. See xref:core/aop/ataspectj/advice.adoc#aop-ataspectj-advice-params[Advice Parameters] for details. If you wish
to explicitly specify argument names for the advice methods (not relying on the
detection strategies previously described), you can do so by using the `arg-names`
attribute of the advice element, which is treated in the same manner as the `argNames`
attribute in an advice annotation (as described in xref:core/aop/ataspectj/advice.adoc#aop-ataspectj-advice-params-names[Determining Argument Names]).
The following example shows how to specify an argument name in XML:
[source,xml,indent=0,subs="verbatim"]
----
<aop:before
pointcut="com.xyz.Pointcuts.publicMethod() and @annotation(auditable)" <1>
method="audit"
arg-names="auditable" />
----
<1> References the `publicMethod` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-pointcuts-combining[Combining Pointcut Expressions].
The `arg-names` attribute accepts a comma-delimited list of parameter names.
The following slightly more involved example of the XSD-based approach shows
some around advice used in conjunction with a number of strongly typed parameters:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
----
package com.xyz.service;
public interface PersonService {
Person getPerson(String personName, int age);
}
public class DefaultPersonService implements PersonService {
public Person getPerson(String name, int age) {
return new Person(name, age);
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
----
package com.xyz.service
interface PersonService {
fun getPerson(personName: String, age: Int): Person
}
class DefaultPersonService : PersonService {
fun getPerson(name: String, age: Int): Person {
return Person(name, age)
}
}
----
======
Next up is the aspect. Notice the fact that the `profile(..)` method accepts a number of
strongly-typed parameters, the first of which happens to be the join point used to
proceed with the method call. The presence of this parameter is an indication that the
`profile(..)` is to be used as `around` advice, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
----
package com.xyz;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.util.StopWatch;
public class SimpleProfiler {
public Object profile(ProceedingJoinPoint call, String name, int age) throws Throwable {
StopWatch clock = new StopWatch("Profiling for '" + name + "' and '" + age + "'");
try {
clock.start(call.toShortString());
return call.proceed();
} finally {
clock.stop();
System.out.println(clock.prettyPrint());
}
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
----
package com.xyz
import org.aspectj.lang.ProceedingJoinPoint
import org.springframework.util.StopWatch
class SimpleProfiler {
fun profile(call: ProceedingJoinPoint, name: String, age: Int): Any? {
val clock = StopWatch("Profiling for '$name' and '$age'")
try {
clock.start(call.toShortString())
return call.proceed()
} finally {
clock.stop()
println(clock.prettyPrint())
}
}
}
----
======
Finally, the following example XML configuration effects the execution of the
preceding advice for a particular join point:
[source,xml,indent=0,subs="verbatim"]
----
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- this is the object that will be proxied by Spring's AOP infrastructure -->
<bean id="personService" class="com.xyz.service.DefaultPersonService"/>
<!-- this is the actual advice itself -->
<bean id="profiler" class="com.xyz.SimpleProfiler"/>
<aop:config>
<aop:aspect ref="profiler">
<aop:pointcut id="theExecutionOfSomePersonServiceMethod"
expression="execution(* com.xyz.service.PersonService.getPerson(String,int))
and args(name, age)"/>
<aop:around pointcut-ref="theExecutionOfSomePersonServiceMethod"
method="profile"/>
</aop:aspect>
</aop:config>
</beans>
----
Consider the following driver script:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
public class Boot {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
PersonService person = ctx.getBean(PersonService.class);
person.getPerson("Pengo", 12);
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
fun main() {
val ctx = ClassPathXmlApplicationContext("beans.xml")
val person = ctx.getBean(PersonService.class)
person.getPerson("Pengo", 12)
}
----
======
With such a `Boot` class, we would get output similar to the following on standard output:
[literal,subs="verbatim"]
----
StopWatch 'Profiling for 'Pengo' and '12': running time (millis) = 0
-----------------------------------------
ms % Task name
-----------------------------------------
00000 ? execution(getFoo)
----
[[aop-ordering]]
=== Advice Ordering
When multiple pieces of advice need to run at the same join point (executing method)
the ordering rules are as described in xref:core/aop/ataspectj/advice.adoc#aop-ataspectj-advice-ordering[Advice Ordering]. The precedence
between aspects is determined via the `order` attribute in the `<aop:aspect>` element or
by either adding the `@Order` annotation to the bean that backs the aspect or by having
the bean implement the `Ordered` interface.
[NOTE]
====
In contrast to the precedence rules for advice methods defined in the same `@Aspect`
class, when two pieces of advice defined in the same `<aop:aspect>` element both need to
run at the same join point, the precedence is determined by the order in which the advice
elements are declared within the enclosing `<aop:aspect>` element, from highest to lowest
precedence.
For example, given an `around` advice and a `before` advice defined in the same
`<aop:aspect>` element that apply to the same join point, to ensure that the `around`
advice has higher precedence than the `before` advice, the `<aop:around>` element must be
declared before the `<aop:before>` element.
As a general rule of thumb, if you find that you have multiple pieces of advice defined
in the same `<aop:aspect>` element that apply to the same join point, consider collapsing
such advice methods into one advice method per join point in each `<aop:aspect>` element
or refactor the pieces of advice into separate `<aop:aspect>` elements that you can order
at the aspect level.
====
[[aop-schema-introductions]]
== Introductions
Introductions (known as inter-type declarations in AspectJ) let an aspect declare
that advised objects implement a given interface and provide an implementation of
that interface on behalf of those objects.
You can make an introduction by using the `aop:declare-parents` element inside an `aop:aspect`.
You can use the `aop:declare-parents` element to declare that matching types have a new parent (hence the name).
For example, given an interface named `UsageTracked` and an implementation of that interface named
`DefaultUsageTracked`, the following aspect declares that all implementors of service
interfaces also implement the `UsageTracked` interface. (In order to expose statistics
through JMX for example.)
[source,xml,indent=0,subs="verbatim"]
----
<aop:aspect id="usageTrackerAspect" ref="usageTracking">
<aop:declare-parents
types-matching="com.xyz.service.*+"
implement-interface="com.xyz.service.tracking.UsageTracked"
default-impl="com.xyz.service.tracking.DefaultUsageTracked"/>
<aop:before
pointcut="execution(* com.xyz..service.*.*(..))
and this(usageTracked)"
method="recordUsage"/>
</aop:aspect>
----
The class that backs the `usageTracking` bean would then contain the following method:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
public void recordUsage(UsageTracked usageTracked) {
usageTracked.incrementUseCount();
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
fun recordUsage(usageTracked: UsageTracked) {
usageTracked.incrementUseCount()
}
----
======
The interface to be implemented is determined by the `implement-interface` attribute. The
value of the `types-matching` attribute is an AspectJ type pattern. Any bean of a
matching type implements the `UsageTracked` interface. Note that, in the before
advice of the preceding example, service beans can be directly used as implementations of
the `UsageTracked` interface. To access a bean programmatically, you could write the
following:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
UsageTracked usageTracked = context.getBean("myService", UsageTracked.class);
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
val usageTracked = context.getBean("myService", UsageTracked.class)
----
======
[[aop-schema-instantiation-models]]
== Aspect Instantiation Models
The only supported instantiation model for schema-defined aspects is the singleton
model. Other instantiation models may be supported in future releases.
[[aop-schema-advisors]]
== Advisors
The concept of "advisors" comes from the AOP support defined in Spring
and does not have a direct equivalent in AspectJ. An advisor is like a small
self-contained aspect that has a single piece of advice. The advice itself is
represented by a bean and must implement one of the advice interfaces described in
xref:core/aop-api/advice.adoc#aop-api-advice-types[Advice Types in Spring]. Advisors can take advantage of AspectJ pointcut expressions.
Spring supports the advisor concept with the `<aop:advisor>` element. You most
commonly see it used in conjunction with transactional advice, which also has its own
namespace support in Spring. The following example shows an advisor:
[source,xml,indent=0,subs="verbatim"]
----
<aop:config>
<aop:pointcut id="businessService"
expression="execution(* com.xyz.service.*.*(..))"/>
<aop:advisor
pointcut-ref="businessService"
advice-ref="tx-advice" />
</aop:config>
<tx:advice id="tx-advice">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
----
As well as the `pointcut-ref` attribute used in the preceding example, you can also use the
`pointcut` attribute to define a pointcut expression inline.
To define the precedence of an advisor so that the advice can participate in ordering,
use the `order` attribute to define the `Ordered` value of the advisor.
[[aop-schema-example]]
== An AOP Schema Example
This section shows how the concurrent locking failure retry example from
xref:core/aop/ataspectj/example.adoc[An AOP Example] looks when rewritten with the schema support.
The execution of business services can sometimes fail due to concurrency issues (for
example, a deadlock loser). If the operation is retried, it is likely to succeed
on the next try. For business services where it is appropriate to retry in such
conditions (idempotent operations that do not need to go back to the user for conflict
resolution), we want to transparently retry the operation to avoid the client seeing a
`PessimisticLockingFailureException`. This is a requirement that clearly cuts across
multiple services in the service layer and, hence, is ideal for implementing through an
aspect.
Because we want to retry the operation, we need to use around advice so that we can
call `proceed` multiple times. The following listing shows the basic aspect implementation
(which is a regular Java class that uses the schema support):
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
public class ConcurrentOperationExecutor implements Ordered {
private static final int DEFAULT_MAX_RETRIES = 2;
private int maxRetries = DEFAULT_MAX_RETRIES;
private int order = 1;
public void setMaxRetries(int maxRetries) {
this.maxRetries = maxRetries;
}
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
int numAttempts = 0;
PessimisticLockingFailureException lockFailureException;
do {
numAttempts++;
try {
return pjp.proceed();
}
catch(PessimisticLockingFailureException ex) {
lockFailureException = ex;
}
} while(numAttempts <= this.maxRetries);
throw lockFailureException;
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
class ConcurrentOperationExecutor : Ordered {
private val DEFAULT_MAX_RETRIES = 2
private var maxRetries = DEFAULT_MAX_RETRIES
private var order = 1
fun setMaxRetries(maxRetries: Int) {
this.maxRetries = maxRetries
}
override fun getOrder(): Int {
return this.order
}
fun setOrder(order: Int) {
this.order = order
}
fun doConcurrentOperation(pjp: ProceedingJoinPoint): Any? {
var numAttempts = 0
var lockFailureException: PessimisticLockingFailureException
do {
numAttempts++
try {
return pjp.proceed()
} catch (ex: PessimisticLockingFailureException) {
lockFailureException = ex
}
} while (numAttempts <= this.maxRetries)
throw lockFailureException
}
}
----
======
Note that the aspect implements the `Ordered` interface so that we can set the precedence of
the aspect higher than the transaction advice (we want a fresh transaction each time we
retry). The `maxRetries` and `order` properties are both configured by Spring. The
main action happens in the `doConcurrentOperation` around advice method. We try to
proceed. If we fail with a `PessimisticLockingFailureException`, we try again,
unless we have exhausted all of our retry attempts.
NOTE: This class is identical to the one used in the @AspectJ example, but with the
annotations removed.
The corresponding Spring configuration is as follows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:config>
<aop:aspect id="concurrentOperationRetry" ref="concurrentOperationExecutor">
<aop:pointcut id="idempotentOperation"
expression="execution(* com.xyz.service.*.*(..))"/>
<aop:around
pointcut-ref="idempotentOperation"
method="doConcurrentOperation"/>
</aop:aspect>
</aop:config>
<bean id="concurrentOperationExecutor"
class="com.xyz.service.impl.ConcurrentOperationExecutor">
<property name="maxRetries" value="3"/>
<property name="order" value="100"/>
</bean>
----
Notice that, for the time being, we assume that all business services are idempotent. If
this is not the case, we can refine the aspect so that it retries only genuinely
idempotent operations, by introducing an `Idempotent` annotation and using the annotation
to annotate the implementation of service operations, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Retention(RetentionPolicy.RUNTIME)
// marker annotation
public @interface Idempotent {
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Retention(AnnotationRetention.RUNTIME)
// marker annotation
annotation class Idempotent
----
======
The
change to the aspect to retry only idempotent operations involves refining the
pointcut expression so that only `@Idempotent` operations match, as follows:
[source,xml,indent=0,subs="verbatim"]
----
<aop:pointcut id="idempotentOperation"
expression="execution(* com.xyz.service.*.*(..)) and
@annotation(com.xyz.service.Idempotent)"/>
----
@@ -0,0 +1,988 @@
[[aop-using-aspectj]]
= Using AspectJ with Spring Applications
Everything we have covered so far in this chapter is pure Spring AOP. In this section,
we look at how you can use the AspectJ compiler or weaver instead of or in
addition to Spring AOP if your needs go beyond the facilities offered by Spring AOP
alone.
Spring ships with a small AspectJ aspect library, which is available stand-alone in your
distribution as `spring-aspects.jar`. You need to add this to your classpath in order
to use the aspects in it. xref:core/aop/using-aspectj.adoc#aop-atconfigurable[Using AspectJ to Dependency Inject Domain Objects with Spring] and xref:core/aop/using-aspectj.adoc#aop-ajlib-other[Other Spring aspects for AspectJ] discuss the
content of this library and how you can use it. xref:core/aop/using-aspectj.adoc#aop-aj-configure[Configuring AspectJ Aspects by Using Spring IoC] discusses how to
dependency inject AspectJ aspects that are woven using the AspectJ compiler. Finally,
xref:core/aop/using-aspectj.adoc#aop-aj-ltw[Load-time Weaving with AspectJ in the Spring Framework] provides an introduction to load-time weaving for Spring applications
that use AspectJ.
[[aop-atconfigurable]]
== Using AspectJ to Dependency Inject Domain Objects with Spring
The Spring container instantiates and configures beans defined in your application
context. It is also possible to ask a bean factory to configure a pre-existing
object, given the name of a bean definition that contains the configuration to be applied.
`spring-aspects.jar` contains an annotation-driven aspect that exploits this
capability to allow dependency injection of any object. The support is intended to
be used for objects created outside of the control of any container. Domain objects
often fall into this category because they are often created programmatically with the
`new` operator or by an ORM tool as a result of a database query.
The `@Configurable` annotation marks a class as being eligible for Spring-driven
configuration. In the simplest case, you can use purely it as a marker annotation, as the
following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
----
package com.xyz.domain;
import org.springframework.beans.factory.annotation.Configurable;
@Configurable
public class Account {
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
----
package com.xyz.domain
import org.springframework.beans.factory.annotation.Configurable
@Configurable
class Account {
// ...
}
----
======
When used as a marker interface in this way, Spring configures new instances of the
annotated type (`Account`, in this case) by using a bean definition (typically
prototype-scoped) with the same name as the fully-qualified type name
(`com.xyz.domain.Account`). Since the default name for a bean is the
fully-qualified name of its type, a convenient way to declare the prototype definition
is to omit the `id` attribute, as the following example shows:
[source,xml,indent=0,subs="verbatim"]
----
<bean class="com.xyz.domain.Account" scope="prototype">
<property name="fundsTransferService" ref="fundsTransferService"/>
</bean>
----
If you want to explicitly specify the name of the prototype bean definition to use, you
can do so directly in the annotation, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
----
package com.xyz.domain;
import org.springframework.beans.factory.annotation.Configurable;
@Configurable("account")
public class Account {
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
----
package com.xyz.domain
import org.springframework.beans.factory.annotation.Configurable
@Configurable("account")
class Account {
// ...
}
----
======
Spring now looks for a bean definition named `account` and uses that as the
definition to configure new `Account` instances.
You can also use autowiring to avoid having to specify a dedicated bean definition at
all. To have Spring apply autowiring, use the `autowire` property of the `@Configurable`
annotation. You can specify either `@Configurable(autowire=Autowire.BY_TYPE)` or
`@Configurable(autowire=Autowire.BY_NAME)` for autowiring by type or by name,
respectively. As an alternative, it is preferable to specify explicit, annotation-driven
dependency injection for your `@Configurable` beans through `@Autowired` or `@Inject`
at the field or method level (see xref:core/beans/annotation-config.adoc[Annotation-based Container Configuration] for further details).
Finally, you can enable Spring dependency checking for the object references in the newly
created and configured object by using the `dependencyCheck` attribute (for example,
`@Configurable(autowire=Autowire.BY_NAME,dependencyCheck=true)`). If this attribute is
set to `true`, Spring validates after configuration that all properties (which
are not primitives or collections) have been set.
Note that using the annotation on its own does nothing. It is the
`AnnotationBeanConfigurerAspect` in `spring-aspects.jar` that acts on the presence of
the annotation. In essence, the aspect says, "after returning from the initialization of
a new object of a type annotated with `@Configurable`, configure the newly created object
using Spring in accordance with the properties of the annotation". In this context,
"initialization" refers to newly instantiated objects (for example, objects instantiated
with the `new` operator) as well as to `Serializable` objects that are undergoing
deserialization (for example, through
https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html[readResolve()]).
[NOTE]
=====
One of the key phrases in the above paragraph is "in essence". For most cases, the
exact semantics of "after returning from the initialization of a new object" are
fine. In this context, "after initialization" means that the dependencies are
injected after the object has been constructed. This means that the dependencies
are not available for use in the constructor bodies of the class. If you want the
dependencies to be injected before the constructor bodies run and thus be
available for use in the body of the constructors, you need to define this on the
`@Configurable` declaration, as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Configurable(preConstruction = true)
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Configurable(preConstruction = true)
----
======
You can find more information about the language semantics of the various pointcut
types in AspectJ
https://www.eclipse.org/aspectj/doc/next/progguide/semantics-joinPoints.html[in this
appendix] of the https://www.eclipse.org/aspectj/doc/next/progguide/index.html[AspectJ
Programming Guide].
=====
For this to work, the annotated types must be woven with the AspectJ weaver. You can
either use a build-time Ant or Maven task to do this (see, for example, the
https://www.eclipse.org/aspectj/doc/released/devguide/antTasks.html[AspectJ Development
Environment Guide]) or load-time weaving (see xref:core/aop/using-aspectj.adoc#aop-aj-ltw[Load-time Weaving with AspectJ in the Spring Framework]). The
`AnnotationBeanConfigurerAspect` itself needs to be configured by Spring (in order to obtain
a reference to the bean factory that is to be used to configure new objects). If you
use Java-based configuration, you can add `@EnableSpringConfigured` to any
`@Configuration` class, as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Configuration
@EnableSpringConfigured
public class AppConfig {
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Configuration
@EnableSpringConfigured
class AppConfig {
}
----
======
If you prefer XML based configuration, the Spring
xref:core/appendix/xsd-schemas.adoc#context[`context` namespace]
defines a convenient `context:spring-configured` element, which you can use as follows:
[source,xml,indent=0,subs="verbatim"]
----
<context:spring-configured/>
----
Instances of `@Configurable` objects created before the aspect has been configured
result in a message being issued to the debug log and no configuration of the
object taking place. An example might be a bean in the Spring configuration that creates
domain objects when it is initialized by Spring. In this case, you can use the
`depends-on` bean attribute to manually specify that the bean depends on the
configuration aspect. The following example shows how to use the `depends-on` attribute:
[source,xml,indent=0,subs="verbatim"]
----
<bean id="myService"
class="com.xyz.service.MyService"
depends-on="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect">
<!-- ... -->
</bean>
----
NOTE: Do not activate `@Configurable` processing through the bean configurer aspect unless you
really mean to rely on its semantics at runtime. In particular, make sure that you do
not use `@Configurable` on bean classes that are registered as regular Spring beans
with the container. Doing so results in double initialization, once through the
container and once through the aspect.
[[aop-configurable-testing]]
=== Unit Testing `@Configurable` Objects
One of the goals of the `@Configurable` support is to enable independent unit testing
of domain objects without the difficulties associated with hard-coded lookups.
If `@Configurable` types have not been woven by AspectJ, the annotation has no affect
during unit testing. You can set mock or stub property references in the object under
test and proceed as normal. If `@Configurable` types have been woven by AspectJ,
you can still unit test outside of the container as normal, but you see a warning
message each time that you construct a `@Configurable` object indicating that it has
not been configured by Spring.
[[aop-configurable-container]]
=== Working with Multiple Application Contexts
The `AnnotationBeanConfigurerAspect` that is used to implement the `@Configurable` support
is an AspectJ singleton aspect. The scope of a singleton aspect is the same as the scope
of `static` members: There is one aspect instance per `ClassLoader` that defines the type.
This means that, if you define multiple application contexts within the same `ClassLoader`
hierarchy, you need to consider where to define the `@EnableSpringConfigured` bean and
where to place `spring-aspects.jar` on the classpath.
Consider a typical Spring web application configuration that has a shared parent application
context that defines common business services, everything needed to support those services,
and one child application context for each servlet (which contains definitions particular
to that servlet). All of these contexts co-exist within the same `ClassLoader` hierarchy,
and so the `AnnotationBeanConfigurerAspect` can hold a reference to only one of them.
In this case, we recommend defining the `@EnableSpringConfigured` bean in the shared
(parent) application context. This defines the services that you are likely to want to
inject into domain objects. A consequence is that you cannot configure domain objects
with references to beans defined in the child (servlet-specific) contexts by using the
@Configurable mechanism (which is probably not something you want to do anyway).
When deploying multiple web applications within the same container, ensure that each
web application loads the types in `spring-aspects.jar` by using its own `ClassLoader`
(for example, by placing `spring-aspects.jar` in `WEB-INF/lib`). If `spring-aspects.jar`
is added only to the container-wide classpath (and hence loaded by the shared parent
`ClassLoader`), all web applications share the same aspect instance (which is probably
not what you want).
[[aop-ajlib-other]]
== Other Spring aspects for AspectJ
In addition to the `@Configurable` aspect, `spring-aspects.jar` contains an AspectJ
aspect that you can use to drive Spring's transaction management for types and methods
annotated with the `@Transactional` annotation. This is primarily intended for users who
want to use the Spring Framework's transaction support outside of the Spring container.
The aspect that interprets `@Transactional` annotations is the
`AnnotationTransactionAspect`. When you use this aspect, you must annotate the
implementation class (or methods within that class or both), not the interface (if
any) that the class implements. AspectJ follows Java's rule that annotations on
interfaces are not inherited.
A `@Transactional` annotation on a class specifies the default transaction semantics for
the execution of any public operation in the class.
A `@Transactional` annotation on a method within the class overrides the default
transaction semantics given by the class annotation (if present). Methods of any
visibility may be annotated, including private methods. Annotating non-public methods
directly is the only way to get transaction demarcation for the execution of such methods.
TIP: Since Spring Framework 4.2, `spring-aspects` provides a similar aspect that offers the
exact same features for the standard `jakarta.transaction.Transactional` annotation. Check
`JtaAnnotationTransactionAspect` for more details.
For AspectJ programmers who want to use the Spring configuration and transaction
management support but do not want to (or cannot) use annotations, `spring-aspects.jar`
also contains `abstract` aspects you can extend to provide your own pointcut
definitions. See the sources for the `AbstractBeanConfigurerAspect` and
`AbstractTransactionAspect` aspects for more information. As an example, the following
excerpt shows how you could write an aspect to configure all instances of objects
defined in the domain model by using prototype bean definitions that match the
fully qualified class names:
[source,java,indent=0,subs="verbatim"]
----
public aspect DomainObjectConfiguration extends AbstractBeanConfigurerAspect {
public DomainObjectConfiguration() {
setBeanWiringInfoResolver(new ClassNameBeanWiringInfoResolver());
}
// the creation of a new bean (any object in the domain model)
protected pointcut beanCreation(Object beanInstance) :
initialization(new(..)) &&
CommonPointcuts.inDomainModel() &&
this(beanInstance);
}
----
[[aop-aj-configure]]
== Configuring AspectJ Aspects by Using Spring IoC
When you use AspectJ aspects with Spring applications, it is natural to both want and
expect to be able to configure such aspects with Spring. The AspectJ runtime itself is
responsible for aspect creation, and the means of configuring the AspectJ-created
aspects through Spring depends on the AspectJ instantiation model (the `per-xxx` clause)
used by the aspect.
The majority of AspectJ aspects are singleton aspects. Configuration of these
aspects is easy. You can create a bean definition that references the aspect type as
normal and include the `factory-method="aspectOf"` bean attribute. This ensures that
Spring obtains the aspect instance by asking AspectJ for it rather than trying to create
an instance itself. The following example shows how to use the `factory-method="aspectOf"` attribute:
[source,xml,indent=0,subs="verbatim"]
----
<bean id="profiler" class="com.xyz.profiler.Profiler"
factory-method="aspectOf"> <1>
<property name="profilingStrategy" ref="jamonProfilingStrategy"/>
</bean>
----
<1> Note the `factory-method="aspectOf"` attribute
Non-singleton aspects are harder to configure. However, it is possible to do so by
creating prototype bean definitions and using the `@Configurable` support from
`spring-aspects.jar` to configure the aspect instances once they have bean created by
the AspectJ runtime.
If you have some @AspectJ aspects that you want to weave with AspectJ (for example,
using load-time weaving for domain model types) and other @AspectJ aspects that you want
to use with Spring AOP, and these aspects are all configured in Spring, you
need to tell the Spring AOP @AspectJ auto-proxying support which exact subset of the
@AspectJ aspects defined in the configuration should be used for auto-proxying. You can
do this by using one or more `<include/>` elements inside the `<aop:aspectj-autoproxy/>`
declaration. Each `<include/>` element specifies a name pattern, and only beans with
names matched by at least one of the patterns are used for Spring AOP auto-proxy
configuration. The following example shows how to use `<include/>` elements:
[source,xml,indent=0,subs="verbatim"]
----
<aop:aspectj-autoproxy>
<aop:include name="thisBean"/>
<aop:include name="thatBean"/>
</aop:aspectj-autoproxy>
----
NOTE: Do not be misled by the name of the `<aop:aspectj-autoproxy/>` element. Using it
results in the creation of Spring AOP proxies. The @AspectJ style of aspect
declaration is being used here, but the AspectJ runtime is not involved.
[[aop-aj-ltw]]
== Load-time Weaving with AspectJ in the Spring Framework
Load-time weaving (LTW) refers to the process of weaving AspectJ aspects into an
application's class files as they are being loaded into the Java virtual machine (JVM).
The focus of this section is on configuring and using LTW in the specific context of the
Spring Framework. This section is not a general introduction to LTW. For full details on
the specifics of LTW and configuring LTW with only AspectJ (with Spring not being
involved at all), see the
https://www.eclipse.org/aspectj/doc/released/devguide/ltw.html[LTW section of the AspectJ
Development Environment Guide].
The value that the Spring Framework brings to AspectJ LTW is in enabling much
finer-grained control over the weaving process. 'Vanilla' AspectJ LTW is effected by using
a Java (5+) agent, which is switched on by specifying a VM argument when starting up a
JVM. It is, thus, a JVM-wide setting, which may be fine in some situations but is often a
little too coarse. Spring-enabled LTW lets you switch on LTW on a
per-`ClassLoader` basis, which is more fine-grained and which can make more
sense in a 'single-JVM-multiple-application' environment (such as is found in a typical
application server environment).
Further, xref:core/aop/using-aspectj.adoc#aop-aj-ltw-environments[in certain environments], this support enables
load-time weaving without making any modifications to the application server's launch
script that is needed to add `-javaagent:path/to/aspectjweaver.jar` or (as we describe
later in this section) `-javaagent:path/to/spring-instrument.jar`. Developers configure
the application context to enable load-time weaving instead of relying on administrators
who typically are in charge of the deployment configuration, such as the launch script.
Now that the sales pitch is over, let us first walk through a quick example of AspectJ
LTW that uses Spring, followed by detailed specifics about elements introduced in the
example. For a complete example, see the
https://github.com/spring-projects/spring-petclinic[Petclinic sample application].
[[aop-aj-ltw-first-example]]
=== A First Example
Assume that you are an application developer who has been tasked with diagnosing
the cause of some performance problems in a system. Rather than break out a
profiling tool, we are going to switch on a simple profiling aspect that lets us
quickly get some performance metrics. We can then apply a finer-grained profiling
tool to that specific area immediately afterwards.
NOTE: The example presented here uses XML configuration. You can also configure and
use @AspectJ with xref:core/beans/java.adoc[Java configuration]. Specifically, you can use the
`@EnableLoadTimeWeaving` annotation as an alternative to `<context:load-time-weaver/>`
(see xref:core/aop/using-aspectj.adoc#aop-aj-ltw-spring[below] for details).
The following example shows the profiling aspect, which is not fancy.
It is a time-based profiler that uses the @AspectJ-style of aspect declaration:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
----
package com.xyz;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.util.StopWatch;
import org.springframework.core.annotation.Order;
@Aspect
public class ProfilingAspect {
@Around("methodsToBeProfiled()")
public Object profile(ProceedingJoinPoint pjp) throws Throwable {
StopWatch sw = new StopWatch(getClass().getSimpleName());
try {
sw.start(pjp.getSignature().getName());
return pjp.proceed();
} finally {
sw.stop();
System.out.println(sw.prettyPrint());
}
}
@Pointcut("execution(public * com.xyz..*.*(..))")
public void methodsToBeProfiled(){}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
----
package com.xyz
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Pointcut
import org.springframework.util.StopWatch
import org.springframework.core.annotation.Order
@Aspect
class ProfilingAspect {
@Around("methodsToBeProfiled()")
fun profile(pjp: ProceedingJoinPoint): Any? {
val sw = StopWatch(javaClass.simpleName)
try {
sw.start(pjp.getSignature().getName())
return pjp.proceed()
} finally {
sw.stop()
println(sw.prettyPrint())
}
}
@Pointcut("execution(public * com.xyz..*.*(..))")
fun methodsToBeProfiled() {
}
}
----
======
We also need to create an `META-INF/aop.xml` file, to inform the AspectJ weaver that
we want to weave our `ProfilingAspect` into our classes. This file convention, namely
the presence of a file (or files) on the Java classpath called `META-INF/aop.xml` is
standard AspectJ. The following example shows the `aop.xml` file:
[source,xml,indent=0,subs="verbatim"]
----
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!-- only weave classes in our application-specific packages -->
<include within="com.xyz.*"/>
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="com.xyz.ProfilingAspect"/>
</aspects>
</aspectj>
----
Now we can move on to the Spring-specific portion of the configuration. We need
to configure a `LoadTimeWeaver` (explained later). This load-time weaver is the
essential component responsible for weaving the aspect configuration in one or
more `META-INF/aop.xml` files into the classes in your application. The good
thing is that it does not require a lot of configuration (there are some more
options that you can specify, but these are detailed later), as can be seen in
the following example:
[source,xml,indent=0,subs="verbatim"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- a service object; we will be profiling its methods -->
<bean id="entitlementCalculationService"
class="com.xyz.StubEntitlementCalculationService"/>
<!-- this switches on the load-time weaving -->
<context:load-time-weaver/>
</beans>
----
Now that all the required artifacts (the aspect, the `META-INF/aop.xml`
file, and the Spring configuration) are in place, we can create the following
driver class with a `main(..)` method to demonstrate the LTW in action:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
----
package com.xyz;
// imports
public class Main {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
EntitlementCalculationService service =
ctx.getBean(EntitlementCalculationService.class);
// the profiling aspect is 'woven' around this method execution
service.calculateEntitlement();
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
----
package com.xyz
// imports
fun main() {
val ctx = ClassPathXmlApplicationContext("beans.xml")
val service = ctx.getBean(EntitlementCalculationService.class)
// the profiling aspect is 'woven' around this method execution
service.calculateEntitlement()
}
----
======
We have one last thing to do. The introduction to this section did say that one could
switch on LTW selectively on a per-`ClassLoader` basis with Spring, and this is true.
However, for this example, we use a Java agent (supplied with Spring) to switch on LTW.
We use the following command to run the `Main` class shown earlier:
[literal,subs="verbatim"]
----
java -javaagent:C:/projects/xyz/lib/spring-instrument.jar com.xyz.Main
----
The `-javaagent` is a flag for specifying and enabling
https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/package-summary.html[agents
to instrument programs that run on the JVM]. The Spring Framework ships with such an
agent, the `InstrumentationSavingAgent`, which is packaged in the
`spring-instrument.jar` that was supplied as the value of the `-javaagent` argument in
the preceding example.
The output from the execution of the `Main` program looks something like the next example.
(I have introduced a `Thread.sleep(..)` statement into the `calculateEntitlement()`
implementation so that the profiler actually captures something other than 0
milliseconds (the `01234` milliseconds is not an overhead introduced by the AOP).
The following listing shows the output we got when we ran our profiler:
[literal,subs="verbatim"]
----
Calculating entitlement
StopWatch 'ProfilingAspect': running time (millis) = 1234
------ ----- ----------------------------
ms % Task name
------ ----- ----------------------------
01234 100% calculateEntitlement
----
Since this LTW is effected by using full-blown AspectJ, we are not limited only to advising
Spring beans. The following slight variation on the `Main` program yields the same
result:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
----
package com.xyz;
// imports
public class Main {
public static void main(String[] args) {
new ClassPathXmlApplicationContext("beans.xml");
EntitlementCalculationService service =
new StubEntitlementCalculationService();
// the profiling aspect will be 'woven' around this method execution
service.calculateEntitlement();
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
----
package com.xyz
// imports
fun main(args: Array<String>) {
ClassPathXmlApplicationContext("beans.xml")
val service = StubEntitlementCalculationService()
// the profiling aspect will be 'woven' around this method execution
service.calculateEntitlement()
}
----
======
Notice how, in the preceding program, we bootstrap the Spring container and
then create a new instance of the `StubEntitlementCalculationService` totally outside
the context of Spring. The profiling advice still gets woven in.
Admittedly, the example is simplistic. However, the basics of the LTW support in Spring
have all been introduced in the earlier example, and the rest of this section explains
the "why" behind each bit of configuration and usage in detail.
NOTE: The `ProfilingAspect` used in this example may be basic, but it is quite useful. It is a
nice example of a development-time aspect that developers can use during development
and then easily exclude from builds of the application being deployed
into UAT or production.
[[aop-aj-ltw-the-aspects]]
=== Aspects
The aspects that you use in LTW have to be AspectJ aspects. You can write them in
either the AspectJ language itself, or you can write your aspects in the @AspectJ-style.
Your aspects are then both valid AspectJ and Spring AOP aspects.
Furthermore, the compiled aspect classes need to be available on the classpath.
[[aop-aj-ltw-aop_dot_xml]]
=== 'META-INF/aop.xml'
The AspectJ LTW infrastructure is configured by using one or more `META-INF/aop.xml`
files that are on the Java classpath (either directly or, more typically, in jar files).
The structure and contents of this file is detailed in the LTW part of the
https://www.eclipse.org/aspectj/doc/released/devguide/ltw-configuration.html[AspectJ reference
documentation]. Because the `aop.xml` file is 100% AspectJ, we do not describe it further here.
[[aop-aj-ltw-libraries]]
=== Required libraries (JARS)
At minimum, you need the following libraries to use the Spring Framework's support
for AspectJ LTW:
* `spring-aop.jar`
* `aspectjweaver.jar`
If you use the xref:core/aop/using-aspectj.adoc#aop-aj-ltw-environments-generic[Spring-provided agent to enable instrumentation]
, you also need:
* `spring-instrument.jar`
[[aop-aj-ltw-spring]]
=== Spring Configuration
The key component in Spring's LTW support is the `LoadTimeWeaver` interface (in the
`org.springframework.instrument.classloading` package), and the numerous implementations
of it that ship with the Spring distribution. A `LoadTimeWeaver` is responsible for
adding one or more `java.lang.instrument.ClassFileTransformers` to a `ClassLoader` at
runtime, which opens the door to all manner of interesting applications, one of which
happens to be the LTW of aspects.
TIP: If you are unfamiliar with the idea of runtime class file transformation, see the
javadoc API documentation for the `java.lang.instrument` package before continuing.
While that documentation is not comprehensive, at least you can see the key interfaces
and classes (for reference as you read through this section).
Configuring a `LoadTimeWeaver` for a particular `ApplicationContext` can be as easy as
adding one line. (Note that you almost certainly need to use an
`ApplicationContext` as your Spring container -- typically, a `BeanFactory` is not
enough because the LTW support uses `BeanFactoryPostProcessors`.)
To enable the Spring Framework's LTW support, you need to configure a `LoadTimeWeaver`,
which typically is done by using the `@EnableLoadTimeWeaving` annotation, as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Configuration
@EnableLoadTimeWeaving
public class AppConfig {
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Configuration
@EnableLoadTimeWeaving
class AppConfig {
}
----
======
Alternatively, if you prefer XML-based configuration, use the
`<context:load-time-weaver/>` element. Note that the element is defined in the
`context` namespace. The following example shows how to use `<context:load-time-weaver/>`:
[source,xml,indent=0,subs="verbatim"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:load-time-weaver/>
</beans>
----
The preceding configuration automatically defines and registers a number of LTW-specific
infrastructure beans, such as a `LoadTimeWeaver` and an `AspectJWeavingEnabler`, for you.
The default `LoadTimeWeaver` is the `DefaultContextLoadTimeWeaver` class, which attempts
to decorate an automatically detected `LoadTimeWeaver`. The exact type of `LoadTimeWeaver`
that is "automatically detected" is dependent upon your runtime environment.
The following table summarizes various `LoadTimeWeaver` implementations:
[[aop-aj-ltw-spring-env-impls]]
.DefaultContextLoadTimeWeaver LoadTimeWeavers
|===
| Runtime Environment| `LoadTimeWeaver` implementation
| Running in https://tomcat.apache.org/[Apache Tomcat]
| `TomcatLoadTimeWeaver`
| Running in https://eclipse-ee4j.github.io/glassfish/[GlassFish] (limited to EAR deployments)
| `GlassFishLoadTimeWeaver`
| Running in Red Hat's https://www.jboss.org/jbossas/[JBoss AS] or https://www.wildfly.org/[WildFly]
| `JBossLoadTimeWeaver`
| JVM started with Spring `InstrumentationSavingAgent`
(`java -javaagent:path/to/spring-instrument.jar`)
| `InstrumentationLoadTimeWeaver`
| Fallback, expecting the underlying ClassLoader to follow common conventions
(namely `addTransformer` and optionally a `getThrowawayClassLoader` method)
| `ReflectiveLoadTimeWeaver`
|===
Note that the table lists only the `LoadTimeWeavers` that are autodetected when you
use the `DefaultContextLoadTimeWeaver`. You can specify exactly which `LoadTimeWeaver`
implementation to use.
To specify a specific `LoadTimeWeaver` with Java configuration, implement the
`LoadTimeWeavingConfigurer` interface and override the `getLoadTimeWeaver()` method.
The following example specifies a `ReflectiveLoadTimeWeaver`:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
----
@Configuration
@EnableLoadTimeWeaving
public class AppConfig implements LoadTimeWeavingConfigurer {
@Override
public LoadTimeWeaver getLoadTimeWeaver() {
return new ReflectiveLoadTimeWeaver();
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
@Configuration
@EnableLoadTimeWeaving
class AppConfig : LoadTimeWeavingConfigurer {
override fun getLoadTimeWeaver(): LoadTimeWeaver {
return ReflectiveLoadTimeWeaver()
}
}
----
======
If you use XML-based configuration, you can specify the fully qualified class name
as the value of the `weaver-class` attribute on the `<context:load-time-weaver/>`
element. Again, the following example specifies a `ReflectiveLoadTimeWeaver`:
[source,xml,indent=0,subs="verbatim"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:load-time-weaver
weaver-class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
</beans>
----
The `LoadTimeWeaver` that is defined and registered by the configuration can be later
retrieved from the Spring container by using the well known name, `loadTimeWeaver`.
Remember that the `LoadTimeWeaver` exists only as a mechanism for Spring's LTW
infrastructure to add one or more `ClassFileTransformers`. The actual
`ClassFileTransformer` that does the LTW is the `ClassPreProcessorAgentAdapter` (from
the `org.aspectj.weaver.loadtime` package) class. See the class-level javadoc of the
`ClassPreProcessorAgentAdapter` class for further details, because the specifics of how
the weaving is actually effected is beyond the scope of this document.
There is one final attribute of the configuration left to discuss: the `aspectjWeaving`
attribute (or `aspectj-weaving` if you use XML). This attribute controls whether LTW
is enabled or not. It accepts one of three possible values, with the default value being
`autodetect` if the attribute is not present. The following table summarizes the three
possible values:
[[aop-aj-ltw-ltw-tag-attrs]]
.AspectJ weaving attribute values
|===
| Annotation Value| XML Value| Explanation
| `ENABLED`
| `on`
| AspectJ weaving is on, and aspects are woven at load-time as appropriate.
| `DISABLED`
| `off`
| LTW is off. No aspect is woven at load-time.
| `AUTODETECT`
| `autodetect`
| If the Spring LTW infrastructure can find at least one `META-INF/aop.xml` file,
then AspectJ weaving is on. Otherwise, it is off. This is the default value.
|===
[[aop-aj-ltw-environments]]
=== Environment-specific Configuration
This last section contains any additional settings and configuration that you need
when you use Spring's LTW support in environments such as application servers and web
containers.
[[aop-aj-ltw-environments-tomcat-jboss-etc]]
==== Tomcat, JBoss, WildFly
Tomcat and JBoss/WildFly provide a general app `ClassLoader` that is capable of local
instrumentation. Spring's native LTW may leverage those ClassLoader implementations
to provide AspectJ weaving.
You can simply enable load-time weaving, as xref:core/aop/using-aspectj.adoc[described earlier].
Specifically, you do not need to modify the JVM launch script to add
`-javaagent:path/to/spring-instrument.jar`.
Note that on JBoss, you may need to disable the app server scanning to prevent it from
loading the classes before the application actually starts. A quick workaround is to add
to your artifact a file named `WEB-INF/jboss-scanning.xml` with the following content:
[source,xml,indent=0,subs="verbatim"]
----
<scanning xmlns="urn:jboss:scanning:1.0"/>
----
[[aop-aj-ltw-environments-generic]]
==== Generic Java Applications
When class instrumentation is required in environments that are not supported by
specific `LoadTimeWeaver` implementations, a JVM agent is the general solution.
For such cases, Spring provides `InstrumentationLoadTimeWeaver` which requires a
Spring-specific (but very general) JVM agent, `spring-instrument.jar`, autodetected
by common `@EnableLoadTimeWeaving` and `<context:load-time-weaver/>` setups.
To use it, you must start the virtual machine with the Spring agent by supplying
the following JVM options:
[literal]
[subs="verbatim"]
----
-javaagent:/path/to/spring-instrument.jar
----
Note that this requires modification of the JVM launch script, which may prevent you
from using this in application server environments (depending on your server and your
operation policies). That said, for one-app-per-JVM deployments such as standalone
Spring Boot applications, you typically control the entire JVM setup in any case.
@@ -0,0 +1,502 @@
[[aot]]
= Ahead of Time Optimizations
This chapter covers Spring's Ahead of Time (AOT) optimizations.
For AOT support specific to integration tests, see xref:testing/testcontext-framework/aot.adoc[Ahead of Time Support for Tests].
[[aot.introduction]]
== Introduction to Ahead of Time Optimizations
Spring's support for AOT optimizations is meant to inspect an `ApplicationContext` at build time and apply decisions and discovery logic that usually happens at runtime.
Doing so allows building an application startup arrangement that is more straightforward and focused on a fixed set of features based mainly on the classpath and the `Environment`.
Applying such optimizations early implies the following restrictions:
* The classpath is fixed and fully defined at build time.
* The beans defined in your application cannot change at runtime, meaning:
** `@Profile`, in particular profile-specific configuration needs to be chosen at build time.
** `Environment` properties that impact the presence of a bean (`@Conditional`) are only considered at build time.
* Bean definitions with instance suppliers (lambdas or method references) cannot be transformed ahead-of-time (see related https://github.com/spring-projects/spring-framework/issues/29555[spring-framework#29555] issue).
* Make sure that the bean type is as precise as possible.
TIP: See also the xref:core/aot.adoc#aot.bestpractices[] section.
When these restrictions are in place, it becomes possible to perform ahead-of-time processing at build time and generate additional assets.
A Spring AOT processed application typically generates:
* Java source code
* Bytecode (usually for dynamic proxies)
* {api-spring-framework}/aot/hint/RuntimeHints.html[`RuntimeHints`] for the use of reflection, resource loading, serialization, and JDK proxies.
NOTE: At the moment, AOT is focused on allowing Spring applications to be deployed as native images using GraalVM.
We intend to support more JVM-based use cases in future generations.
[[aot.basics]]
== AOT engine overview
The entry point of the AOT engine for processing an `ApplicationContext` arrangement is `ApplicationContextAotGenerator`. It takes care of the following steps, based on a `GenericApplicationContext` that represents the application to optimize and a {api-spring-framework}/aot/generate/GenerationContext.html[`GenerationContext`]:
* Refresh an `ApplicationContext` for AOT processing. Contrary to a traditional refresh, this version only creates bean definitions, not bean instances.
* Invoke the available `BeanFactoryInitializationAotProcessor` implementations and apply their contributions against the `GenerationContext`.
For instance, a core implementation iterates over all candidate bean definitions and generates the necessary code to restore the state of the `BeanFactory`.
Once this process completes, the `GenerationContext` will have been updated with the generated code, resources, and classes that are necessary for the application to run.
The `RuntimeHints` instance can also be used to generate the relevant GraalVM native image configuration files.
`ApplicationContextAotGenerator#processAheadOfTime` returns the class name of the `ApplicationContextInitializer` entry point that allows the context to be started with AOT optimizations.
Those steps are covered in greater detail in the sections below.
[[aot.refresh]]
== Refresh for AOT Processing
Refresh for AOT processing is supported on all `GenericApplicationContext` implementations.
An application context is created with any number of entry points, usually in the form of `@Configuration`-annotated classes.
Let's look at a basic example:
include-code::./AotProcessingSample[tag=myapplication]
Starting this application with the regular runtime involves a number of steps including classpath scanning, configuration class parsing, bean instantiation, and lifecycle callback handling.
Refresh for AOT processing only applies a subset of what happens with a xref:core/beans/introduction.adoc[regular `refresh`].
AOT processing can be triggered as follows:
include-code::./AotProcessingSample[tag=aotcontext]
In this mode, xref:core/beans/factory-extension.adoc#beans-factory-extension-factory-postprocessors[`BeanFactoryPostProcessor` implementations] are invoked as usual.
This includes configuration class parsing, import selectors, classpath scanning, etc.
Such steps make sure that the `BeanRegistry` contains the relevant bean definitions for the application.
If bean definitions are guarded by conditions (such as `@Profile`), these are discarded at this stage.
Because this mode does not actually create bean instances, `BeanPostProcessor` implementations are not invoked, except for specific variants that are relevant for AOT processing.
These are:
* `MergedBeanDefinitionPostProcessor` implementations post-process bean definitions to extract additional settings, such as `init` and `destroy` methods.
* `SmartInstantiationAwareBeanPostProcessor` implementations determine a more precise bean type if necessary.
This makes sure to create any proxy that will be required at runtime.
Once this part completes, the `BeanFactory` contains the bean definitions that are necessary for the application to run. It does not trigger bean instantiation but allows the AOT engine to inspect the beans that will be created at runtime.
[[aot.bean-factory-initialization-contributions]]
== Bean Factory Initialization AOT Contributions
Components that want to participate in this step can implement the {api-spring-framework}/beans/factory/aot/BeanFactoryInitializationAotProcessor.html[`BeanFactoryInitializationAotProcessor`] interface.
Each implementation can return an AOT contribution, based on the state of the bean factory.
An AOT contribution is a component that contributes generated code that reproduces a particular behavior.
It can also contribute `RuntimeHints` to indicate the need for reflection, resource loading, serialization, or JDK proxies.
A `BeanFactoryInitializationAotProcessor` implementation can be registered in `META-INF/spring/aot.factories` with a key equal to the fully qualified name of the interface.
A `BeanFactoryInitializationAotProcessor` can also be implemented directly by a bean.
In this mode, the bean provides an AOT contribution equivalent to the feature it provides with a regular runtime.
Consequently, such a bean is automatically excluded from the AOT-optimized context.
[NOTE]
====
If a bean implements the `BeanFactoryInitializationAotProcessor` interface, the bean and **all** of its dependencies will be initialized during AOT processing.
We generally recommend that this interface is only implemented by infrastructure beans such as `BeanFactoryPostProcessor` which have limited dependencies and are already initialized early in the bean factory lifecycle.
If such a bean is registered using an `@Bean` factory method, ensure the method is `static` so that its enclosing `@Configuration` class does not have to be initialized.
====
[[aot.bean-registration-contributions]]
=== Bean Registration AOT Contributions
A core `BeanFactoryInitializationAotProcessor` implementation is responsible for collecting the necessary contributions for each candidate `BeanDefinition`.
It does so using a dedicated `BeanRegistrationAotProcessor`.
This interface is used as follows:
* Implemented by a `BeanPostProcessor` bean, to replace its runtime behavior.
For instance xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp-examples-aabpp[`AutowiredAnnotationBeanPostProcessor`] implements this interface to generate code that injects members annotated with `@Autowired`.
* Implemented by a type registered in `META-INF/spring/aot.factories` with a key equal to the fully qualified name of the interface.
Typically used when the bean definition needs to be tuned for specific features of the core framework.
[NOTE]
====
If a bean implements the `BeanRegistrationAotProcessor` interface, the bean and **all** of its dependencies will be initialized during AOT processing.
We generally recommend that this interface is only implemented by infrastructure beans such as `BeanFactoryPostProcessor` which have limited dependencies and are already initialized early in the bean factory lifecycle.
If such a bean is registered using an `@Bean` factory method, ensure the method is `static` so that its enclosing `@Configuration` class does not have to be initialized.
====
If no `BeanRegistrationAotProcessor` handles a particular registered bean, a default implementation processes it.
This is the default behavior, since tuning the generated code for a bean definition should be restricted to corner cases.
Taking our previous example, let's assume that `DataSourceConfiguration` is as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Configuration(proxyBeanMethods = false)
public class DataSourceConfiguration {
@Bean
public SimpleDataSource dataSource() {
return new SimpleDataSource();
}
}
----
======
Since there isn't any particular condition on this class, `dataSourceConfiguration` and `dataSource` are identified as candidates.
The AOT engine will convert the configuration class above to code similar to the following:
[tabs]
======
Java::
+
[source,java,indent=0,role="primary"]
----
/**
* Bean definitions for {@link DataSourceConfiguration}
*/
public class DataSourceConfiguration__BeanDefinitions {
/**
* Get the bean definition for 'dataSourceConfiguration'
*/
public static BeanDefinition getDataSourceConfigurationBeanDefinition() {
Class<?> beanType = DataSourceConfiguration.class;
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType);
beanDefinition.setInstanceSupplier(DataSourceConfiguration::new);
return beanDefinition;
}
/**
* Get the bean instance supplier for 'dataSource'.
*/
private static BeanInstanceSupplier<SimpleDataSource> getDataSourceInstanceSupplier() {
return BeanInstanceSupplier.<SimpleDataSource>forFactoryMethod(DataSourceConfiguration.class, "dataSource")
.withGenerator((registeredBean) -> registeredBean.getBeanFactory().getBean(DataSourceConfiguration.class).dataSource());
}
/**
* Get the bean definition for 'dataSource'
*/
public static BeanDefinition getDataSourceBeanDefinition() {
Class<?> beanType = SimpleDataSource.class;
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType);
beanDefinition.setInstanceSupplier(getDataSourceInstanceSupplier());
return beanDefinition;
}
}
----
======
NOTE: The exact code generated may differ depending on the exact nature of your bean definitions.
The generated code above creates bean definitions equivalent to the `@Configuration` class, but in a direct way and without the use of reflection if at all possible.
There is a bean definition for `dataSourceConfiguration` and one for `dataSourceBean`.
When a `datasource` instance is required, a `BeanInstanceSupplier` is called.
This supplier invokes the `dataSource()` method on the `dataSourceConfiguration` bean.
[[aot.bestpractices]]
== Best Practices
The AOT engine is designed to handle as many use cases as possible, with no code change in applications.
However, keep in mind that some optimizations are made at build time based on a static definition of the beans.
This section lists the best practices that make sure your application is ready for AOT.
[[aot.bestpractices.bean-type]]
=== Expose The Most Precise Bean Type
While your application may interact with an interface that a bean implements, it is still very important to declare the most precise type.
The AOT engine performs additional checks on the bean type, such as detecting the presence of `@Autowired` members, or lifecycle callback methods.
For `@Configuration` classes, make sure that the return type of the factory `@Bean` method is as precise as possible.
Consider the following example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Configuration(proxyBeanMethods = false)
public class UserConfiguration {
@Bean
public MyInterface myInterface() {
return new MyImplementation();
}
}
----
======
In the example above, the declared type for the `myInterface` bean is `MyInterface`.
None of the usual post-processing will take `MyImplementation` into account.
For instance, if there is an annotated handler method on `MyImplementation` that the context should register, it wont be detected upfront.
The example above should be rewritten as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Configuration(proxyBeanMethods = false)
public class UserConfiguration {
@Bean
public MyImplementation myInterface() {
return new MyImplementation();
}
}
----
======
If you are registering bean definitions programmatically, consider using `RootBeanBefinition` as it allows to specify a `ResolvableType` that handles generics.
[[aot.bestpractices.constructors]]
=== Avoid Multiple Constructors
The container is able to choose the most appropriate constructor to use based on several candidates.
However, this is not a best practice and flagging the preferred constructor with `@Autowired` if necessary is preferred.
In case you are working on a code base that you can't modify, you can set the {api-spring-framework}/beans/factory/support/AbstractBeanDefinition.html#PREFERRED_CONSTRUCTORS_ATTRIBUTE[`preferredConstructors` attribute] on the related bean definition to indicate which constructor should be used.
[[aot.bestpractices.factory-bean]]
=== FactoryBean
`FactoryBean` should be used with care as it introduces an intermediate layer in terms of bean type resolution that may not be conceptually necessary.
As a rule of thumb, if the `FactoryBean` instance does not hold long-term state and is not needed at a later point in time at runtime, it should be replaced by a regular factory method, possibly with a `FactoryBean` adapter layer on top (for declarative configuration purposes).
If your `FactoryBean` implementation does not resolve the object type (i.e. `T`), extra care is necessary.
Consider the following example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class ClientFactoryBean<T extends AbstractClient> implements FactoryBean<T> {
}
----
======
A concrete client declaration should provide a resolved generic for the client, as shown in the following example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Configuration(proxyBeanMethods = false)
public class UserConfiguration {
@Bean
public ClientFactoryBean<MyClient> myClient() {
return new ClientFactoryBean<>(...);
}
}
----
======
If the `FactoryBean` bean definition is registered programmatically, make sure to follow these steps:
1. Use `RootBeanDefinition`.
2. Set the `beanClass` to the `FactoryBean` class so that AOT knows that it is an intermediate layer.
3. Set the `ResolvableType` to a resolved generic, which makes sure the most precise type is exposed.
The following example showcases a basic definition:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
RootBeanDefinition beanDefinition = new RootBeanDefinition(ClientFactoryBean.class);
beanDefinition.setTargetType(ResolvableType.forClassWithGenerics(ClientFactoryBean.class, MyClient.class));
// ...
registry.registerBeanDefinition("myClient", beanDefinition);
----
======
[[aot.bestpractices.jpa]]
=== JPA
The JPA persistence unit has to be known upfront for certain optimizations to apply. Consider the following basic example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Bean
LocalContainerEntityManagerFactoryBean customDBEntityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setPackagesToScan("com.example.app");
return factoryBean;
}
----
======
To make sure the scanning occurs ahead of time, a `PersistenceManagedTypes` bean must be declared and used by the
factory bean definition, as shown by the following example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Bean
PersistenceManagedTypes persistenceManagedTypes(ResourceLoader resourceLoader) {
return new PersistenceManagedTypesScanner(resourceLoader)
.scan("com.example.app");
}
@Bean
LocalContainerEntityManagerFactoryBean customDBEntityManagerFactory(DataSource dataSource, PersistenceManagedTypes managedTypes) {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setManagedTypes(managedTypes);
return factoryBean;
}
----
======
[[aot.hints]]
== Runtime Hints
Running an application as a native image requires additional information compared to a regular JVM runtime.
For instance, GraalVM needs to know ahead of time if a component uses reflection.
Similarly, classpath resources are not shipped in a native image unless specified explicitly.
Consequently, if the application needs to load a resource, it must be referenced from the corresponding GraalVM native image configuration file.
The {api-spring-framework}/aot/hint/RuntimeHints.html[`RuntimeHints`] API collects the need for reflection, resource loading, serialization, and JDK proxies at runtime.
The following example makes sure that `config/app.properties` can be loaded from the classpath at runtime within a native image:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
runtimeHints.resources().registerPattern("config/app.properties");
----
======
A number of contracts are handled automatically during AOT processing.
For instance, the return type of a `@Controller` method is inspected, and relevant reflection hints are added if Spring detects that the type should be serialized (typically to JSON).
For cases that the core container cannot infer, you can register such hints programmatically.
A number of convenient annotations are also provided for common use cases.
[[aot.hints.import-runtime-hints]]
=== `@ImportRuntimeHints`
`RuntimeHintsRegistrar` implementations allow you to get a callback to the `RuntimeHints` instance managed by the AOT engine.
Implementations of this interface can be registered using `@ImportRuntimeHints` on any Spring bean or `@Bean` factory method.
`RuntimeHintsRegistrar` implementations are detected and invoked at build time.
include-code::./SpellCheckService[]
If at all possible, `@ImportRuntimeHints` should be used as close as possible to the component that requires the hints.
This way, if the component is not contributed to the `BeanFactory`, the hints won't be contributed either.
It is also possible to register an implementation statically by adding an entry in `META-INF/spring/aot.factories` with a key equal to the fully qualified name of the `RuntimeHintsRegistrar` interface.
[[aot.hints.reflective]]
=== `@Reflective`
{api-spring-framework}/aot/hint/annotation/Reflective.html[`@Reflective`] provides an idiomatic way to flag the need for reflection on an annotated element.
For instance, `@EventListener` is meta-annotated with `@Reflective` since the underlying implementation invokes the annotated method using reflection.
By default, only Spring beans are considered and an invocation hint is registered for the annotated element.
This can be tuned by specifying a custom `ReflectiveProcessor` implementation via the
`@Reflective` annotation.
Library authors can reuse this annotation for their own purposes.
If components other than Spring beans need to be processed, a `BeanFactoryInitializationAotProcessor` can detect the relevant types and use `ReflectiveRuntimeHintsRegistrar` to process them.
[[aot.hints.register-reflection-for-binding]]
=== `@RegisterReflectionForBinding`
{api-spring-framework}/aot/hint/annotation/RegisterReflectionForBinding.html[`@RegisterReflectionForBinding`] is a specialization of `@Reflective` that registers the need for serializing arbitrary types.
A typical use case is the use of DTOs that the container cannot infer, such as using a web client within a method body.
`@RegisterReflectionForBinding` can be applied to any Spring bean at the class level, but it can also be applied directly to a method, field, or constructor to better indicate where the hints are actually required.
The following example registers `Account` for serialization.
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Component
public class OrderService {
@RegisterReflectionForBinding(Account.class)
public void process(Order order) {
// ...
}
}
----
======
[[aot.hints.testing]]
=== Testing Runtime Hints
Spring Core also ships `RuntimeHintsPredicates`, a utility for checking that existing hints match a particular use case.
This can be used in your own tests to validate that a `RuntimeHintsRegistrar` contains the expected results.
We can write a test for our `SpellCheckService` and ensure that we will be able to load a dictionary at runtime:
include-code::./SpellCheckServiceTests[tag=hintspredicates]
With `RuntimeHintsPredicates`, we can check for reflection, resource, serialization, or proxy generation hints.
This approach works well for unit tests but implies that the runtime behavior of a component is well known.
You can learn more about the global runtime behavior of an application by running its test suite (or the app itself) with the {docs-graalvm}/native-image/metadata/AutomaticMetadataCollection/[GraalVM tracing agent].
This agent will record all relevant calls requiring GraalVM hints at runtime and write them out as JSON configuration files.
For more targeted discovery and testing, Spring Framework ships a dedicated module with core AOT testing utilities, `"org.springframework:spring-core-test"`.
This module contains the RuntimeHints Agent, a Java agent that records all method invocations that are related to runtime hints and helps you to assert that a given `RuntimeHints` instance covers all recorded invocations.
Let's consider a piece of infrastructure for which we'd like to test the hints we're contributing during the AOT processing phase.
include-code::./SampleReflection[]
We can then write a unit test (no native compilation required) that checks our contributed hints:
include-code::./SampleReflectionRuntimeHintsTests[]
If you forgot to contribute a hint, the test will fail and provide some details about the invocation:
[source,txt,indent=0,subs="verbatim,quotes"]
----
org.springframework.docs.core.aot.hints.testing.SampleReflection performReflection
INFO: Spring version:6.0.0-SNAPSHOT
Missing <"ReflectionHints"> for invocation <java.lang.Class#forName>
with arguments ["org.springframework.core.SpringVersion",
false,
jdk.internal.loader.ClassLoaders$AppClassLoader@251a69d7].
Stacktrace:
<"org.springframework.util.ClassUtils#forName, Line 284
io.spring.runtimehintstesting.SampleReflection#performReflection, Line 19
io.spring.runtimehintstesting.SampleReflectionRuntimeHintsTests#lambda$shouldRegisterReflectionHints$0, Line 25
----
There are various ways to configure this Java agent in your build, so please refer to the documentation of your build tool and test execution plugin.
The agent itself can be configured to instrument specific packages (by default, only `org.springframework` is instrumented).
You'll find more details in the {spring-framework-main-code}/buildSrc/README.md[Spring Framework `buildSrc` README] file.
@@ -0,0 +1,7 @@
[[appendix]]
= Appendix
:page-section-summary-toc: 1
@@ -0,0 +1,57 @@
[[application-startup-steps]]
= Application Startup Steps
This part of the appendix lists the existing `StartupSteps` that the core container is instrumented with.
WARNING: The name and detailed information about each startup step is not part of the public contract and
is subject to change; this is considered as an implementation detail of the core container and will follow
its behavior changes.
.Application startup steps defined in the core container
|===
| Name| Description| Tags
| `spring.beans.instantiate`
| Instantiation of a bean and its dependencies.
| `beanName` the name of the bean, `beanType` the type required at the injection point.
| `spring.beans.smart-initialize`
| Initialization of `SmartInitializingSingleton` beans.
| `beanName` the name of the bean.
| `spring.context.annotated-bean-reader.create`
| Creation of the `AnnotatedBeanDefinitionReader`.
|
| `spring.context.base-packages.scan`
| Scanning of base packages.
| `packages` array of base packages for scanning.
| `spring.context.beans.post-process`
| Beans post-processing phase.
|
| `spring.context.bean-factory.post-process`
| Invocation of the `BeanFactoryPostProcessor` beans.
| `postProcessor` the current post-processor.
| `spring.context.beandef-registry.post-process`
| Invocation of the `BeanDefinitionRegistryPostProcessor` beans.
| `postProcessor` the current post-processor.
| `spring.context.component-classes.register`
| Registration of component classes through `AnnotationConfigApplicationContext#register`.
| `classes` array of given classes for registration.
| `spring.context.config-classes.enhance`
| Enhancement of configuration classes with CGLIB proxies.
| `classCount` count of enhanced classes.
| `spring.context.config-classes.parse`
| Configuration classes parsing phase with the `ConfigurationClassPostProcessor`.
| `classCount` count of processed classes.
| `spring.context.refresh`
| Application context refresh phase.
|
|===
@@ -0,0 +1,661 @@
[[xsd-schemas]]
= XML Schemas
This part of the appendix lists XML schemas related to the core container.
[[xsd-schemas-util]]
== The `util` Schema
As the name implies, the `util` tags deal with common, utility configuration
issues, such as configuring collections, referencing constants, and so forth.
To use the tags in the `util` schema, you need to have the following preamble at the top
of your Spring XML configuration file (the text in the snippet references the
correct schema so that the tags in the `util` namespace are available to you):
[source,xml,indent=0,subs="verbatim,quotes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<!-- bean definitions here -->
</beans>
----
[[xsd-schemas-util-constant]]
=== Using `<util:constant/>`
Consider the following bean definition:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="..." class="...">
<property name="isolation">
<bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />
</property>
</bean>
----
The preceding configuration uses a Spring `FactoryBean` implementation (the
`FieldRetrievingFactoryBean`) to set the value of the `isolation` property on a bean
to the value of the `java.sql.Connection.TRANSACTION_SERIALIZABLE` constant. This is
all well and good, but it is verbose and (unnecessarily) exposes Spring's internal
plumbing to the end user.
The following XML Schema-based version is more concise, clearly expresses the
developer's intent ("`inject this constant value`"), and it reads better:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="..." class="...">
<property name="isolation">
<util:constant static-field="java.sql.Connection.TRANSACTION_SERIALIZABLE"/>
</property>
</bean>
----
[[xsd-schemas-util-frfb]]
==== Setting a Bean Property or Constructor Argument from a Field Value
{api-spring-framework}/beans/factory/config/FieldRetrievingFactoryBean.html[`FieldRetrievingFactoryBean`]
is a `FactoryBean` that retrieves a `static` or non-static field value. It is typically
used for retrieving `public` `static` `final` constants, which may then be used to set a
property value or constructor argument for another bean.
The following example shows how a `static` field is exposed, by using the
{api-spring-framework}/beans/factory/config/FieldRetrievingFactoryBean.html#setStaticField(java.lang.String)[`staticField`]
property:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="myField"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<property name="staticField" value="java.sql.Connection.TRANSACTION_SERIALIZABLE"/>
</bean>
----
There is also a convenience usage form where the `static` field is specified as the bean
name, as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>
----
This does mean that there is no longer any choice in what the bean `id` is (so any other
bean that refers to it also has to use this longer name), but this form is very
concise to define and very convenient to use as an inner bean since the `id` does not have
to be specified for the bean reference, as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="..." class="...">
<property name="isolation">
<bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />
</property>
</bean>
----
You can also access a non-static (instance) field of another bean, as
described in the API documentation for the
{api-spring-framework}/beans/factory/config/FieldRetrievingFactoryBean.html[`FieldRetrievingFactoryBean`]
class.
Injecting enumeration values into beans as either property or constructor arguments is
easy to do in Spring. You do not actually have to do anything or know anything about
the Spring internals (or even about classes such as the `FieldRetrievingFactoryBean`).
The following example enumeration shows how easy injecting an enum value is:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
----
package jakarta.persistence;
public enum PersistenceContextType {
TRANSACTION,
EXTENDED
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
----
package jakarta.persistence
enum class PersistenceContextType {
TRANSACTION,
EXTENDED
}
----
======
Now consider the following setter of type `PersistenceContextType` and the corresponding bean definition:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
----
package example;
public class Client {
private PersistenceContextType persistenceContextType;
public void setPersistenceContextType(PersistenceContextType type) {
this.persistenceContextType = type;
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
----
package example
class Client {
lateinit var persistenceContextType: PersistenceContextType
}
----
======
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean class="example.Client">
<property name="persistenceContextType" value="TRANSACTION"/>
</bean>
----
[[xsd-schemas-util-property-path]]
=== Using `<util:property-path/>`
Consider the following example:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- target bean to be referenced by name -->
<bean id="testBean" class="org.springframework.beans.TestBean" scope="prototype">
<property name="age" value="10"/>
<property name="spouse">
<bean class="org.springframework.beans.TestBean">
<property name="age" value="11"/>
</bean>
</property>
</bean>
<!-- results in 10, which is the value of property 'age' of bean 'testBean' -->
<bean id="testBean.age" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>
----
The preceding configuration uses a Spring `FactoryBean` implementation (the
`PropertyPathFactoryBean`) to create a bean (of type `int`) called `testBean.age` that
has a value equal to the `age` property of the `testBean` bean.
Now consider the following example, which adds a `<util:property-path/>` element:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- target bean to be referenced by name -->
<bean id="testBean" class="org.springframework.beans.TestBean" scope="prototype">
<property name="age" value="10"/>
<property name="spouse">
<bean class="org.springframework.beans.TestBean">
<property name="age" value="11"/>
</bean>
</property>
</bean>
<!-- results in 10, which is the value of property 'age' of bean 'testBean' -->
<util:property-path id="name" path="testBean.age"/>
----
The value of the `path` attribute of the `<property-path/>` element follows the form of
`beanName.beanProperty`. In this case, it picks up the `age` property of the bean named
`testBean`. The value of that `age` property is `10`.
[[xsd-schemas-util-property-path-dependency]]
==== Using `<util:property-path/>` to Set a Bean Property or Constructor Argument
`PropertyPathFactoryBean` is a `FactoryBean` that evaluates a property path on a given
target object. The target object can be specified directly or by a bean name. You can then use this
value in another bean definition as a property value or constructor
argument.
The following example shows a path being used against another bean, by name:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- target bean to be referenced by name -->
<bean id="person" class="org.springframework.beans.TestBean" scope="prototype">
<property name="age" value="10"/>
<property name="spouse">
<bean class="org.springframework.beans.TestBean">
<property name="age" value="11"/>
</bean>
</property>
</bean>
<!-- results in 11, which is the value of property 'spouse.age' of bean 'person' -->
<bean id="theAge"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetBeanName" value="person"/>
<property name="propertyPath" value="spouse.age"/>
</bean>
----
In the following example, a path is evaluated against an inner bean:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- results in 12, which is the value of property 'age' of the inner bean -->
<bean id="theAge"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetObject">
<bean class="org.springframework.beans.TestBean">
<property name="age" value="12"/>
</bean>
</property>
<property name="propertyPath" value="age"/>
</bean>
----
There is also a shortcut form, where the bean name is the property path.
The following example shows the shortcut form:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- results in 10, which is the value of property 'age' of bean 'person' -->
<bean id="person.age"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>
----
This form does mean that there is no choice in the name of the bean. Any reference to it
also has to use the same `id`, which is the path. If used as an inner
bean, there is no need to refer to it at all, as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="..." class="...">
<property name="age">
<bean id="person.age"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>
</property>
</bean>
----
You can specifically set the result type in the actual definition. This is not necessary
for most use cases, but it can sometimes be useful. See the javadoc for more info on
this feature.
[[xsd-schemas-util-properties]]
=== Using `<util:properties/>`
Consider the following example:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- creates a java.util.Properties instance with values loaded from the supplied location -->
<bean id="jdbcConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:com/foo/jdbc-production.properties"/>
</bean>
----
The preceding configuration uses a Spring `FactoryBean` implementation (the
`PropertiesFactoryBean`) to instantiate a `java.util.Properties` instance with values
loaded from the supplied xref:web/webflux-webclient/client-builder.adoc#webflux-client-builder-reactor-resources[`Resource`] location).
The following example uses a `util:properties` element to make a more concise representation:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- creates a java.util.Properties instance with values loaded from the supplied location -->
<util:properties id="jdbcConfiguration" location="classpath:com/foo/jdbc-production.properties"/>
----
[[xsd-schemas-util-list]]
=== Using `<util:list/>`
Consider the following example:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- creates a java.util.List instance with values loaded from the supplied 'sourceList' -->
<bean id="emails" class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
<value>pechorin@hero.org</value>
<value>raskolnikov@slums.org</value>
<value>stavrogin@gov.org</value>
<value>porfiry@gov.org</value>
</list>
</property>
</bean>
----
The preceding configuration uses a Spring `FactoryBean` implementation (the
`ListFactoryBean`) to create a `java.util.List` instance and initialize it with values taken
from the supplied `sourceList`.
The following example uses a `<util:list/>` element to make a more concise representation:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- creates a java.util.List instance with the supplied values -->
<util:list id="emails">
<value>pechorin@hero.org</value>
<value>raskolnikov@slums.org</value>
<value>stavrogin@gov.org</value>
<value>porfiry@gov.org</value>
</util:list>
----
You can also explicitly control the exact type of `List` that is instantiated and
populated by using the `list-class` attribute on the `<util:list/>` element. For
example, if we really need a `java.util.LinkedList` to be instantiated, we could use the
following configuration:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<util:list id="emails" list-class="java.util.LinkedList">
<value>jackshaftoe@vagabond.org</value>
<value>eliza@thinkingmanscrumpet.org</value>
<value>vanhoek@pirate.org</value>
<value>d'Arcachon@nemesis.org</value>
</util:list>
----
If no `list-class` attribute is supplied, the container chooses a `List` implementation.
[[xsd-schemas-util-map]]
=== Using `<util:map/>`
Consider the following example:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- creates a java.util.Map instance with values loaded from the supplied 'sourceMap' -->
<bean id="emails" class="org.springframework.beans.factory.config.MapFactoryBean">
<property name="sourceMap">
<map>
<entry key="pechorin" value="pechorin@hero.org"/>
<entry key="raskolnikov" value="raskolnikov@slums.org"/>
<entry key="stavrogin" value="stavrogin@gov.org"/>
<entry key="porfiry" value="porfiry@gov.org"/>
</map>
</property>
</bean>
----
The preceding configuration uses a Spring `FactoryBean` implementation (the
`MapFactoryBean`) to create a `java.util.Map` instance initialized with key-value pairs
taken from the supplied `'sourceMap'`.
The following example uses a `<util:map/>` element to make a more concise representation:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- creates a java.util.Map instance with the supplied key-value pairs -->
<util:map id="emails">
<entry key="pechorin" value="pechorin@hero.org"/>
<entry key="raskolnikov" value="raskolnikov@slums.org"/>
<entry key="stavrogin" value="stavrogin@gov.org"/>
<entry key="porfiry" value="porfiry@gov.org"/>
</util:map>
----
You can also explicitly control the exact type of `Map` that is instantiated and
populated by using the `'map-class'` attribute on the `<util:map/>` element. For
example, if we really need a `java.util.TreeMap` to be instantiated, we could use the
following configuration:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<util:map id="emails" map-class="java.util.TreeMap">
<entry key="pechorin" value="pechorin@hero.org"/>
<entry key="raskolnikov" value="raskolnikov@slums.org"/>
<entry key="stavrogin" value="stavrogin@gov.org"/>
<entry key="porfiry" value="porfiry@gov.org"/>
</util:map>
----
If no `'map-class'` attribute is supplied, the container chooses a `Map` implementation.
[[xsd-schemas-util-set]]
=== Using `<util:set/>`
Consider the following example:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- creates a java.util.Set instance with values loaded from the supplied 'sourceSet' -->
<bean id="emails" class="org.springframework.beans.factory.config.SetFactoryBean">
<property name="sourceSet">
<set>
<value>pechorin@hero.org</value>
<value>raskolnikov@slums.org</value>
<value>stavrogin@gov.org</value>
<value>porfiry@gov.org</value>
</set>
</property>
</bean>
----
The preceding configuration uses a Spring `FactoryBean` implementation (the
`SetFactoryBean`) to create a `java.util.Set` instance initialized with values taken
from the supplied `sourceSet`.
The following example uses a `<util:set/>` element to make a more concise representation:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- creates a java.util.Set instance with the supplied values -->
<util:set id="emails">
<value>pechorin@hero.org</value>
<value>raskolnikov@slums.org</value>
<value>stavrogin@gov.org</value>
<value>porfiry@gov.org</value>
</util:set>
----
You can also explicitly control the exact type of `Set` that is instantiated and
populated by using the `set-class` attribute on the `<util:set/>` element. For
example, if we really need a `java.util.TreeSet` to be instantiated, we could use the
following configuration:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<util:set id="emails" set-class="java.util.TreeSet">
<value>pechorin@hero.org</value>
<value>raskolnikov@slums.org</value>
<value>stavrogin@gov.org</value>
<value>porfiry@gov.org</value>
</util:set>
----
If no `set-class` attribute is supplied, the container chooses a `Set` implementation.
[[xsd-schemas-aop]]
== The `aop` Schema
The `aop` tags deal with configuring all things AOP in Spring, including Spring's
own proxy-based AOP framework and Spring's integration with the AspectJ AOP framework.
These tags are comprehensively covered in the chapter entitled xref:core/aop.adoc[Aspect Oriented Programming with Spring]
.
In the interest of completeness, to use the tags in the `aop` schema, you need to have
the following preamble at the top of your Spring XML configuration file (the text in the
snippet references the correct schema so that the tags in the `aop` namespace
are available to you):
[source,xml,indent=0,subs="verbatim,quotes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- bean definitions here -->
</beans>
----
[[xsd-schemas-context]]
== The `context` Schema
The `context` tags deal with `ApplicationContext` configuration that relates to plumbing
-- that is, not usually beans that are important to an end-user but rather beans that do
a lot of the "`grunt`" work in Spring, such as `BeanfactoryPostProcessors`. The following
snippet references the correct schema so that the elements in the `context` namespace are
available to you:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- bean definitions here -->
</beans>
----
[[xsd-schemas-context-pphc]]
=== Using `<property-placeholder/>`
This element activates the replacement of `${...}` placeholders, which are resolved against a
specified properties file (as a xref:web/webflux-webclient/client-builder.adoc#webflux-client-builder-reactor-resources[Spring resource location]). This element
is a convenience mechanism that sets up a xref:core/beans/factory-extension.adoc#beans-factory-placeholderconfigurer[`PropertySourcesPlaceholderConfigurer`]
for you. If you need more control over the specific
`PropertySourcesPlaceholderConfigurer` setup, you can explicitly define it as a bean yourself.
[[xsd-schemas-context-ac]]
=== Using `<annotation-config/>`
This element activates the Spring infrastructure to detect annotations in bean classes:
* Spring's xref:core/beans/basics.adoc#beans-factory-metadata[`@Configuration`] model
* xref:core/beans/annotation-config.adoc[`@Autowired`/`@Inject`], `@Value`, and `@Lookup`
* JSR-250's `@Resource`, `@PostConstruct`, and `@PreDestroy` (if available)
* JAX-WS's `@WebServiceRef` and EJB 3's `@EJB` (if available)
* JPA's `@PersistenceContext` and `@PersistenceUnit` (if available)
* Spring's xref:core/beans/context-introduction.adoc#context-functionality-events-annotation[`@EventListener`]
Alternatively, you can choose to explicitly activate the individual `BeanPostProcessors`
for those annotations.
NOTE: This element does not activate processing of Spring's
xref:data-access/transaction/declarative/annotations.adoc[`@Transactional`] annotation;
you can use the <<data-access.adoc#tx-decl-explained, `<tx:annotation-driven/>`>>
element for that purpose. Similarly, Spring's
xref:integration/cache/annotations.adoc[caching annotations] need to be explicitly
xref:integration/cache/annotations.adoc#cache-annotation-enable[enabled] as well.
[[xsd-schemas-context-component-scan]]
=== Using `<component-scan/>`
This element is detailed in the section on xref:core/beans/annotation-config.adoc[annotation-based container configuration]
.
[[xsd-schemas-context-ltw]]
=== Using `<load-time-weaver/>`
This element is detailed in the section on xref:core/aop/using-aspectj.adoc#aop-aj-ltw[load-time weaving with AspectJ in the Spring Framework]
.
[[xsd-schemas-context-sc]]
=== Using `<spring-configured/>`
This element is detailed in the section on xref:core/aop/using-aspectj.adoc#aop-atconfigurable[using AspectJ to dependency inject domain objects with Spring]
.
[[xsd-schemas-context-mbe]]
=== Using `<mbean-export/>`
This element is detailed in the section on xref:integration/jmx/naming.adoc#jmx-context-mbeanexport[configuring annotation-based MBean export]
.
[[xsd-schemas-beans]]
== The Beans Schema
Last but not least, we have the elements in the `beans` schema. These elements
have been in Spring since the very dawn of the framework. Examples of the various elements
in the `beans` schema are not shown here because they are quite comprehensively covered
in xref:core/beans/dependencies/factory-properties-detailed.adoc[dependencies and configuration in detail]
(and, indeed, in that entire xref:web/webmvc-view/mvc-xslt.adoc#mvc-view-xslt-beandefs[chapter]).
Note that you can add zero or more key-value pairs to `<bean/>` XML definitions.
What, if anything, is done with this extra metadata is totally up to your own custom
logic (and so is typically only of use if you write your own custom elements as described
in the appendix entitled xref:core/appendix/xml-custom.adoc[XML Schema Authoring]).
The following example shows the `<meta/>` element in the context of a surrounding `<bean/>`
(note that, without any logic to interpret it, the metadata is effectively useless
as it stands).
[source,xml,indent=0,subs="verbatim,quotes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="foo" class="x.y.Foo">
<meta key="cacheName" value="foo"/> <1>
<property name="name" value="Rick"/>
</bean>
</beans>
----
<1> This is the example `meta` element
In the case of the preceding example, you could assume that there is some logic that consumes
the bean definition and sets up some caching infrastructure that uses the supplied metadata.
@@ -0,0 +1,9 @@
[[beans]]
= The IoC Container
:page-section-summary-toc: 1
This chapter covers Spring's Inversion of Control (IoC) container.
@@ -0,0 +1,81 @@
[[beans-annotation-config]]
= Annotation-based Container Configuration
.Are annotations better than XML for configuring Spring?
****
The introduction of annotation-based configuration raised the question of whether this
approach is "`better`" than XML. The short answer is "`it depends.`" The long answer is
that each approach has its pros and cons, and, usually, it is up to the developer to
decide which strategy suits them better. Due to the way they are defined, annotations
provide a lot of context in their declaration, leading to shorter and more concise
configuration. However, XML excels at wiring up components without touching their source
code or recompiling them. Some developers prefer having the wiring close to the source
while others argue that annotated classes are no longer POJOs and, furthermore, that the
configuration becomes decentralized and harder to control.
No matter the choice, Spring can accommodate both styles and even mix them together.
It is worth pointing out that through its xref:core/beans/java.adoc[JavaConfig] option, Spring lets
annotations be used in a non-invasive way, without touching the target components'
source code and that, in terms of tooling, all configuration styles are supported by
https://spring.io/tools[Spring Tools] for Eclipse, Visual Studio Code, and Theia.
****
An alternative to XML setup is provided by annotation-based configuration, which relies
on bytecode metadata for wiring up components instead of XML declarations. Instead of
using XML to describe a bean wiring, the developer moves the configuration into the
component class itself by using annotations on the relevant class, method, or field
declaration. As mentioned in xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp-examples-aabpp[Example: The `AutowiredAnnotationBeanPostProcessor`], using a
`BeanPostProcessor` in conjunction with annotations is a common means of extending the
Spring IoC container. For example, the xref:core/beans/annotation-config/autowired.adoc[`@Autowired`]
annotation provides the same capabilities as described in xref:core/beans/dependencies/factory-autowire.adoc[Autowiring Collaborators] but
with more fine-grained control and wider applicability. In addition, Spring provides
support for JSR-250 annotations, such as `@PostConstruct` and `@PreDestroy`, as well as
support for JSR-330 (Dependency Injection for Java) annotations contained in the
`jakarta.inject` package such as `@Inject` and `@Named`. Details about those annotations
can be found in the xref:core/beans/standard-annotations.adoc[relevant section].
[NOTE]
====
Annotation injection is performed before XML injection. Thus, the XML configuration
overrides the annotations for properties wired through both approaches.
====
As always, you can register the post-processors as individual bean definitions, but they
can also be implicitly registered by including the following tag in an XML-based Spring
configuration (notice the inclusion of the `context` namespace):
[source,xml,indent=0,subs="verbatim,quotes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
----
The `<context:annotation-config/>` element implicitly registers the following post-processors:
* {api-spring-framework}/context/annotation/ConfigurationClassPostProcessor.html[`ConfigurationClassPostProcessor`]
* {api-spring-framework}/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html[`AutowiredAnnotationBeanPostProcessor`]
* {api-spring-framework}/context/annotation/CommonAnnotationBeanPostProcessor.html[`CommonAnnotationBeanPostProcessor`]
* {api-spring-framework}/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.html[`PersistenceAnnotationBeanPostProcessor`]
* {api-spring-framework}/context/event/EventListenerMethodProcessor.html[`EventListenerMethodProcessor`]
[NOTE]
====
`<context:annotation-config/>` only looks for annotations on beans in the same
application context in which it is defined. This means that, if you put
`<context:annotation-config/>` in a `WebApplicationContext` for a `DispatcherServlet`,
it only checks for `@Autowired` beans in your controllers, and not your services. See
xref:web/webmvc/mvc-servlet.adoc[The DispatcherServlet] for more information.
====
@@ -0,0 +1,114 @@
[[beans-autowired-annotation-primary]]
= Fine-tuning Annotation-based Autowiring with `@Primary`
Because autowiring by type may lead to multiple candidates, it is often necessary to have
more control over the selection process. One way to accomplish this is with Spring's
`@Primary` annotation. `@Primary` indicates that a particular bean should be given
preference when multiple beans are candidates to be autowired to a single-valued
dependency. If exactly one primary bean exists among the candidates, it becomes the
autowired value.
Consider the following configuration that defines `firstMovieCatalog` as the
primary `MovieCatalog`:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... }
@Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@Configuration
class MovieConfiguration {
@Bean
@Primary
fun firstMovieCatalog(): MovieCatalog { ... }
@Bean
fun secondMovieCatalog(): MovieCatalog { ... }
// ...
}
----
======
With the preceding configuration, the following `MovieRecommender` is autowired with the
`firstMovieCatalog`:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class MovieRecommender {
@Autowired
private lateinit var movieCatalog: MovieCatalog
// ...
}
----
======
The corresponding bean definitions follow:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog" primary="true">
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
----
@@ -0,0 +1,585 @@
[[beans-autowired-annotation-qualifiers]]
= Fine-tuning Annotation-based Autowiring with Qualifiers
`@Primary` is an effective way to use autowiring by type with several instances when one
primary candidate can be determined. When you need more control over the selection process,
you can use Spring's `@Qualifier` annotation. You can associate qualifier values
with specific arguments, narrowing the set of type matches so that a specific bean is
chosen for each argument. In the simplest case, this can be a plain descriptive value, as
shown in the following example:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class MovieRecommender {
@Autowired
@Qualifier("main")
private MovieCatalog movieCatalog;
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class MovieRecommender {
@Autowired
@Qualifier("main")
private lateinit var movieCatalog: MovieCatalog
// ...
}
----
======
--
You can also specify the `@Qualifier` annotation on individual constructor arguments or
method parameters, as shown in the following example:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class MovieRecommender {
private final MovieCatalog movieCatalog;
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(@Qualifier("main") MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class MovieRecommender {
private lateinit var movieCatalog: MovieCatalog
private lateinit var customerPreferenceDao: CustomerPreferenceDao
@Autowired
fun prepare(@Qualifier("main") movieCatalog: MovieCatalog,
customerPreferenceDao: CustomerPreferenceDao) {
this.movieCatalog = movieCatalog
this.customerPreferenceDao = customerPreferenceDao
}
// ...
}
----
======
--
The following example shows corresponding bean definitions.
--
[source,xml,indent=0,subs="verbatim,quotes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier value="main"/> <1>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier value="action"/> <2>
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
----
<1> The bean with the `main` qualifier value is wired with the constructor argument that
is qualified with the same value.
<2> The bean with the `action` qualifier value is wired with the constructor argument that
is qualified with the same value.
--
For a fallback match, the bean name is considered a default qualifier value. Thus, you
can define the bean with an `id` of `main` instead of the nested qualifier element, leading
to the same matching result. However, although you can use this convention to refer to
specific beans by name, `@Autowired` is fundamentally about type-driven injection with
optional semantic qualifiers. This means that qualifier values, even with the bean name
fallback, always have narrowing semantics within the set of type matches. They do not
semantically express a reference to a unique bean `id`. Good qualifier values are `main`
or `EMEA` or `persistent`, expressing characteristics of a specific component that are
independent from the bean `id`, which may be auto-generated in case of an anonymous bean
definition such as the one in the preceding example.
Qualifiers also apply to typed collections, as discussed earlier -- for example, to
`Set<MovieCatalog>`. In this case, all matching beans, according to the declared
qualifiers, are injected as a collection. This implies that qualifiers do not have to be
unique. Rather, they constitute filtering criteria. For example, you can define
multiple `MovieCatalog` beans with the same qualifier value "`action`", all of which are
injected into a `Set<MovieCatalog>` annotated with `@Qualifier("action")`.
[TIP]
====
Letting qualifier values select against target bean names, within the type-matching
candidates, does not require a `@Qualifier` annotation at the injection point.
If there is no other resolution indicator (such as a qualifier or a primary marker),
for a non-unique dependency situation, Spring matches the injection point name
(that is, the field name or parameter name) against the target bean names and chooses the
same-named candidate, if any.
====
That said, if you intend to express annotation-driven injection by name, do not
primarily use `@Autowired`, even if it is capable of selecting by bean name among
type-matching candidates. Instead, use the JSR-250 `@Resource` annotation, which is
semantically defined to identify a specific target component by its unique name, with
the declared type being irrelevant for the matching process. `@Autowired` has rather
different semantics: After selecting candidate beans by type, the specified `String`
qualifier value is considered within those type-selected candidates only (for example,
matching an `account` qualifier against beans marked with the same qualifier label).
For beans that are themselves defined as a collection, `Map`, or array type, `@Resource`
is a fine solution, referring to the specific collection or array bean by unique name.
That said, as of 4.3, you can match collection, `Map`, and array types through Spring's
`@Autowired` type matching algorithm as well, as long as the element type information
is preserved in `@Bean` return type signatures or collection inheritance hierarchies.
In this case, you can use qualifier values to select among same-typed collections,
as outlined in the previous paragraph.
As of 4.3, `@Autowired` also considers self references for injection (that is, references
back to the bean that is currently injected). Note that self injection is a fallback.
Regular dependencies on other components always have precedence. In that sense, self
references do not participate in regular candidate selection and are therefore in
particular never primary. On the contrary, they always end up as lowest precedence.
In practice, you should use self references as a last resort only (for example, for
calling other methods on the same instance through the bean's transactional proxy).
Consider factoring out the affected methods to a separate delegate bean in such a scenario.
Alternatively, you can use `@Resource`, which may obtain a proxy back to the current bean
by its unique name.
[NOTE]
====
Trying to inject the results from `@Bean` methods on the same configuration class is
effectively a self-reference scenario as well. Either lazily resolve such references
in the method signature where it is actually needed (as opposed to an autowired field
in the configuration class) or declare the affected `@Bean` methods as `static`,
decoupling them from the containing configuration class instance and its lifecycle.
Otherwise, such beans are only considered in the fallback phase, with matching beans
on other configuration classes selected as primary candidates instead (if available).
====
`@Autowired` applies to fields, constructors, and multi-argument methods, allowing for
narrowing through qualifier annotations at the parameter level. In contrast, `@Resource`
is supported only for fields and bean property setter methods with a single argument.
As a consequence, you should stick with qualifiers if your injection target is a
constructor or a multi-argument method.
You can create your own custom qualifier annotations. To do so, define an annotation and
provide the `@Qualifier` annotation within your definition, as the following example shows:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {
String value();
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER)
@Retention(AnnotationRetention.RUNTIME)
@Qualifier
annotation class Genre(val value: String)
----
======
--
Then you can provide the custom qualifier on autowired fields and parameters, as the
following example shows:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class MovieRecommender {
@Autowired
@Genre("Action")
private MovieCatalog actionCatalog;
private MovieCatalog comedyCatalog;
@Autowired
public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) {
this.comedyCatalog = comedyCatalog;
}
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class MovieRecommender {
@Autowired
@Genre("Action")
private lateinit var actionCatalog: MovieCatalog
private lateinit var comedyCatalog: MovieCatalog
@Autowired
fun setComedyCatalog(@Genre("Comedy") comedyCatalog: MovieCatalog) {
this.comedyCatalog = comedyCatalog
}
// ...
}
----
======
--
Next, you can provide the information for the candidate bean definitions. You can add
`<qualifier/>` tags as sub-elements of the `<bean/>` tag and then specify the `type` and
`value` to match your custom qualifier annotations. The type is matched against the
fully-qualified class name of the annotation. Alternately, as a convenience if no risk of
conflicting names exists, you can use the short class name. The following example
demonstrates both approaches:
--
[source,xml,indent=0,subs="verbatim,quotes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier type="Genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier type="example.Genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
----
--
In xref:core/beans/classpath-scanning.adoc[Classpath Scanning and Managed Components], you can see an annotation-based alternative to
providing the qualifier metadata in XML. Specifically, see xref:core/beans/classpath-scanning.adoc#beans-scanning-qualifiers[Providing Qualifier Metadata with Annotations].
In some cases, using an annotation without a value may suffice. This can be
useful when the annotation serves a more generic purpose and can be applied across
several different types of dependencies. For example, you may provide an offline
catalog that can be searched when no Internet connection is available. First, define
the simple annotation, as the following example shows:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Offline {
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER)
@Retention(AnnotationRetention.RUNTIME)
@Qualifier
annotation class Offline
----
======
--
Then add the annotation to the field or property to be autowired, as shown in the
following example:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class MovieRecommender {
@Autowired
@Offline // <1>
private MovieCatalog offlineCatalog;
// ...
}
----
<1> This line adds the `@Offline` annotation.
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class MovieRecommender {
@Autowired
@Offline // <1>
private lateinit var offlineCatalog: MovieCatalog
// ...
}
----
<1> This line adds the `@Offline` annotation.
======
--
Now the bean definition only needs a qualifier `type`, as shown in the following example:
--
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean class="example.SimpleMovieCatalog">
<qualifier type="Offline"/> <1>
<!-- inject any dependencies required by this bean -->
</bean>
----
<1> This element specifies the qualifier.
--
You can also define custom qualifier annotations that accept named attributes in
addition to or instead of the simple `value` attribute. If multiple attribute values are
then specified on a field or parameter to be autowired, a bean definition must match
all such attribute values to be considered an autowire candidate. As an example,
consider the following annotation definition:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MovieQualifier {
String genre();
Format format();
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER)
@Retention(AnnotationRetention.RUNTIME)
@Qualifier
annotation class MovieQualifier(val genre: String, val format: Format)
----
======
--
In this case `Format` is an enum, defined as follows:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public enum Format {
VHS, DVD, BLURAY
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
enum class Format {
VHS, DVD, BLURAY
}
----
======
--
The fields to be autowired are annotated with the custom qualifier and include values
for both attributes: `genre` and `format`, as the following example shows:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class MovieRecommender {
@Autowired
@MovieQualifier(format=Format.VHS, genre="Action")
private MovieCatalog actionVhsCatalog;
@Autowired
@MovieQualifier(format=Format.VHS, genre="Comedy")
private MovieCatalog comedyVhsCatalog;
@Autowired
@MovieQualifier(format=Format.DVD, genre="Action")
private MovieCatalog actionDvdCatalog;
@Autowired
@MovieQualifier(format=Format.BLURAY, genre="Comedy")
private MovieCatalog comedyBluRayCatalog;
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class MovieRecommender {
@Autowired
@MovieQualifier(format = Format.VHS, genre = "Action")
private lateinit var actionVhsCatalog: MovieCatalog
@Autowired
@MovieQualifier(format = Format.VHS, genre = "Comedy")
private lateinit var comedyVhsCatalog: MovieCatalog
@Autowired
@MovieQualifier(format = Format.DVD, genre = "Action")
private lateinit var actionDvdCatalog: MovieCatalog
@Autowired
@MovieQualifier(format = Format.BLURAY, genre = "Comedy")
private lateinit var comedyBluRayCatalog: MovieCatalog
// ...
}
----
======
--
Finally, the bean definitions should contain matching qualifier values. This example
also demonstrates that you can use bean meta attributes instead of the
`<qualifier/>` elements. If available, the `<qualifier/>` element and its attributes take
precedence, but the autowiring mechanism falls back on the values provided within the
`<meta/>` tags if no such qualifier is present, as in the last two bean definitions in
the following example:
--
[source,xml,indent=0,subs="verbatim,quotes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier type="MovieQualifier">
<attribute key="format" value="VHS"/>
<attribute key="genre" value="Action"/>
</qualifier>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier type="MovieQualifier">
<attribute key="format" value="VHS"/>
<attribute key="genre" value="Comedy"/>
</qualifier>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<meta key="format" value="DVD"/>
<meta key="genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<meta key="format" value="BLURAY"/>
<meta key="genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
</bean>
</beans>
----
--
@@ -0,0 +1,490 @@
[[beans-autowired-annotation]]
= Using `@Autowired`
[NOTE]
====
JSR 330's `@Inject` annotation can be used in place of Spring's `@Autowired` annotation in the
examples included in this section. See xref:core/beans/standard-annotations.adoc[here] for more details.
====
You can apply the `@Autowired` annotation to constructors, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class MovieRecommender @Autowired constructor(
private val customerPreferenceDao: CustomerPreferenceDao)
----
======
[NOTE]
====
As of Spring Framework 4.3, an `@Autowired` annotation on such a constructor is no longer
necessary if the target bean defines only one constructor to begin with. However, if
several constructors are available and there is no primary/default constructor, at least
one of the constructors must be annotated with `@Autowired` in order to instruct the
container which one to use. See the discussion on
xref:core/beans/annotation-config/autowired.adoc#beans-autowired-annotation-constructor-resolution[constructor resolution] for details.
====
You can also apply the `@Autowired` annotation to _traditional_ setter methods,
as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class SimpleMovieLister {
@set:Autowired
lateinit var movieFinder: MovieFinder
// ...
}
----
======
You can also apply the annotation to methods with arbitrary names and multiple
arguments, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class MovieRecommender {
private lateinit var movieCatalog: MovieCatalog
private lateinit var customerPreferenceDao: CustomerPreferenceDao
@Autowired
fun prepare(movieCatalog: MovieCatalog,
customerPreferenceDao: CustomerPreferenceDao) {
this.movieCatalog = movieCatalog
this.customerPreferenceDao = customerPreferenceDao
}
// ...
}
----
======
You can apply `@Autowired` to fields as well and even mix it with constructors, as the
following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
private MovieCatalog movieCatalog;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class MovieRecommender @Autowired constructor(
private val customerPreferenceDao: CustomerPreferenceDao) {
@Autowired
private lateinit var movieCatalog: MovieCatalog
// ...
}
----
======
[TIP]
====
Make sure that your target components (for example, `MovieCatalog` or `CustomerPreferenceDao`)
are consistently declared by the type that you use for your `@Autowired`-annotated
injection points. Otherwise, injection may fail due to a "no type match found" error at runtime.
For XML-defined beans or component classes found via classpath scanning, the container
usually knows the concrete type up front. However, for `@Bean` factory methods, you need
to make sure that the declared return type is sufficiently expressive. For components
that implement several interfaces or for components potentially referred to by their
implementation type, consider declaring the most specific return type on your factory
method (at least as specific as required by the injection points referring to your bean).
====
You can also instruct Spring to provide all beans of a particular type from the
`ApplicationContext` by adding the `@Autowired` annotation to a field or method that
expects an array of that type, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class MovieRecommender {
@Autowired
private MovieCatalog[] movieCatalogs;
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class MovieRecommender {
@Autowired
private lateinit var movieCatalogs: Array<MovieCatalog>
// ...
}
----
======
The same applies for typed collections, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class MovieRecommender {
private Set<MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class MovieRecommender {
@Autowired
lateinit var movieCatalogs: Set<MovieCatalog>
// ...
}
----
======
[[beans-factory-ordered]]
[TIP]
====
Your target beans can implement the `org.springframework.core.Ordered` interface or use
the `@Order` or standard `@Priority` annotation if you want items in the array or list
to be sorted in a specific order. Otherwise, their order follows the registration
order of the corresponding target bean definitions in the container.
You can declare the `@Order` annotation at the target class level and on `@Bean` methods,
potentially for individual bean definitions (in case of multiple definitions that
use the same bean class). `@Order` values may influence priorities at injection points,
but be aware that they do not influence singleton startup order, which is an
orthogonal concern determined by dependency relationships and `@DependsOn` declarations.
Note that the standard `jakarta.annotation.Priority` annotation is not available at the
`@Bean` level, since it cannot be declared on methods. Its semantics can be modeled
through `@Order` values in combination with `@Primary` on a single bean for each type.
====
Even typed `Map` instances can be autowired as long as the expected key type is `String`.
The map values contain all beans of the expected type, and the keys contain the
corresponding bean names, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class MovieRecommender {
private Map<String, MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class MovieRecommender {
@Autowired
lateinit var movieCatalogs: Map<String, MovieCatalog>
// ...
}
----
======
By default, autowiring fails when no matching candidate beans are available for a given
injection point. In the case of a declared array, collection, or map, at least one
matching element is expected.
The default behavior is to treat annotated methods and fields as indicating required
dependencies. You can change this behavior as demonstrated in the following example,
enabling the framework to skip a non-satisfiable injection point through marking it as
non-required (i.e., by setting the `required` attribute in `@Autowired` to `false`):
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired(required = false)
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class SimpleMovieLister {
@Autowired(required = false)
var movieFinder: MovieFinder? = null
// ...
}
----
======
[NOTE]
====
A non-required method will not be called at all if its dependency (or one of its
dependencies, in case of multiple arguments) is not available. A non-required field will
not get populated at all in such cases, leaving its default value in place.
In other words, setting the `required` attribute to `false` indicates that the
corresponding property is _optional_ for autowiring purposes, and the property will be
ignored if it cannot be autowired. This allows properties to be assigned default values
that can be optionally overridden via dependency injection.
====
[[beans-autowired-annotation-constructor-resolution]]
Injected constructor and factory method arguments are a special case since the `required`
attribute in `@Autowired` has a somewhat different meaning due to Spring's constructor
resolution algorithm that may potentially deal with multiple constructors. Constructor
and factory method arguments are effectively required by default but with a few special
rules in a single-constructor scenario, such as multi-element injection points (arrays,
collections, maps) resolving to empty instances if no matching beans are available. This
allows for a common implementation pattern where all dependencies can be declared in a
unique multi-argument constructor — for example, declared as a single public constructor
without an `@Autowired` annotation.
[NOTE]
====
Only one constructor of any given bean class may declare `@Autowired` with the `required`
attribute set to `true`, indicating _the_ constructor to autowire when used as a Spring
bean. As a consequence, if the `required` attribute is left at its default value `true`,
only a single constructor may be annotated with `@Autowired`. If multiple constructors
declare the annotation, they will all have to declare `required=false` in order to be
considered as candidates for autowiring (analogous to `autowire=constructor` in XML).
The constructor with the greatest number of dependencies that can be satisfied by matching
beans in the Spring container will be chosen. If none of the candidates can be satisfied,
then a primary/default constructor (if present) will be used. Similarly, if a class
declares multiple constructors but none of them is annotated with `@Autowired`, then a
primary/default constructor (if present) will be used. If a class only declares a single
constructor to begin with, it will always be used, even if not annotated. Note that an
annotated constructor does not have to be public.
====
Alternatively, you can express the non-required nature of a particular dependency
through Java 8's `java.util.Optional`, as the following example shows:
[source,java,indent=0,subs="verbatim,quotes"]
----
public class SimpleMovieLister {
@Autowired
public void setMovieFinder(Optional<MovieFinder> movieFinder) {
...
}
}
----
As of Spring Framework 5.0, you can also use a `@Nullable` annotation (of any kind
in any package -- for example, `javax.annotation.Nullable` from JSR-305) or just leverage
Kotlin built-in null-safety support:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class SimpleMovieLister {
@Autowired
public void setMovieFinder(@Nullable MovieFinder movieFinder) {
...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class SimpleMovieLister {
@Autowired
var movieFinder: MovieFinder? = null
// ...
}
----
======
You can also use `@Autowired` for interfaces that are well-known resolvable
dependencies: `BeanFactory`, `ApplicationContext`, `Environment`, `ResourceLoader`,
`ApplicationEventPublisher`, and `MessageSource`. These interfaces and their extended
interfaces, such as `ConfigurableApplicationContext` or `ResourcePatternResolver`, are
automatically resolved, with no special setup necessary. The following example autowires
an `ApplicationContext` object:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class MovieRecommender {
@Autowired
private ApplicationContext context;
public MovieRecommender() {
}
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class MovieRecommender {
@Autowired
lateinit var context: ApplicationContext
// ...
}
----
======
[NOTE]
====
The `@Autowired`, `@Inject`, `@Value`, and `@Resource` annotations are handled by Spring
`BeanPostProcessor` implementations. This means that you cannot apply these annotations
within your own `BeanPostProcessor` or `BeanFactoryPostProcessor` types (if any).
These types must be 'wired up' explicitly by using XML or a Spring `@Bean` method.
====

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