Compare commits

...

2752 Commits

Author SHA1 Message Date
Spring Builds e6585e0250 Release v6.1.0 2023-11-16 14:21:14 +00:00
rstoyanchev af1b3c72d5 Merge branch '6.0.x' 2023-11-16 11:15:44 +00:00
rstoyanchev 770cbd2fb5 Revise exception handling in HandlerMappingIntrospector
See gh-31588
2023-11-16 11:15:29 +00:00
Juergen Hoeller d1867f1b73 Merge branch '6.0.x' 2023-11-16 11:35:12 +01:00
Juergen Hoeller e5f04e5ddf Polishing 2023-11-16 11:34:31 +01:00
Juergen Hoeller 99378fe947 Polishing 2023-11-16 11:22:09 +01:00
Juergen Hoeller b0e29acd23 Upgrade to SmallRye Mutiny 1.10.0 2023-11-16 11:22:01 +01:00
Brian Clozel c02f735056 Merge branch '6.0.x' 2023-11-16 09:04:09 +01:00
Brian Clozel c18784678d Reduce allocations in server conventions
This commit optimizes the default observation conventions to reduce
`KeyValues` allocations.
2023-11-16 09:00:24 +01:00
Stéphane Nicoll c485e9b74f Merge branch '6.0.x' 2023-11-15 20:50:02 +01:00
Stéphane Nicoll 51cdff591c Merge pull request #31612 from PiotrFLEURY
* pr/31612:
  Polish "Provide invalid class name in exception message"
  Provide invalid class name in exception message

Closes gh-31612
2023-11-15 20:49:55 +01:00
Stéphane Nicoll d93114df9a Polish "Provide invalid class name in exception message"
See gh-31612
2023-11-15 20:45:24 +01:00
PiotrFLEURY 5ac4c3bd76 Provide invalid class name in exception message
See gh-31612
2023-11-15 20:40:45 +01:00
rstoyanchev 3a70c71c5e Merge branch '6.0.x' 2023-11-15 18:57:35 +00:00
rstoyanchev 05c3ffb2fb Use InvalidMimeTypeException in MimeTypeUtils#sortBySpecificity
Closes gh-31254
2023-11-15 18:57:23 +00:00
rstoyanchev 19e8ed130c Cache Filter for HandlerMappingIntrospector and log warnings
See gh-31588
2023-11-15 18:57:23 +00:00
Stéphane Nicoll f15b8b95ad Merge branch '6.0.x' 2023-11-15 19:04:11 +01:00
Sébastien Deleuze 183c2f82b2 Refine @EmbeddableInstantiator reflection hints
Based on @odrotbohm proposal to manage a wider set
of use cases.

Closes gh-31534
2023-11-15 18:48:27 +01:00
Stéphane Nicoll 4464251754 Add missing runtime hints for ProblemDetail mixins
Closes gh-31606
2023-11-15 18:44:17 +01:00
Brian Clozel 8eebb5e27b Polish
See gh-31575
2023-11-15 15:26:49 +01:00
Arjen Poutsma 0ef3cb9b9e Merge branch '6.0.x' 2023-11-15 14:33:55 +01:00
Arjen Poutsma 8868fe2ea5 Fix position bug in NettyDataBuffer::toByteBuffer
Closes gh-31605
2023-11-15 14:23:43 +01:00
Juergen Hoeller ca9634143c Upgrade to Reactor 2023.0.0
Includes Protobuf 3.25.0, Artemis 2.31.2, Checkstyle 10.12.5

Closes gh-31557
2023-11-15 14:06:43 +01:00
Juergen Hoeller 0e6bf098cb Merge branch '6.0.x'
# Conflicts:
#	build.gradle
#	framework-platform/framework-platform.gradle
#	spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java
2023-11-15 13:36:03 +01:00
Juergen Hoeller c373f496f3 Consistent ordering of overloaded operations 2023-11-15 13:29:35 +01:00
Juergen Hoeller eb1883bdc4 Upgrade to Reactor 2022.0.13 and Netty 4.1.101
Includes RxJava 3.1.8, Apache HttpComponents Core Reactive 5.2.3, POI 5.2.4, Commons IO 2.15, WebJars Locator 0.55, OpenPDF 1.3.33, JRuby 9.4.5, H2 2.2.224, ActiveMQ 5.17.6, Checkstyle 10.12.5

Closes gh-31585
2023-11-15 13:29:13 +01:00
Juergen Hoeller 01fc1ee3bb Introduce update variant with KeyHolder and explicit key column names
Closes gh-31607
2023-11-15 12:20:22 +01:00
Stéphane Nicoll 510caad6c3 Merge branch '6.0.x' 2023-11-15 12:07:50 +01:00
Stéphane Nicoll df6f66110f Fix wrong nullability requirement
Closes gh-31610
2023-11-15 12:01:26 +01:00
Sébastien Deleuze 92c3843dae Add required AspectJ field hints
This commit adds reflection hints on fields for
classes compiled by AspectJ.

Closes gh-31575
2023-11-15 10:30:02 +01:00
rstoyanchev e12269ef1a Merge branch '6.0.x' 2023-11-14 20:01:14 +00:00
rstoyanchev ac235a0c43 Fix checkstyle violation 2023-11-14 20:00:16 +00:00
rstoyanchev 2613dfce0b Merge branch '6.0.x' 2023-11-14 19:24:43 +00:00
rstoyanchev a4e3af5cbe Revise HandlerMappingIntrospector caching
Expose methods to set and reset cache to use from a Filter instead
of a method to create such a Filter. Also use cached results only
if they match by dispatcher type and requestURI.

See gh-31588
2023-11-14 19:24:29 +00:00
Sam Brannen 978e81e72e Merge branch '6.0.x' 2023-11-14 15:15:53 +01:00
Sam Brannen e71117dcdf Polish contribution
See gh-31598
2023-11-14 14:46:34 +01:00
Jason d5874ab99e Avoid duplicate resources in PathMatchingResourcePatternResolver on Windows
This commit updates PathMatchingResourcePatternResolver to avoid
returning duplicate resources on MS Windows when searching using the
`classpath*:` prefix and a wildcard pattern that matches resources
which are directly present in a JAR as well as present via classpath
manifest entries.

Closes gh-31598
2023-11-14 14:39:48 +01:00
Juergen Hoeller 2b7a9209b3 Merge branch '6.0.x' 2023-11-14 12:52:25 +01:00
Juergen Hoeller 99327b7db1 Preserve nested square brackets within parameter name
Closes gh-31596
2023-11-14 12:51:19 +01:00
Juergen Hoeller 3e06441d97 Cache SpEL-loaded types in StandardTypeLocator
Closes gh-31579
2023-11-14 12:46:16 +01:00
Arjen Poutsma 8f21479234 Add body conversion capabilities in RestClient::exchange
This commit introduces a ConvertibleClientHttpResponse type that
extends ClientHttpResponse, and that can convert the body to a desired
type. Before this commit, it was not easy to use the configured HTTP
message converters in combination with RestClient::exchange.

Closes gh-31597
2023-11-14 11:18:59 +01:00
Stéphane Nicoll dd97dee7fd Polish 2023-11-13 19:33:09 +01:00
Sébastien Deleuze eb3982b6c2 Property-driven onRefresh exit for AppCDS purpose
This commit allows to terminate the JVM when the
-Dspring.context.exit=onRefresh property is set,
which can be useful for AppCDS training run in order
to get most of the AppCDS cache without starting the
beans.

Closes gh-31595
2023-11-13 15:53:57 +01:00
Brian Clozel 258f99a8bc Merge branch '6.0.x' 2023-11-13 14:29:16 +01:00
Brian Clozel 01f2925048 Upgrade to Micrometer 1.10.13
Closes gh-31586
2023-11-13 14:28:45 +01:00
Brian Clozel dced3539a3 Upgrade to Context Propagation 1.1.0
Closes gh-31599
2023-11-13 14:15:39 +01:00
Brian Clozel bb66885426 Upgrade to Micrometer 1.12.0
Closes gh-31556
2023-11-13 14:15:02 +01:00
Stéphane Nicoll 7f615fd8af Fix reference in deprecation message of parseForwardedFor 2023-11-11 18:05:36 +01:00
rstoyanchev 33b1ff5d27 Merge branch '6.0.x' 2023-11-10 17:45:24 +00:00
rstoyanchev 44a37000ec HandlerMappingIntrospector exposes Filter for caching
Closes gh-31588
2023-11-10 17:43:52 +00:00
rstoyanchev 53fe5fafed Minor refactoring in HandlerMappingIntrospector
See gh-31588
2023-11-10 17:27:54 +00:00
Stéphane Nicoll f5453cc445 Polish 2023-11-10 16:42:43 +01:00
rstoyanchev b9bd98fc5b Polishing in HandlerMappingIntrospector
See gh-31588
2023-11-10 11:27:44 +00:00
Simon Baslé a97ecf7a29 Link to KDoc/Javadoc in their respective counterpart overview pages
This commit adds a link in the package-overview pages of KDoc and
Javadoc, pointing to the other documentation's own page.

In order for local tests to work, the build has been slightly modified
to align with the directory structure in the distributed documentation
zip (and consequently with that of the deployed documentation website).

Lastly, the javadoc build was fixed to include the `overview.html` again
in the resulting HTML index, since this is where the KDoc link is added.

See gh-28055
Closes gh-31587
2023-11-10 11:36:27 +01:00
Sam Brannen 8a7144ba42 Document how to log @⁠Sql scripts and statements
Closes gh-31589
2023-11-10 11:19:38 +01:00
Sam Brannen 6c3a3dc7d9 Polishing 2023-11-10 11:18:26 +01:00
Sam Brannen b1a7161218 Document @⁠Sql class-level execution phase support in the reference manual
Closes gh-31377
2023-11-09 15:22:14 +01:00
Sam Brannen 332de60586 Update @⁠Sql docs regarding Kotlin and Java 8 2023-11-09 15:19:52 +01:00
rstoyanchev 769128a0b2 Merge branch '6.0.x' 2023-11-09 12:53:36 +00:00
rstoyanchev 7714110940 Polishing in DefaultWebClient 2023-11-09 12:53:15 +00:00
rstoyanchev 75d1278bde Include port when logging URI in DefaultWebClient
Closes gh-30519
2023-11-09 12:53:15 +00:00
rstoyanchev d8441fc80c Invoke handleEmptyBody if there is no content-type
Closes gh-30522
2023-11-09 12:53:05 +00:00
Sébastien Deleuze d8ed7c7906 Merge branch '6.0.x' 2023-11-09 13:11:58 +01:00
Sébastien Deleuze 620f558547 Register hints for superclass in BindingReflectionHintsRegistrar
Closes gh-31552
2023-11-09 13:11:36 +01:00
Juergen Hoeller 8841b7c3bb Upgrade to SnakeYAML 2.2 2023-11-09 11:52:02 +01:00
Juergen Hoeller 6c00e6162b Merge branch '6.0.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
#	spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/GenericCallMetaDataProvider.java
2023-11-09 11:50:55 +01:00
Juergen Hoeller 1e78cc35e5 Log4jLog re-resolves ExtendedLogger on deserialization
This is necessary for compatibility with Log4J 2.21, analogous to the existing re-resolution in Spring's SLF4J adapter.

Closes gh-31582
2023-11-09 11:46:22 +01:00
Simon Baslé 42874178ce Polish RecordApplicationEvents javadoc: add note on captured threads
This commit clarifies that the annotation is used to capture events that
are fired from the test `Thread` or descendant threads, since the test
framework uses `InheritableThreadLocal` to store captured events now.

See gh-31079
See gh-30020
2023-11-09 11:07:53 +01:00
Juergen Hoeller 11fdb5ba17 Upgrade to Log4J 2.21.1, Tomcat 10.1.15, Jetty 11.0.18, Undertow 2.3.10, EclipseLink 3.0.4, Mockito 5.7 2023-11-09 10:53:47 +01:00
Juergen Hoeller 9957bb6918 Check for procedure vs function constants in CallMetaDataContext
Closes gh-31550
2023-11-09 10:52:51 +01:00
Juergen Hoeller 9414c2ddba Coordinated stop before destroy when ExecutorService not terminated yet
Closes gh-31549
2023-11-09 10:22:27 +01:00
Sébastien Deleuze 38724a1205 Fix RestClient generic type handling
For client side use case, the context class should be null,
consistently with what is done in HttpMessageConverterExtractor.

Closes gh-31574
2023-11-09 08:50:31 +01:00
Sam Brannen 55d13a0232 Document @⁠DisabledInAotMode & @[Enabled|Disabled]InNativeImage in ref docs
Closes gh-31437
Closes gh-31438
2023-11-08 16:22:35 +01:00
Sam Brannen a207e5e1b0 Ensure framework-docs can be imported into Eclipse IDE 2023-11-08 15:26:09 +01:00
Sam Brannen b7c579954c Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMapping.java
2023-11-08 13:48:22 +01:00
lorenzsimon 6a7a0bddb7 Restore support for recursive annotations in Kotlin
This commit reinstates support for recursive annotations in Kotlin.

See gh-28012
See gh-28618
See gh-31400
Closes gh-31518
2023-11-08 13:28:28 +01:00
rstoyanchev ba4d459f81 Merge branch '6.0.x' 2023-11-08 11:47:18 +00:00
rstoyanchev 5c012bbb0c Set maxAge correctly when expiring WebSession
Closes gh-31214
2023-11-08 11:44:36 +00:00
Stéphane Nicoll d34b3c1a71 Merge branch '6.0.x' 2023-11-08 08:04:27 +01:00
Stéphane Nicoll e943058b18 Merge pull request #31571 from izeye
* pr/31571:
  Add Javadoc since to ProblemDetail.setProperties()

Closes gh-31571
2023-11-08 08:04:10 +01:00
Johnny Lim cafb38ad1d Add Javadoc since to ProblemDetail.setProperties()
See gh-31571
2023-11-08 08:02:57 +01:00
Sam Brannen 9759bf5964 Merge branch '6.0.x' 2023-11-07 17:13:46 +01:00
Sam Brannen e778d2e908 Polish duplicate key exception error code support for SAP HANA database for R2DBC
See gh-31554
2023-11-07 17:12:29 +01:00
Sam Brannen c5bcfc7682 Polish contribution
See gh-31554
2023-11-07 17:08:44 +01:00
Sam Brannen 5752e03d97 Polishing 2023-11-07 16:58:21 +01:00
Arjen Poutsma 5afb00d270 Merge branch '6.0.x' 2023-11-07 15:10:59 +01:00
Arjen Poutsma dc26d3b0ec Defer cleanup in DefaultServerWebExchange
This commit ensures that the multipartRead flag is read in a deferred
block, and is not evaluated too early.

Closes gh-31567
2023-11-07 15:00:20 +01:00
Arjen Poutsma 486503bd31 Buffer writes in JettyClientHttpRequest
This commit ensures that not every OutputStream.write gets written as a
separate chunk, by buffering the written data in a BufferedOutputStream.
In some cases, a large quantity of small writes would result in many
sent chunks.

Closes gh-31361
2023-11-07 14:02:01 +01:00
Arjen Poutsma 0839f5b749 Test form submissions
See gh-31361
2023-11-07 12:27:31 +01:00
Brian Clozel 888d8c15d9 Upgrade CI to Concourse Release Scripts 0.4.0 2023-11-07 11:20:57 +01:00
Brian Clozel dbb2d4f1d3 Extend JMS observation scope to error handling
Prior to this commit, the JMS listener observations would only cover the
actual listener invocation, but not the error handling phase. This means
that all errors (including the handled ones) are marked as errors in the
observation and that the observation is not current anymore when error
handling happens.

This commit aligns the behavior with the other Spring Framework
instrumentations and ensures that the error handling phase is fully part
of the observation recording.

Closes gh-31559
2023-11-07 11:18:03 +01:00
Sébastien Deleuze 9d6bda2b44 Register Hibernate @EmbeddableInstantiator reflection hints
This commit updates PersistenceManagedTypesBeanRegistrationAotProcessor
to register reflection hints for `@EmbeddableInstantiator` annotations
available as of Hibernate 6.0 when needed.

Related tests will be added in
https://github.com/spring-projects/spring-aot-smoke-tests.

Closes gh-31534
2023-11-07 11:04:43 +01:00
Stéphane Nicoll c30b3796f2 Merge branch '6.0.x' 2023-11-07 10:37:22 +01:00
Stéphane Nicoll 7f94c64b72 Merge pull request #31554 from baratrax
* pr/31554:
  Polish "Add SAP HANA duplicate key exception error code"
  Add SAP HANA duplicate key exception error code

Closes gh-31554
2023-11-07 10:37:14 +01:00
Stéphane Nicoll 50e55d5219 Polish "Add SAP HANA duplicate key exception error code"
See gh-31554
2023-11-07 10:33:14 +01:00
Fabrizio De Felice fcd4ba2f1f Add SAP HANA duplicate key exception error code
See gh-31554
2023-11-07 10:27:51 +01:00
wakingrufus 8c77e398b6 Add extension for PropertyResolver#getProperty(String, Class<T>, T)
Allows Kotlin caller to get a non-nullable property,
using a default value when the property is not set.
A method already exists on PropertyResolver which does this,
but takes a Class parameter.
The extension method can eliminate the parameter via reified type,
similar to the other extension methods which exist already.

Closes gh-31523
2023-11-06 15:14:16 +01:00
Sébastien Deleuze 34e5512ff6 Enable PropertyResolverExtensionsKotlinTests
Closes gh-31553
2023-11-06 15:14:16 +01:00
Sam Brannen cd503e3af6 Upgrade to JUnit 5.10.1
Closes gh-31558
2023-11-06 14:57:31 +01:00
rstoyanchev 5df6e8825d Polishing in CookieWebSessionIdResolver
See gh-31214
2023-11-06 11:31:39 +00:00
Brian Clozel 86bb8a015b Document that "error" key is preferred in observations
This commit documents that the "error" key in Micrometer Observations
should be preferred over the legacy "exception" one. Right now the
information is duplicated but we might remove the deprecated one in the
future.

Closes gh-31514
2023-11-06 11:52:27 +01:00
Arjen Poutsma efb93ca109 Fix bug in calculation of maximum form part size
See gh-31343
2023-11-06 11:20:18 +01:00
Sam Brannen b3a6dbaab3 Polishing 2023-11-04 14:45:09 +01:00
Sam Brannen ed49f86dfb Remove obsolete code in ConcurrentReferenceHashMapTests 2023-11-04 14:38:30 +01:00
Sam Brannen 12078e6ec5 Ensure Java runtime container is always properly configured in Eclipse 2023-11-04 14:32:34 +01:00
rstoyanchev 654e822676 Fix Javadoc link 2023-11-03 14:38:53 +00:00
Stéphane Nicoll 24aa6163f0 Polish 2023-11-03 12:10:01 +01:00
rstoyanchev 30e4a0a300 Polishing as a result of discussion under gh-31529 2023-11-02 16:18:25 +00:00
Arjen Poutsma 6dd93d4d85 Allow repeatable writes in HttpMessageConverter
This commit ensures that the StreamingHttpOutputMessage.Body.repeatable
flag is set in message converters for bodies that can be written
repeatedly.

Closes gh-31516
See gh-31449
2023-11-02 15:51:36 +01:00
Stéphane Nicoll ab316d9bc8 Merge branch '6.0.x' 2023-11-02 15:41:18 +01:00
Stéphane Nicoll e73107341c Document that pertypewithin is supported by Spring AOT
Closes gh-25887
2023-11-02 15:39:45 +01:00
Stéphane Nicoll 27b5813591 Merge pull request #31542 from Young-Zen
* pr/31542:
  Fix link in Javadoc of ConfigurableMockMvcBuilder

Closes gh-31542
2023-11-02 14:26:46 +01:00
yanghaojia fe14c85ada Fix link in Javadoc of ConfigurableMockMvcBuilder
See gh-31542
2023-11-02 14:25:35 +01:00
rstoyanchev 4da2440f63 Polishing
Closes gh-31530
2023-11-02 11:32:03 +00:00
Seth Kuipers 9bbe3aa52a Expand support for adapting container type violations
See gh-31530
2023-11-02 11:32:03 +00:00
rstoyanchev f16122d533 Polishing and minor refactoring
Closes gh-31202
2023-11-02 11:32:03 +00:00
Carl-Eric Menzel d54a694f5a Add handler for unknown status codes
See gh-31202
2023-11-02 11:32:03 +00:00
Stéphane Nicoll 9c5dcad0e5 Polish 2023-11-02 11:45:07 +01:00
Stéphane Nicoll b05b5902c0 Upgrade to Kotlin 1.9.20
Closes gh-31539
2023-11-02 09:42:42 +01:00
Stéphane Nicoll 1d38d649fa Relax test that used to rely on localized message
This reverts commit 93206c3f6e and updates
the related test to only rely on the fact the compiler fails. Relying
on a message will not work and the status code can be implementation
independent according to its javadoc.

Closes gh-31536
2023-11-01 16:33:44 +01:00
Sam Brannen a5841fede5 Polishing 2023-11-01 16:23:18 +01:00
rstoyanchev 2a5653c7d6 Merge branch '6.0.x' 2023-11-01 13:26:34 +00:00
rstoyanchev f8a33cd66e Remove outdated reference to Netty in rest-clients section
Closes gh-31526
2023-11-01 13:25:16 +00:00
Stéphane Nicoll 115a46c5e8 Polish 2023-10-31 17:58:13 +01:00
Stéphane Nicoll 199d5e5f37 Polish 2023-10-31 13:02:01 +01:00
Sam Brannen 3d248607dc Update copyright headers 2023-10-30 15:21:02 +01:00
Sam Brannen 574c57739e Further polishing 2023-10-30 15:10:13 +01:00
Johnny Lim 2b750926c3 Polishing
Closes gh-31522
2023-10-30 15:05:20 +01:00
Sam Brannen 8a2acbeac1 Merge branch '6.0.x' 2023-10-30 13:32:08 +01:00
CroBurnt f088d4a05b Fix link text in @⁠Transactional section of ref docs
Closes gh-31519
2023-10-30 13:29:30 +01:00
Sam Brannen 8770544769 Remove classpath entries for non-existent libraries added by mrjar plugin
The me.champeau.mrjar Gradle plugin causes non-existent libraries to be
added to the Eclipse classpath, such as:

<classpathentry kind="lib" path="/workspaces/spring-framework/spring-core/build/classes/kotlin/java21">
  <attributes>
    <attribute name="gradle_used_by_scope" value="java21"/>
    <attribute name="test" value="true"/>
  </attributes>
</classpathentry>

This results in build errors in Eclipse IDE like the following.

Project 'spring-core' is missing required library:
  '/workspaces/spring-framework/spring-core/build/classes/kotlin/java21'

This commit filters those and removes them.
2023-10-29 12:03:40 +01:00
Sam Brannen fc77172d67 Remove recursive project dependencies from Eclipse classpath 2023-10-29 11:25:53 +01:00
Sam Brannen de74520286 Upgrade to JMH plugin 0.7.2
Closes gh-31517
2023-10-29 11:09:48 +01:00
Sam Brannen cb9382d986 Polishing 2023-10-29 10:16:32 +01:00
Sam Brannen c7bb981db1 Ensure it's possible to extend ControlFlowPointcut with RegEx support
Commit d3fba6d49b introduced built-in pattern matching support for
method names in ControlFlowPointcut; however, it was still cumbersome
to extend ControlFlowPointcut with support for regular expressions
instead of simple pattern matching.

To address that, this commit introduces a variant of isMatch() that
accepts the pattern index instead of the pre-resolved method name
pattern. The default implementation retrieves the method name pattern
from the methodNamePatterns field and delegates to isMatch(String, String).

Subclasses can override the new isMatch(String, int) method to support
regular expressions, as can be seen in the example
RegExControlFlowPointcut class in ControlFlowPointcutTests.

See gh-31435
2023-10-28 16:30:02 +02:00
Sam Brannen 7f1beb0140 Polishing 2023-10-28 16:24:59 +02:00
Stéphane Nicoll 1762bf4a60 Fix code generation for null indexed argument value
This commit fixes code generation when an indexed constructor argument
value is null as the method is overloaded and need the value to be
cast to `Object`.

Closes gh-31508
2023-10-28 10:52:26 +02:00
Sam Brannen d3fba6d49b Support pattern matching for method names in ControlFlowPointcut
Prior to this commit, ControlFlowPointcut supported a single method
name which was matched exactly. Although it was possible to extend
ControlFlowPointcut to add support for pattern matching, it was a bit
cumbersome.

To address that, this commit introduces built-in pattern matching
support for method names in ControlFlowPointcut, analogous to the
pattern matching support in NameMatchMethodPointcut.

Specifically, a user can provide one or more method name patterns, and
the patterns will be matched against candidate method names using OR
semantics.

By default, the matching algorithm delegates to
PatternMatchUtils.simpleMatch(), but this can be overridden in
subclasses by overriding the new protected isMatch() method.

Closes gh-31435
2023-10-27 18:01:36 +02:00
Sam Brannen c5333a0a68 Polishing 2023-10-27 17:44:53 +02:00
Sam Brannen 44b98c6a8b Polish PatternMatchUtils[Tests] 2023-10-27 17:44:44 +02:00
Brian Clozel d6c9ed200a Upgrade to EclipseLink 3.0.4
See gh-31078
2023-10-26 12:00:03 +02:00
Stéphane Nicoll 4977ef9cea Import ConstructorResolver to handle null values
Previously, ConstructorResolver would reject any candidate if the
parameter is `null`. The reason for that is that null does not carry
any type and the matching algorithm would systematically fail for that
argument.

This commit adds an extra check, and several tests, to validate that
a null value is taken into account.

Closes gh-31495
2023-10-25 17:59:11 +02:00
rstoyanchev fe7b6ddf88 More polishing on forwarded header scenarios
See gh-31491
2023-10-25 16:17:37 +01:00
Sam Brannen c5def4c97a Document pattern matching support in NameMatchMethodPointcut
Closes gh-31500
2023-10-25 16:55:21 +02:00
Sam Brannen 555404e679 Polishing 2023-10-25 16:36:53 +02:00
Sam Brannen 6c4cbd2aab Support ContextLoader config in @⁠SpringJUnit[Web]Config
Prior to this commit, @⁠SpringJUnitConfig and @⁠SpringJUnitWebConfig
did not declare `loader` attributes that alias @⁠ContextConfiguration's
`loader` attribute. Consequently, it was not possible to configure a
custom ContextLoader via those annotations.

The lack of those `loader` attributes was an oversight, and this commit
introduces them to support custom ContextLoader configuration directly
via the @⁠SpringJUnitConfig and @⁠SpringJUnitWebConfig annotations.

Closes gh-31498
2023-10-25 16:12:17 +02:00
Brian Clozel c076f44144 Allow ETag generation configuration on ResourceHandlerRegistration
This commit surfaces the ETag generation feature for both
`ResourceHttpRequestHandler` and `ResourceWebHandler` on their
respective `ResourceHandlerRegistration` for easier configuration.

See gh-29031
2023-10-25 16:02:59 +02:00
Brian Clozel 9ac5eb0f55 Support ETag generation on ResourceWebHandler
This commit replicates the ETag generation option now available on
`ResourceHttpRequestHandler` but for its WebFlux counterpart.

See gh-29031
2023-10-25 16:01:15 +02:00
Brian Clozel ff14c5121d Refactor ResourceWebHandlerTests 2023-10-25 16:00:04 +02:00
Sam Brannen 5c1cdcb245 Improve ControlFlowPointcut extensibility
This commit makes ControlFlowPointcut more open to subclasses by:

1. Making the ControlFlowPointcut#clazz field protected.
2. Making the ControlFlowPointcut#methodName field protected.
3. Introducing a protected incrementEvaluationCount() method.

Closes gh-27187
2023-10-25 15:21:14 +02:00
Sam Brannen c0f79ca3bf Polish ControlFlowPointcut[Tests] 2023-10-25 15:21:14 +02:00
Arjen Poutsma 66aac7e359 Add maxParts and maxPartSize to PartEventHttpMessageReader
This commit introduces the maxParts and maxPartSize properties to
PartEventHttpMessageReader, which can be used to limit the amount of
parts, and maximum part size respectively.

Closes gh-31343
2023-10-25 15:18:35 +02:00
rstoyanchev 93528b60d7 Polishing
Closes gh-31491
2023-10-25 13:22:41 +01:00
Rob Winch 03d286c4a1 Document X-Forwarded-* Headers
Previously the documentation assumed that the readers knew how to use
the X-Forwarded-* headers. This commit documents details & examples
of how to use the X-Forwarded-* headers.

See gh-31491
2023-10-25 13:22:41 +01:00
rstoyanchev aa4f09d080 Refine decision to create object for constructor injection
Closes gh-31488
2023-10-25 13:22:25 +01:00
Sam Brannen d7e6b79336 Log and skip resource hint registration for classpath location patterns
Since we do not yet have support for registering resource hints for
classpath location patterns, we have decided to explicitly skip such
resources and log a warning to inform users that they need to manually
supply resource hints for the exact resources needed by their
application.

This commit applies this change for @⁠PropertySource and
@⁠TestPropertySource.

See gh-31162
Closes gh-31429
2023-10-25 12:42:36 +02:00
Sébastien Deleuze 9a7f141867 Upgrade to Kotlin 1.9.20-RC2
Closes gh-31494
2023-10-25 12:21:57 +02:00
Stéphane Nicoll 9f74a64c18 Do not instantiate property value while parsing MVC element
This commit harmonizes AnnotationDrivenBeanDefinitionParser so that it
does not instantiate a property value while parsing the element. Rather,
it creates an inner bean definition so that the property is created
during the refresh phase.

Closes gh-31472
2023-10-25 12:18:33 +02:00
Sébastien Deleuze 3b80f2c4cb Refine MaxUploadSizeExceededException handling
This commit refines MaxUploadSizeExceededException
handling in order to translate to a "413 Payload Too Large"
status code instead of "500 Internal Server Error", with
related ProblemDetail body.

Closes gh-27170
2023-10-25 12:11:53 +02:00
Brian Clozel 7582bd8667 Support ETag generation on ResourceHttpRequestHandler
Prior to this commit, the `ResourceHttpRequestHandler` would support
HTTP caching when serving resources, but only driving it through the
`Resource#lastModified()` information.

This commit introduces an ETag generator function that can be configured
on the `ResourceHttpRequestHandler` to dynamically generate an ETag
value for the Resource that is going to be served.

Closes gh-29031
2023-10-25 11:53:15 +02:00
Brian Clozel ebfa009f18 Refactor tests in ResourceHttpRequestHandlerTests 2023-10-25 11:53:15 +02:00
Stéphane Nicoll 6585f1a208 Merge branch '6.0.x' 2023-10-25 11:23:45 +02:00
Stéphane Nicoll 84c28995fb Improve documentation for the default profile
Closes gh-29071
2023-10-25 11:20:21 +02:00
Juergen Hoeller 83870e35d1 TypeDescriptor/ResolvableType cache in GenericTypeAwarePropertyDescriptor
Closes gh-31490
2023-10-24 23:13:19 +02:00
Juergen Hoeller 93b0b66735 Merge branch '6.0.x'
# Conflicts:
#	spring-beans/src/main/java/org/springframework/beans/BeanUtils.java
#	spring-core/src/main/java/org/springframework/core/ResolvableType.java
#	spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java
2023-10-24 22:58:31 +02:00
Juergen Hoeller 925fa0272b Polishing 2023-10-24 22:53:44 +02:00
Juergen Hoeller 09aa59f9e7 Avoid ResolvableType for simple assignability check in copyProperties
Closes gh-27246
2023-10-24 22:53:00 +02:00
Stéphane Nicoll d23263619a Improve exception message when configuration class parsing fails
This commit improves the exception that is thrown when a particular
source class cannot be parsed. Previously, the message would include
the root configuration class, which may not be the class that
actually failed as parsing can trigger component scan. There's now
a dedicated catch that generates an exception message that includes the
class that is currently parsed.

Closes gh-31146
2023-10-24 18:31:25 +02:00
Sébastien Deleuze a71eb3fb08 Merge branch '6.0.x' 2023-10-24 17:56:06 +02:00
Sébastien Deleuze 7874a59771 Remove invalid domain integration tests
Closes gh-31119
2023-10-24 17:54:39 +02:00
Stéphane Nicoll 1022e090e7 Merge pull request #31078 from bdshadow
* pr/31078:
  Polish "Fix spring-orm tests with eclipselink and Java 18+"
  Fix spring-orm tests with eclipselink and Java 18+

Closes gh-31078
2023-10-24 16:50:34 +02:00
Stéphane Nicoll a5950ca7d5 Polish "Fix spring-orm tests with eclipselink and Java 18+"
We can't upgrade to Eclipselink 4 as it would change the baseline that
this generation uses. However, there is a recent release in the current
line that adds compatibility with recent JDKs.

See gh-31078
2023-10-24 16:49:58 +02:00
Dmitrii Bocharov ce778cee27 Fix spring-orm tests with eclipselink and Java 18+
See gh-31078
2023-10-24 16:49:58 +02:00
Sam Brannen a33791e2b8 Fix typo 2023-10-24 16:44:58 +02:00
Juergen Hoeller 795ce1658c Consistent Class and array matching with Class comparison shortcut
Closes gh-31487
2023-10-24 16:42:52 +02:00
Arjen Poutsma b6e0b8c343 Use StreamingHttpOutputMessage.Body.repeatable in OkHttp3ClientHttpRequest
See gh-31449
2023-10-24 16:12:26 +02:00
Stéphane Nicoll 322013a30a Clarify the semantic of lite mode
This commit removes the "plain old class" bit of the documentation as
it may be confusing. The gist of it is that it must be a bean but not
annotated with `@Configuration` so the updated sentence states exactly
that.

Closes gh-29957
2023-10-24 16:00:48 +02:00
Sam Brannen 54839a7126 Test quoted identifiers in schema in SimpleJdbcInsert
This commit introduces additional tests for "quoted identifier" support
in SimpleJdbcInsert when the schema itself is defined using quoted
identifiers -- for example, to use keywords as column names.

See gh-31208
2023-10-24 14:36:10 +02:00
rstoyanchev 2864c12887 Merge branch '6.0.x' 2023-10-24 12:58:31 +01:00
rstoyanchev 4dab35205d Avoid super.doTrace for ERROR dispatches
Closes gh-31457
2023-10-24 12:58:11 +01:00
rstoyanchev 3f8bbdb116 Merge branch '6.0.x' 2023-10-24 12:53:55 +01:00
rstoyanchev 5c6b9be3a1 Send 400 for PathVariable that is null after conversion
This implies a value was actually sent, but is not something
that can be converted to the expected type.

Closes gh-31382
2023-10-24 12:53:25 +01:00
Stéphane Nicoll 999b5d4462 Better error reporting when instance does not match factory method
This commit improves the handling of IllegalArgumentException in
SimpleInstantiationStrategy. Previously, only arguments mismatch were
handled but the exception can also be thrown if the factory instance
does not match the target method.

Closes gh-28897
2023-10-24 13:29:12 +02:00
Stéphane Nicoll 6299a9dfc9 Add tests for SimpleInstantiationStrategy 2023-10-24 13:29:12 +02:00
rstoyanchev 796080abb8 Test for change to add conversion of defaultValue
This commit adds a test and polishing for a change in
AbstractNamedValueMethodArgumentResolver erroneously committed
with (unrelated) commit e57b942b.

If an argument becomes null after conversion and a default value is
applied, that default value should also pass through conversion.

Closes gh-31336
2023-10-24 12:24:03 +01:00
Arjen Poutsma e0ac000415 Allow repeatable writes in StreamingHttpOutputMessage
This commit adds a repeatable property to
StreamingHttpOutputMessage.Body, indicating that the body can be written
 multiple times. In HttpComponentsClientHttpRequest, this property is
 exposed via org.apache.hc.core5.http.HttpEntity.isRepeatable, to allow
 for redirects.

Closes gh-31449
2023-10-24 12:11:13 +02:00
Sam Brannen 71330ddb0f Revise support for quoted identifiers in SimpleJdbcInsert
Closes gh-31208
2023-10-24 11:52:51 +02:00
Sam Brannen a803206d5f Polishing 2023-10-24 11:52:51 +02:00
rstoyanchev e57b942b4d MockMvcBuilder supports filter name in addition to initParams
Closes gh-31474
2023-10-24 10:33:58 +01:00
Stéphane Nicoll ef47eef92a Merge branch '6.0.x' 2023-10-24 10:57:09 +02:00
Stéphane Nicoll 33fba8ea0c Merge pull request #31483 from bernie-schelberg-invicara
* pr/31483:
  Polish "Return consistent collection type for matrix variables"
  Return consistent collection type for matrix variables

Closes gh-31483
2023-10-24 10:56:36 +02:00
Stéphane Nicoll 9aa707ec4b Polish "Return consistent collection type for matrix variables"
See gh-31483
2023-10-24 10:55:42 +02:00
Bernie Schelberg ea30c8fb5b Return consistent collection type for matrix variables
See gh-31483
2023-10-24 10:27:47 +02:00
Juergen Hoeller 8712fdcd3b Polishing 2023-10-23 17:36:06 +02:00
Juergen Hoeller cf3a25bfac Merge branch '6.0.x' 2023-10-23 17:34:45 +02:00
Juergen Hoeller 6bdf7ad36a Polishing 2023-10-23 17:32:45 +02:00
Juergen Hoeller d2108d2db6 Test for @Resource @Lazy fallback type match
See gh-31447
2023-10-23 17:32:35 +02:00
Juergen Hoeller f9be717602 Avoid getObjectType exception for uninitialized ProxyFactoryBean
Closes gh-31473
2023-10-23 17:32:25 +02:00
Juergen Hoeller 8457c768e8 Polishing 2023-10-23 16:56:40 +02:00
Juergen Hoeller 6dc79b5105 Declare empty default postProcessBeanFactory method
Closes gh-31476
2023-10-23 16:56:05 +02:00
Arjen Poutsma cb4d44b83e JdkClientHttpRequest does not support Content-Length 0
This commit ensures the correct HttpRequest.BodyPublisher is used with
Content-Length 0.

Closes gh-31451
2023-10-23 12:25:10 +02:00
Stéphane Nicoll 3cb700c103 Merge branch '6.0.x' 2023-10-23 11:34:12 +02:00
Stéphane Nicoll bb446a3905 Merge pull request #31433 from martin-lukas
* pr/31433:
  Polish "Ignore @Value on record property"
  Ignore @Value on record property

Closes gh-31433
2023-10-23 11:33:57 +02:00
Stéphane Nicoll f3dce4bb9a Polish "Ignore @Value on record property"
See gh-31433
2023-10-23 11:20:49 +02:00
Martin Lukas 70cb96c1d8 Ignore @Value on record property
See gh-31433
2023-10-23 11:15:24 +02:00
Sam Brannen 2d792f000a Polish "Apply SingleSpaceSeparator Checkstyle module"
See gh-31469
2023-10-22 14:18:18 +02:00
Johnny Lim 64e9fcad53 Apply SingleSpaceSeparator Checkstyle module
This commit also fixes its violations.

Closes gh-31469
2023-10-22 14:09:57 +02:00
Sam Brannen 8a05661707 Polishing 2023-10-22 13:35:49 +02:00
Sam Brannen f72bf0c177 Revert "Skipping duplicate test classes during test AOT processing"
This reverts commit 1281f03b96.
2023-10-22 13:35:49 +02:00
Sam Brannen 563112c1b7 Ensure integration tests pass in AOT mode
See gh-29122
2023-10-22 13:35:49 +02:00
Sam Brannen 37e6fe5b64 Update copyright headers 2023-10-22 11:28:40 +02:00
Stéphane Nicoll cf10cee16a Polish 2023-10-21 17:48:27 +02:00
Brian Clozel dab7e03c93 Polish
See gh-28041
2023-10-20 18:34:52 +02:00
Chen Jianbin 4bf995fa8b Support "*" mapping in MockMvc filter registration
Prior to this commit, configuring a Servlet filter in MockMvc with a
defined mapping would only consider "/*" as a catch-all pattern.

This commit relaxes this rule by also accepting "*" mappings.

Closes gh-28041
2023-10-20 18:32:06 +02:00
Brian Clozel 31a62ff8ba Add JMH benchmarks for Protobuf message converter
This commit re-generates the protobuf Java classes with a recent version
of the protoc binary and adds JMH benchmarks that exercise the message
converter for both the reading and writing cases.

See gh-29496
2023-10-20 16:35:21 +02:00
Brian Clozel 631a5d1dc1 Remove support for Protobuf 2.x and protobuf-java-format
Closes gh-31465
2023-10-20 15:05:02 +02:00
rstoyanchev 7271dfed68 Use CopyOnWriteArrayList for beforeCommit actions
Closes gh-27587
2023-10-20 13:21:09 +01:00
rstoyanchev a2f2f7c348 Use correct RequestParam resolver
Closes gh-31329
2023-10-20 12:39:50 +01:00
Sébastien Deleuze c1437f9817 Refine CRaC restoration logs
Closes gh-31462
2023-10-20 11:40:44 +02:00
Brian Clozel daaccce918 Merge branch '6.0.x' 2023-10-19 16:07:41 +02:00
Brian Clozel 6ec264252b Ensure consistent value count in ConcurrentReferenceHashMap#Segment
Prior to this commit, the `ConcurrentReferenceHashMap#Segment` would
recalculate its element count during the restructure phase by
subtracting the number of polled elements from the queue to the current
count.
Later, the newly restructured `references` array would only contain
references that 1) are not in the set of elements to purge and
2) that hold a non-null value.

The issues with this approach are multiple. The newly calculated count
is only an estimate, as some situations can make it invalid, even
temporarily.

* since we initially collected all elements to be purged from the queue,
  the GC might have collected new values. This means that we might
  filter out more references that we initially intended to

* because the restructure operation re-creates new references for all
  elements in the original array, we might later get references from the
  queue that are not in the array anymore. This could lead to
  "duplicate" removals for the same value

Because several methods in the Segment class have special no-op behavior
when `count == 0`, an invalid count can lead to keys appearing missing
when they are actually still present. In some scenarios, this can
decrease the performance of the cache since values need to be
recalculated.

This commit fixes this inconsistency count issue by first using an
estimate in order to decide whether the array needs a resize and then by
counting the actual numbers of elements inserted in the restructured
array as the new count.

Fixes gh-31373
2023-10-19 15:54:31 +02:00
Brian Clozel c73c16f07f Configure JDK 22 compatibility build on CI
This commit does not enable this build right now as testing libraries
are not ready yet for JDK 22.

See gh-31459
2023-10-19 13:59:13 +02:00
Sébastien Deleuze c6b86af78b Fall back on UTF-8 charset in WebClientResponseException
Instead of ISO-8859-1, consistently with the change done
in RestClientResponseException.

Closes gh-31072
2023-10-19 12:59:12 +02:00
Brian Clozel 9eac9a1831 Upgrade CI to JDK 21.0.1+12 2023-10-19 11:47:25 +02:00
Brian Clozel 0a10c1ffa0 Merge branch '6.0.x' 2023-10-19 11:46:39 +02:00
Brian Clozel 187b4e5ea6 Upgrade CI image to ubuntu:jammy-20231004 2023-10-19 10:02:15 +02:00
Brian Clozel 3bc607df53 Upgrade CI to JDK 17.0.9 2023-10-19 10:01:20 +02:00
Misagh Moayyed 1e7e532ed6 Fix typos in SubstituteOnlyIfPresent Javadoc
Closes gh-31455
2023-10-18 14:11:44 +02:00
Sébastien Deleuze fa57598327 Refine BeanFactory extensions to avoid type erasure when possible
Closes gh-31439
2023-10-18 13:25:42 +02:00
Sébastien Deleuze a9d67878c5 Introduce conditional activation of Hibernate substitutions
Closes gh-31452
2023-10-18 12:16:58 +02:00
Stéphane Nicoll 9af239c8be Clean resources in case of unexpected exception
This commit updates AbstractApplicationContext#refresh to handle any
exceptions, not only BeansExceptions.

Closes gh-28878
2023-10-18 10:42:28 +02:00
Stéphane Nicoll 46cc75b3f1 Merge branch '6.0.x' 2023-10-18 10:13:49 +02:00
Stéphane Nicoll 69c92f9ac7 Document when to use multiple property placeholder configurers
This commit adds a warning in the reference guide to address the
use cases where users might be tempted to use several property
placeholder configurers.

Closes gh-14623
2023-10-18 10:12:26 +02:00
rstoyanchev a53d3f3cea Apply DisconnectedClientHelper to @ExceptionHandler methods
Use the helper to reduce logging when an @ExceptionHandler fails
to write to the response due to a network failure where the client
has gone away.

Closes gh-26181
2023-10-17 15:52:24 +01:00
rstoyanchev a8019f2d0b Create reusable DisconnectedClientHelper
See gh-26181
2023-10-17 15:52:24 +01:00
Stéphane Nicoll 49ff96dd0b Merge pull request #31368 from izeye
* pr/31368:
  Polish "Order modifiers to align with JLS"
  Order modifiers to align with JLS

Closes gh-31368
2023-10-17 16:19:04 +02:00
Stéphane Nicoll 5c6232e681 Polish "Order modifiers to align with JLS"
See gh-31368
2023-10-17 16:16:58 +02:00
Johnny Lim 919faa2ce2 Order modifiers to align with JLS
This commit also applies Checkstyle ModifierOrder to enforce it.

See gh-31368
2023-10-17 16:13:56 +02:00
Stéphane Nicoll f60791a8e2 Merge pull request #31445 from izeye
* pr/31445:
  Polish "Enable checkstyle in buildSrc"
  Enable checkstyle in buildSrc

Closes gh-31445
2023-10-17 15:55:37 +02:00
Stéphane Nicoll 27431b5138 Polish "Enable checkstyle in buildSrc"
See gh-31445
2023-10-17 15:53:37 +02:00
Johnny Lim e95ba4c205 Enable checkstyle in buildSrc
See gh-31445
2023-10-17 15:53:37 +02:00
Stéphane Nicoll 73a5229b03 Polish 2023-10-17 15:53:28 +02:00
Stéphane Nicoll 370c8e0b9e Do not enable spring javaformat plugin
We do not use the plugin, but rather apply some checkstyle rules that
should be available on the classpath.

Closes gh-31448
2023-10-17 15:46:53 +02:00
Stéphane Nicoll 4fd1431cea Restructure test to use Nested more consistently 2023-10-17 14:58:12 +02:00
Sébastien Deleuze 669c723ae0 Merge branch '6.0.x' 2023-10-17 14:25:33 +02:00
Sébastien Deleuze 875eeabb6f Add a properties setter to ProblemDetail
Mainly to allow Kotlin idiomatic properties assignment.

Closes gh-31430
2023-10-17 14:11:24 +02:00
Stéphane Nicoll 6efc99fdd8 Harmonize BeanRegistrationAotContribution class names 2023-10-17 12:37:52 +02:00
Stéphane Nicoll 9465ff0334 Add support for merging two BeanRegistrationAotContribution instances
Closes gh-31446
2023-10-17 12:31:06 +02:00
Sébastien Deleuze 22db1ac146 Add Coroutines support for @EventListener
Closes gh-28343
2023-10-17 12:11:44 +02:00
Brian Clozel 33deaff108 Move performance test to JMH benchmark
This commit removes an ignored performance test in the
`ConcurrentReferenceHashMap` test suite and converts it to a JMH
benchmark.
2023-10-17 10:42:02 +02:00
Sam Brannen 1fb2a37957 Apply @⁠DisabledInAotMode for @⁠EJB and SpEL usage
Most of the remaining failures are due to @⁠Resource usage.

Current AOT test results for the spring-test module:

Test run finished after 6140 ms
[       399 containers found      ]
[        64 containers skipped    ]
[       335 containers started    ]
[         0 containers aborted    ]
[       333 containers successful ]
[         2 containers failed     ]
[       745 tests found           ]
[       116 tests skipped         ]
[       628 tests started         ]
[         1 tests aborted         ]
[       589 tests successful      ]
[        38 tests failed          ]

Failing Test Classes:
org.springframework.test.context.groovy.AbsolutePathGroovySpringContextTests
org.springframework.test.context.groovy.GroovySpringContextTests
org.springframework.test.context.groovy.RelativePathGroovySpringContextTests
org.springframework.test.context.jdbc.BeforeTestClassSqlScriptsTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$ConfigOverriddenByDefaultTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$InheritedAndExtendedConfigTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$InheritedAndExtendedConfigTests$DoubleNestedWithOverriddenConfigTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$InheritedAndExtendedConfigTests$DoubleNestedWithOverriddenConfigTests$TripleNestedWithInheritedConfigAndTestInterfaceTests
org.springframework.test.context.junit.jupiter.orm.JpaEntityListenerTests
org.springframework.test.context.junit4.AbsolutePathSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.ConcreteTransactionalJUnit4SpringContextTests
org.springframework.test.context.junit4.InheritedConfigSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.MultipleResourcesSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.ParameterizedDependencyInjectionTests
org.springframework.test.context.junit4.RelativePathSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.SpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.annotation.AnnotationConfigSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.spr9799.Spr9799XmlConfigTests
org.springframework.test.context.testng.ConcreteTransactionalTestNGSpringContextTests

See gh-29122
2023-10-16 21:39:17 +02:00
Sam Brannen 88cd0700b2 Filter out TestNG @⁠EJB tests in AOT end-to-end tests
See gh-29122
2023-10-16 21:39:17 +02:00
Sam Brannen 9cac5eeeab Consistently use generated name in embedded databases
... to avoid database name conflicts when test classes are executed in
a different order.

See gh-29122
2023-10-16 21:38:47 +02:00
Sam Brannen 0adec6d15a Apply @⁠DisabledInAotMode to remaining @⁠ContextHierarchy integration tests
See gh-29122
2023-10-16 21:35:57 +02:00
Sam Brannen bb95f2e5ca Apply @⁠DisabledInAotMode to @⁠ContextHierarchy integration tests
This commit applies @⁠DisabledInAotMode to all integration test classes
in the spring-test module that use @⁠ContextHierarchy since that
feature is not supported for AOT optimizations.

Current AOT test results for the spring-test module:

Test run finished after 6888 ms
[       403 containers found      ]
[        57 containers skipped    ]
[       346 containers started    ]
[         0 containers aborted    ]
[       338 containers successful ]
[         8 containers failed     ]
[       757 tests found           ]
[        98 tests skipped         ]
[       654 tests started         ]
[         9 tests aborted         ]
[       576 tests successful      ]
[        69 tests failed          ]

Failing Test Classes:
org.springframework.test.context.configuration.interfaces.SqlConfigInterfaceTests
org.springframework.test.context.expression.ExpressionUsageTests
org.springframework.test.context.groovy.AbsolutePathGroovySpringContextTests
org.springframework.test.context.groovy.GroovySpringContextTests
org.springframework.test.context.groovy.RelativePathGroovySpringContextTests
org.springframework.test.context.hierarchies.meta.MetaHierarchyLevelTwoTests
org.springframework.test.context.hierarchies.standard.TestHierarchyLevelTwoWithBareContextConfigurationInSubclassTests
org.springframework.test.context.jdbc.CustomScriptSyntaxSqlScriptsTests
org.springframework.test.context.jdbc.GlobalCustomScriptSyntaxSqlScriptsTests
org.springframework.test.context.jdbc.InferredDataSourceTransactionalSqlScriptsTests
org.springframework.test.context.jdbc.InfrastructureProxyTransactionalSqlScriptsTests
org.springframework.test.context.jdbc.MultipleDataSourcesAndTransactionManagersSqlScriptsTests
org.springframework.test.context.jdbc.MultipleDataSourcesAndTransactionManagersTransactionalSqlScriptsTests
org.springframework.test.context.jdbc.NonTransactionalSqlScriptsTests
org.springframework.test.context.jdbc.RepeatableSqlAnnotationSqlScriptsChildTests
org.springframework.test.context.jdbc.RepeatableSqlAnnotationSqlScriptsParentTests
org.springframework.test.context.jdbc.TransactionalAfterTestMethodSqlScriptsTests
org.springframework.test.context.jdbc.TransactionalInlinedStatementsSqlScriptsTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$ConfigOverriddenByDefaultTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$InheritedAndExtendedConfigTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$InheritedAndExtendedConfigTests$DoubleNestedWithOverriddenConfigTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$InheritedAndExtendedConfigTests$DoubleNestedWithOverriddenConfigTests$TripleNestedWithInheritedConfigAndTestInterfaceTests
org.springframework.test.context.junit.jupiter.orm.JpaEntityListenerTests
org.springframework.test.context.junit4.AbsolutePathSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.ConcreteTransactionalJUnit4SpringContextTests
org.springframework.test.context.junit4.InheritedConfigSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.MultipleResourcesSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.ParameterizedDependencyInjectionTests
org.springframework.test.context.junit4.RelativePathSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.SpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.annotation.AnnotationConfigSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.rules.TransactionalSqlScriptsSpringRuleTests
org.springframework.test.context.junit4.spr9799.Spr9799XmlConfigTests
org.springframework.test.context.testng.ConcreteTransactionalTestNGSpringContextTests
org.springframework.test.context.testng.transaction.ejb.CommitForRequiredEjbTxDaoTestNGTests
org.springframework.test.context.testng.transaction.ejb.CommitForRequiresNewEjbTxDaoTestNGTests
org.springframework.test.context.testng.transaction.ejb.RollbackForRequiredEjbTxDaoTestNGTests
org.springframework.test.context.testng.transaction.ejb.RollbackForRequiresNewEjbTxDaoTestNGTests
org.springframework.test.context.transaction.ejb.CommitForRequiredEjbTxDaoTests
org.springframework.test.context.transaction.ejb.CommitForRequiresNewEjbTxDaoTests
org.springframework.test.context.transaction.ejb.RollbackForRequiredEjbTxDaoTests
org.springframework.test.context.transaction.ejb.RollbackForRequiresNewEjbTxDaoTests

See gh-29122
2023-10-16 17:11:00 +02:00
Sam Brannen 44931dca44 Include all failing test classes in AOT end-to-end test report
Prior to this commit, AotIntegrationTests only printed "failing test
classes" for tests that failed at the class level.

This commit updates the reporting logic to report test classes for
failing test methods as well.

Current results for the spring-test module:

Test run finished after 6531 ms
[       403 containers found      ]
[        27 containers skipped    ]
[       376 containers started    ]
[         0 containers aborted    ]
[       366 containers successful ]
[        10 containers failed     ]
[       757 tests found           ]
[        61 tests skipped         ]
[       689 tests started         ]
[         9 tests aborted         ]
[       585 tests successful      ]
[        95 tests failed          ]

Failing Test Classes:
org.springframework.test.context.configuration.interfaces.ContextHierarchyInterfaceTests
org.springframework.test.context.configuration.interfaces.SqlConfigInterfaceTests
org.springframework.test.context.expression.ExpressionUsageTests
org.springframework.test.context.groovy.AbsolutePathGroovySpringContextTests
org.springframework.test.context.groovy.GroovySpringContextTests
org.springframework.test.context.groovy.RelativePathGroovySpringContextTests
org.springframework.test.context.hierarchies.meta.MetaHierarchyLevelTwoTests
org.springframework.test.context.hierarchies.standard.ClassHierarchyWithMergedConfigLevelOneTests
org.springframework.test.context.hierarchies.standard.ClassHierarchyWithMergedConfigLevelTwoTests
org.springframework.test.context.hierarchies.standard.ClassHierarchyWithOverriddenConfigLevelTwoTests
org.springframework.test.context.hierarchies.standard.DirtiesContextWithContextHierarchyTests
org.springframework.test.context.hierarchies.standard.SingleTestClassWithTwoLevelContextHierarchyAndMixedConfigTypesTests
org.springframework.test.context.hierarchies.standard.SingleTestClassWithTwoLevelContextHierarchyTests
org.springframework.test.context.hierarchies.standard.TestHierarchyLevelTwoWithBareContextConfigurationInSubclassTests
org.springframework.test.context.hierarchies.standard.TestHierarchyLevelTwoWithBareContextConfigurationInSuperclassTests
org.springframework.test.context.hierarchies.standard.TestHierarchyLevelTwoWithSingleLevelContextHierarchyAndMixedConfigTypesTests
org.springframework.test.context.hierarchies.standard.TestHierarchyLevelTwoWithSingleLevelContextHierarchyTests
org.springframework.test.context.hierarchies.web.ControllerIntegrationTests
org.springframework.test.context.hierarchies.web.DispatcherWacRootWacEarTests
org.springframework.test.context.hierarchies.web.RootWacEarTests
org.springframework.test.context.jdbc.CustomScriptSyntaxSqlScriptsTests
org.springframework.test.context.jdbc.GlobalCustomScriptSyntaxSqlScriptsTests
org.springframework.test.context.jdbc.InferredDataSourceTransactionalSqlScriptsTests
org.springframework.test.context.jdbc.InfrastructureProxyTransactionalSqlScriptsTests
org.springframework.test.context.jdbc.MultipleDataSourcesAndTransactionManagersSqlScriptsTests
org.springframework.test.context.jdbc.MultipleDataSourcesAndTransactionManagersTransactionalSqlScriptsTests
org.springframework.test.context.jdbc.NonTransactionalSqlScriptsTests
org.springframework.test.context.jdbc.RepeatableSqlAnnotationSqlScriptsChildTests
org.springframework.test.context.jdbc.RepeatableSqlAnnotationSqlScriptsParentTests
org.springframework.test.context.jdbc.TransactionalAfterTestMethodSqlScriptsTests
org.springframework.test.context.jdbc.TransactionalInlinedStatementsSqlScriptsTests
org.springframework.test.context.junit.jupiter.nested.ContextHierarchyNestedTests$NestedTestCaseWithInheritedConfigTests
org.springframework.test.context.junit.jupiter.nested.ContextHierarchyNestedTests$NestedTestCaseWithInheritedConfigTests$DoubleNestedTestCaseWithOverriddenConfigTests
org.springframework.test.context.junit.jupiter.nested.ContextHierarchyNestedTests$NestedTestCaseWithInheritedConfigTests$DoubleNestedTestCaseWithOverriddenConfigTests$TripleNestedWithInheritedConfigAndTestInterfaceTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$ConfigOverriddenByDefaultTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$InheritedAndExtendedConfigTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$InheritedAndExtendedConfigTests$DoubleNestedWithOverriddenConfigTests
org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests$InheritedAndExtendedConfigTests$DoubleNestedWithOverriddenConfigTests$TripleNestedWithInheritedConfigAndTestInterfaceTests
org.springframework.test.context.junit.jupiter.orm.JpaEntityListenerTests
org.springframework.test.context.junit4.AbsolutePathSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.ConcreteTransactionalJUnit4SpringContextTests
org.springframework.test.context.junit4.InheritedConfigSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.MultipleResourcesSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.ParameterizedDependencyInjectionTests
org.springframework.test.context.junit4.RelativePathSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.SpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.annotation.AnnotationConfigSpringJUnit4ClassRunnerAppCtxTests
org.springframework.test.context.junit4.rules.TransactionalSqlScriptsSpringRuleTests
org.springframework.test.context.junit4.spr9799.Spr9799XmlConfigTests
org.springframework.test.context.testng.ConcreteTransactionalTestNGSpringContextTests
org.springframework.test.context.testng.transaction.ejb.CommitForRequiredEjbTxDaoTestNGTests
org.springframework.test.context.testng.transaction.ejb.CommitForRequiresNewEjbTxDaoTestNGTests
org.springframework.test.context.testng.transaction.ejb.RollbackForRequiredEjbTxDaoTestNGTests
org.springframework.test.context.testng.transaction.ejb.RollbackForRequiresNewEjbTxDaoTestNGTests
org.springframework.test.context.transaction.ejb.CommitForRequiredEjbTxDaoTests
org.springframework.test.context.transaction.ejb.CommitForRequiresNewEjbTxDaoTests
org.springframework.test.context.transaction.ejb.RollbackForRequiredEjbTxDaoTests
org.springframework.test.context.transaction.ejb.RollbackForRequiresNewEjbTxDaoTests
org.springframework.test.web.servlet.samples.client.context.JavaConfigTests
org.springframework.test.web.servlet.samples.client.context.WebAppResourceTests
org.springframework.test.web.servlet.samples.client.context.XmlConfigTests
org.springframework.test.web.servlet.samples.context.JavaConfigTests
org.springframework.test.web.servlet.samples.context.WebAppResourceTests
org.springframework.test.web.servlet.samples.context.XmlConfigTests

See gh-29122
2023-10-16 16:56:20 +02:00
Sam Brannen 32b4f55d92 Update copyright headers 2023-10-16 16:19:55 +02:00
Sam Brannen 119a9ffc3e Rename test class to NestedTests for AOT integration testing
Prior to this commit, the NestedTestCase resulted in errors during our
AOT end-to-end integration tests since it did not comply to our "*Tests"
naming convention.

See gh-29122
2023-10-16 16:19:55 +02:00
Sam Brannen 66e3a7a25c Apply @⁠DisabledInAotMode to appropriate test classes
This commit applies @⁠DisabledInAotMode to test classes in the
spring-test module that will never be able to be processed for AOT
optimizations.

Test classes that fail for reasons that can potentially be addressed in
a future version of the framework have not been annotated with
@⁠DisabledInAotMode.

See gh-29122
2023-10-16 16:19:55 +02:00
Sam Brannen 991afe0939 Fix formatting for @⁠DisabledInAotMode error messages
See gh-30834
2023-10-16 16:19:55 +02:00
Sam Brannen 1281f03b96 Skipping duplicate test classes during test AOT processing
Although it should not happen in theory, sometimes a test class is
discovered more than once via the TestClassScanner in our integration
tests. When it does happen in our tests, the two Class objects have the
same fully-qualified class name but represent different classes which
leads to failures due to incorrect associations between test class
names and their MergedContextConfiguration.

To address this, this commit modifies TestContextAotGenerator so that
it skips duplicate test class names.
2023-10-16 16:19:55 +02:00
Sam Brannen 28939e4754 Find @⁠DisabledInAotMode on enclosing classes for @⁠Nested tests
See gh-30834
2023-10-16 16:19:55 +02:00
Sam Brannen fc81cc5cda Polishing 2023-10-16 15:56:12 +02:00
Sam Brannen 41098d52d6 Print test summary for AotIntegrationTests.endToEndTestsForEntireSpringTestModule()
Current results for the spring-test module:

Test run finished after 6785 ms
[       403 containers found      ]
[         6 containers skipped    ]
[       397 containers started    ]
[         0 containers aborted    ]
[       381 containers successful ]
[        16 containers failed     ]
[       757 tests found           ]
[        41 tests skipped         ]
[       703 tests started         ]
[         9 tests aborted         ]
[       599 tests successful      ]
[        95 tests failed          ]

Failing Test Classes:
org.springframework.test.context.testng.transaction.ejb.RollbackForRequiresNewEjbTxDaoTestNGTests
org.springframework.test.context.testng.transaction.ejb.CommitForRequiredEjbTxDaoTestNGTests
org.springframework.test.context.testng.transaction.ejb.RollbackForRequiredEjbTxDaoTestNGTests
org.springframework.test.context.testng.transaction.ejb.CommitForRequiresNewEjbTxDaoTestNGTests
org.springframework.test.context.env.ExplicitPropertiesFileTestPropertySourceTests$ClasspathTests$PlaceholderAndClasspathPrefixTests
org.springframework.test.context.env.ExplicitPropertiesFileTestPropertySourceTests$ClasspathTests$PlaceholderTests
org.springframework.test.context.env.ExplicitPropertiesFileTestPropertySourceTests$FileSystemTests$CustomPlaceholderTests
org.springframework.test.context.env.ExplicitPropertiesFileTestPropertySourceTests$FileSystemTests$PlaceholdersFollowedByRelativePathsTests
org.springframework.test.context.env.ExplicitPropertiesFileTestPropertySourceTests$FileSystemTests$UserDirAndCustomPlaceholdersTests
org.springframework.test.web.servlet.samples.client.context.WebAppResourceTests
org.springframework.test.web.servlet.samples.client.context.XmlConfigTests
org.springframework.test.web.servlet.samples.context.WebAppResourceTests
org.springframework.test.web.servlet.samples.context.XmlConfigTests
org.springframework.test.context.junit4.ParameterizedDependencyInjectionTests
org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests$NestedTestCase
org.springframework.test.context.junit4.spr9799.Spr9799XmlConfigTests

See gh-29122
2023-10-16 13:13:36 +02:00
Sam Brannen 3ad79e919b Modify tests so they pass in AOT mode
... when run via AotIntegrationTests.endToEndTestsForEntireSpringTestModule().
2023-10-16 13:00:07 +02:00
Sam Brannen 87127ab684 Polishing 2023-10-16 13:00:07 +02:00
Sébastien Deleuze 466c8d8f23 Add Coroutines support for @Cacheable
This commit adds Coroutines support for `@Cacheable`.

It also refines SimpleKeyGenerator to ignore Continuation
parameters (Kotlin does not allow to have the same method
signature with both suspending and non-suspending variants)
and refines
org.springframework.aop.framework.CoroutinesUtils.awaitSingleOrNull
in order to wrap plain value to Mono.

Closes gh-31412
2023-10-15 19:25:59 +02:00
Sam Brannen 39a282e463 Introduce @⁠DisabledInAotMode in the TestContext framework
This commit introduces @⁠DisabledInAotMode in the TestContext
framework to support the following use cases.

- Disabling AOT build-time processing of a test ApplicationContext --
  applicable to any testing framework (JUnit 4, JUnit Jupiter, etc.).

- Disabling an entire test class or a single test method at run time
  when the test suite is run with AOT optimizations enabled -- only
  applicable to JUnit Jupiter based tests.

Closes gh-30834
2023-10-15 19:22:26 +02:00
Sam Brannen 8e5f39b439 Align with StackWalker use in MergedAnnotationsTests.getFromMethodWithBridgeMethod() 2023-10-15 17:53:19 +02:00
Juergen Hoeller 0eb92c1267 Merge branch '6.0.x' 2023-10-15 16:10:12 +02:00
Juergen Hoeller 7a60e2024b BeanCopier sets name prefix for public classes as well
Includes consistent formatting of Spring-patched files.

Closes gh-28699
2023-10-15 16:09:17 +02:00
Juergen Hoeller 4458799e06 Upgrade to ASM 9.6
Closes gh-31431
2023-10-15 16:04:44 +02:00
Juergen Hoeller 7bee1fdb71 Polishing 2023-10-15 16:04:30 +02:00
Lars Grefer b124522a11 Update to io.freefair.aspectj 8.4 2023-10-15 01:09:29 +02:00
Johnny Lim 15f7e8ef2f Fix typo in ClassUtils.forName()
See gh-31258
Closes gh-31428
2023-10-14 17:43:06 +02:00
Sam Brannen 39400901cd Set failOnError flag to false endToEndTestsForEntireSpringTestModule() 2023-10-14 13:09:11 +02:00
Sam Brannen 8b335e793c Revise endToEndTestsForEntireSpringTestModule() 2023-10-14 12:41:01 +02:00
Sam Brannen d43cf2c5cd Polishing 2023-10-13 18:12:49 +02:00
Stéphane Nicoll 607c84f960 Fix support for target arrays
This commits makes sure that a bean that produces an array can be
processed ahead of time. If the request target type is an array, its
component type is used.

Closes gh-31426
2023-10-13 15:33:32 +02:00
Stéphane Nicoll 85388aa642 Add AOT support for generic constructor argument values
This commit improves compatibility with the core container when running
in AOT mode by adding support for generic constructor argument values.

Previously, these were ignored altogether. We now have code generation
support for them as well as resolution that is similar to what
AbstractAutowiredCapableBeanFactory does in a regular runtime.

This commit also improves AOT support for XML bean configurations by
adding more support for TypedStringValue and inner bean definitions.

Closes gh-31420
2023-10-13 15:33:32 +02:00
Brian Clozel ca4d0d784b Apply instrumentation fixes to HttpWebHandlerAdapter
Since the Spring WebFlux HTTP server instrumentation has been moved from
the `WebFilter` to the `HttpWebHandlerAdapter`, we need to apply similar
changes there.

See gh-31417
2023-10-13 15:04:03 +02:00
Brian Clozel 579f29857f Merge branch '6.0.x' 2023-10-13 15:03:56 +02:00
Brian Clozel da95542d8f Prevent duplicate HTTP server observations
Prior to this commit, HTTP server observations for Spring WebFlux could
be recorded twice for a single request in some cases. The "COMPLETE" and
"CANCEL" signals would race in the reactive pipeline and would trigger
both the `doOnComplete()` and ` `doOnCancel()` operators, each calling
`observation.stop()` on the current observation.
This would in fact publish two different observations for the same
request.

This commit ensures that the instrumentation uses the `Mono#tap`
operator to guard against this case and only call `Observation#stop`
once for each request.

Fixes gh-31417
2023-10-13 14:56:40 +02:00
rstoyanchev b5b9386be6 Polishing
Closes gh-31413
2023-10-13 11:47:47 +01:00
Olga MaciaszekSharma 0cd196e3dd Add UriBuilderFactoryArgumentResolver
See gh-31413
2023-10-13 11:47:47 +01:00
Sam Brannen 364186e699 Polishing 2023-10-12 17:52:55 +02:00
Sam Brannen 047c2c1c20 Do not swallow failures in tests 2023-10-12 17:51:26 +02:00
Sam Brannen a4fe57a9e2 Restore imports for deprecated types in tests 2023-10-12 17:35:01 +02:00
Stéphane Nicoll 1e7fc6035d Merge branch '6.0.x' 2023-10-12 16:19:49 +02:00
Stéphane Nicoll 6669ab1ae7 Merge pull request #31416 from GVictorG7
* pr/31416:
  Polish "Replace deprecated method getBuildDir()"
  Replace deprecated method getBuildDir()

Closes gh-31416
2023-10-12 16:19:41 +02:00
Stéphane Nicoll d05ac097dd Polish "Replace deprecated method getBuildDir()"
See gh-31416
2023-10-12 16:14:23 +02:00
Victor Georgescu 35103b0cd1 Replace deprecated method getBuildDir()
See gh-31416
2023-10-12 16:10:40 +02:00
Stephane Nicoll 37c2619fc4 Add AOT support for TypedStringValue
This commit adds support for TypeStringValue when generating AOT code.
If the value does not specify an explicit type, it's specified as is.
Otherwise, the TypeStringValue instance is restored via the appropriate
code generation.

Closes gh-29074
2023-10-12 14:11:53 +02:00
Stéphane Nicoll 15c19411f6 Harmonize exception handling
This commit applies the same catch block to orderForConsistence(Map)
than the one that's used for sets.

Closes gh-31419
2023-10-12 13:55:33 +02:00
Brian Clozel aab538d1f0 Merge branch '6.0.x' 2023-10-12 11:58:10 +02:00
Spring Builds 3b50f992fe Next development version (v6.0.14-SNAPSHOT) 2023-10-12 09:28:10 +00:00
Brian Clozel bb23032a78 Merge branch '6.0.x' 2023-10-11 19:16:41 +02:00
Brian Clozel 4bd54dffbc Upgrade to concourse-release-scripts 0.4.0-SNAPSHOT 2023-10-11 19:16:06 +02:00
rstoyanchev 776e28a6c4 MockMvc supports filter initParams and DispatcherType's
Closes gh-27717, gh-31362
2023-10-11 17:09:18 +01:00
rstoyanchev 0542fe5232 Update ClientHttpRequestInterceptor javadoc
Clarify the interceptor is responsible for closing the response
if it throws an exception after receiving it.

Closes gh-29751
2023-10-11 17:09:18 +01:00
Juergen Hoeller c7b832cfc8 Enforce REQUIRES_NEW for correct transaction configuration
Closes gh-31414
2023-10-11 17:14:32 +02:00
Juergen Hoeller 2cdc114273 Merge branch '6.0.x' 2023-10-11 16:11:34 +02:00
Juergen Hoeller 86650d1a39 Polishing 2023-10-11 16:10:53 +02:00
Juergen Hoeller 87424cd605 Upgrade to SLF4J 2.0.9 and AspectJ 1.9.20.1 2023-10-11 15:44:07 +02:00
Juergen Hoeller 80e82cd43f Do not close transactional Connection in doReleaseConnection
Closes gh-28133
2023-10-11 15:43:02 +02:00
Sam Brannen 25778e2f0e Clean up warnings in tests 2023-10-11 13:32:48 +02:00
Sam Brannen 00dde8bd88 Polishing 2023-10-11 13:32:47 +02:00
Juergen Hoeller 653a631df5 Merge branch '6.0.x'
# Conflicts:
#	spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java
2023-10-11 13:28:11 +02:00
rstoyanchev 3277b0d6ac Handle STOMP messages to user destination in order
Closes gh-31395
2023-10-11 12:16:04 +01:00
Rossen Stoyanchev 9eb39e182e Polishing
See gh-21798
2023-10-11 12:16:04 +01:00
rstoyanchev a205eab618 Handle STOMP messages from client in order
See gh-21798
2023-10-11 12:16:04 +01:00
rstoyanchev 4195e6906c OrderedMessageChannelDecorator supports multiple subscribers
See gh-21798
2023-10-11 12:16:04 +01:00
rstoyanchev d62d7f5ff1 Polishing
See gh-21798
2023-10-11 12:16:04 +01:00
Juergen Hoeller 66ce8c9a25 Properly return SQLExceptionTranslator-provided exception
Closes gh-31409
2023-10-11 13:13:22 +02:00
Juergen Hoeller e76b453685 Translate Hibernate TransactionException through SQLException cause
Closes gh-31274
2023-10-11 13:09:19 +02:00
OnlyWick eafbcfd385 Remove redundant static declaration on Search class
Closes gh-31381
2023-10-11 13:01:21 +02:00
Brian Clozel d1cf71cc70 Merge branch '6.0.x' 2023-10-11 11:24:00 +02:00
Brian Clozel e9fcb21d55 Refine status KeyValue for HTTP server observations
Prior to this commit, a cancelled exchange would always result in an
`"status":"UNKNOWN"` KeyValue. This only applied to reactive variants,
as cancelled exchanges are not currently detected for Servlet
implementations.

In some cases, exchanges can be cancelled by clients before they are
completed, but the response was actually received by the client. The
response status information has been set by the application and the
response has been committed. For those cases, we shouldn't assume an
"UNKNOWN" value.

This commit assumes that committed responses have a response status set
by the application and that the observations should reflect that. From
now on, we only assume an "UNKNOWN" status if the response has not been
commited.

Fixes gh-31388
2023-10-11 11:17:38 +02:00
Arjen Poutsma c692d7e020 Merge branch '6.0.x' 2023-10-11 10:37:26 +02:00
Arjen Poutsma ee9dff30c5 Updated Java 17 version in sdkmanrc 2023-10-11 10:36:29 +02:00
Sébastien Deleuze bbaa35e69e Merge branch '6.0.x' 2023-10-11 10:13:12 +02:00
Sébastien Deleuze 2158410853 Revert "Support Jackson's DatatypeFeature in Jackson2ObjectMapperBuilder"
This reverts commit 5f053401e2.
2023-10-11 10:10:36 +02:00
Stéphane Nicoll dc0d6a41d6 Polish 2023-10-11 09:00:40 +02:00
Stéphane Nicoll 93206c3f6e Add support for custom locale to render compiler messages
Closes gh-31408
2023-10-11 09:00:40 +02:00
Sébastien Deleuze ae88bbaac3 Reintroduce org.springframework.http.client.reactive.ReactorResourceFactory
This commit reintroduces a deprecated ReactorResourceFactory in
org.springframework.http.client.reactive package that extends
the one in org.springframework.http.client package to avoid an
API breaking change and to provide a smoother upgrade experience.

Closes gh-31399
2023-10-11 08:38:17 +02:00
Juergen Hoeller 841448877a Upgrade to Reactor 2023.0.0-RC1
Includes Jetty 12.0.2 and Checkstyle 10.12.4

Closes gh-31406
2023-10-11 00:46:24 +02:00
Juergen Hoeller 38de3d5b57 Merge branch '6.0.x'
# Conflicts:
#	build.gradle
#	framework-platform/framework-platform.gradle
#	spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
2023-10-11 00:19:54 +02:00
Juergen Hoeller e0a55c2caa Upgrade to Micrometer 1.10.12 and Reactor 2022.0.12
Includes Context Propagation 1.0.6, Netty 4.1.100, Jetty 11.0.17, Tomcat 10.1.14, Groovy 4.0.15, Mockito 5.6, Checkstyle 10.12.4

Closes gh-31404
Closes gh-31405
2023-10-11 00:13:51 +02:00
Juergen Hoeller 0b96da4b6d Revise javadoc for LifecycleProcessor bean etc 2023-10-10 23:36:08 +02:00
Juergen Hoeller c0d98fcc7a Consistent Object result declarations for ResultQuerySpec
Closes gh-31403
2023-10-10 22:58:13 +02:00
Juergen Hoeller de6692e7d8 Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMapping.java
2023-10-10 21:58:31 +02:00
Juergen Hoeller 387a16bd4e Revise transaction annotation recommendations
Closes gh-23538
2023-10-10 21:56:14 +02:00
Juergen Hoeller 8b5d993e61 Throw IllegalArgumentException for null SQL String
Closes gh-31391
2023-10-10 21:55:12 +02:00
Juergen Hoeller 5459304a4b Re-introduce support for annotation declarations with self references
Closes gh-31400
2023-10-10 21:54:58 +02:00
Juergen Hoeller d339bbbf91 Remove test for MessageSource access after context close
See gh-31397
2023-10-10 20:46:58 +02:00
Brian Clozel 8d6b499cf1 Polish
See gh-31398
2023-10-10 20:42:45 +02:00
Stéphane Nicoll da24c6b346 Merge branch '6.0.x' 2023-10-10 20:34:11 +02:00
Stéphane Nicoll 00d4830e5c Merge pull request #31396 from wfouche
* pr/31396:
  Upgrade to gradle-versions-plugin 0.49.0

Closes gh-31396
2023-10-10 20:33:53 +02:00
Werner Fouché 3c2e21a578 Upgrade to gradle-versions-plugin 0.49.0
See gh-31396
2023-10-10 20:33:14 +02:00
Stéphane Nicoll 96b32580ec Handle deprecation warning in AOT-generated code
Closes gh-29597
2023-10-10 20:16:32 +02:00
Stéphane Nicoll ea66883d79 Detect use of deprecated API
This commit is a best effort attempt at identifying the members that
code generation invokes and might be deprecated. It introduces
a CodeWarnings helper class that records warnings, with special
handling for `@Deprecated`.

See gh-29597
2023-10-10 20:08:04 +02:00
Stéphane Nicoll 35372e5e72 Simplify InstanceSupplierCodeGeneratorTests 2023-10-10 20:08:04 +02:00
Stéphane Nicoll 4b14a0b42c Add support for specifying compiler options
This commit is a prerequisite to help suppressing deprecating warnings
by allowing tests to validate that the compiler does not encounter them.

See gh-29597
2023-10-10 20:08:04 +02:00
Juergen Hoeller 2754da1742 Reset ApplicationEventMulticaster/MessageSource/LifecycleProcessor on close
Closes gh-21988
Closes gh-31397
2023-10-10 18:10:52 +02:00
Juergen Hoeller a6c27652b8 Revise test for ApplicationListener self injection
See gh-28322
2023-10-10 18:09:52 +02:00
Alexander Kriegisch 20c688e68d Avoid duplicate application listeners (proxy vs. proxy target)
In AbstractApplicationEventMulticaster.retrieveApplicationListeners,
despite best efforts to avoid it, unwrapped proxies (singleton targets)
can end up in the list of programmatically registered listeners. In
order to avoid duplicates, we need to find and replace them by their
proxy counterparts, because if both a proxy and its target end up in
'allListeners', listeners will fire twice.

Fixes #28283.
2023-10-10 17:01:00 +02:00
Alexander Kriegisch 86d52a677a Regression test for duplicate firing of proxied application listeners
ApplicationContextEventTests.eventForSelfInjectedProxiedListenerFiredOnlyOnce
relates to and reproduces #28283.
2023-10-10 17:01:00 +02:00
Sébastien Deleuze 299a10ce2a Update @Since Java doc tags in ReactorResourceFactory
See gh-31399
2023-10-10 16:51:21 +02:00
Sébastien Deleuze e0ba42a80c Move ReactorResourceFactory to org.springframework.http.client package
Closes gh-31399
2023-10-10 15:58:20 +02:00
Brian Clozel 99c673f3ea Upgrade to Micrometer 1.12.0-RC1
Closes gh-31398
2023-10-10 15:40:32 +02:00
Arjen Poutsma 307a2c7d7b Polishing external contribution
See gh-29985
2023-10-10 14:16:00 +02:00
Jakob Fels ad50de169c Provide access to HTTP headers in resource routing
This commit adds additional overloaded methods that allow for HTTP
header manipulation of served resources.

Closes gh-29985
2023-10-10 14:16:00 +02:00
Arjen Poutsma faaf3a61f2 Add FormEvent stream event test
Add sample that shows how FormEvents can be used to create a form
submit from a stream of key/value pairs.

See gh-30131
2023-10-10 14:08:06 +02:00
Sébastien Deleuze 298d6e4db0 Fix unused import error in ReactorClientHttpConnector 2023-10-10 13:04:32 +02:00
Sébastien Deleuze 955112be0e Polish ReactorClientHttpConnector Javadoc 2023-10-10 12:50:26 +02:00
Sébastien Deleuze 363d5a6413 Add CRaC support to ReactorNettyClientRequestFactory
This commit adds a constructor with externally managed
Reactor Netty resources to ReactorNettyClientRequestFactory
and makes it lifecycle-aware in order to support Project CRaC.

Closes gh-31280
Closes gh-31281
2023-10-10 12:42:56 +02:00
Sébastien Deleuze cd3daa873f Merge branch '6.0.x' 2023-10-10 10:17:02 +02:00
Bram Hagens 5f053401e2 Support Jackson's DatatypeFeature in Jackson2ObjectMapperBuilder
Closes gh-31380
2023-10-10 10:13:52 +02:00
Brian Clozel 8064659136 Register bean reflection hint for property fields
Prior to this commit, the bean definition properties code generator
would register hints for invoking the setter methods of registered
property values defined for the bean definition.
The internal algorithm is also reflecting on the Field to discover
annotations. Doing so actually calls `getDeclaredFields` to iterate on
the available fields. This is done recursively up the type hierarchy
until the field is found.

This commit registers the required reflection metadata.

Closes gh-31390
2023-10-09 20:03:06 +02:00
Brian Clozel 30a94b041f Upgrade CI image to Ubuntu jammy-20230916 2023-10-09 20:02:43 +02:00
Sébastien Deleuze 22a2847809 Merge branch '6.0.x' 2023-10-09 12:42:44 +02:00
Sébastien Deleuze 63770fb074 Document Kotlin declaration-site variance subtleties
Closes gh-31370
2023-10-09 12:42:36 +02:00
Sam Brannen d1b43386b1 Test status quo for @⁠Sql in @⁠Nested test class w/ class-level execution phases 2023-10-08 18:16:31 +02:00
Johnny Lim 8ed302bfa4 Add @⁠since tags for DataBufferUtils.outputStreamPublisher() methods
See gh-31184
Closes gh-31376
2023-10-08 18:09:21 +02:00
Sam Brannen b98b999997 Test status quo for inherited @⁠Sql in @⁠Nested test class 2023-10-08 18:09:13 +02:00
Sam Brannen af4652db36 Merge branch '6.0.x' 2023-10-08 16:24:53 +02:00
Sam Brannen 9df4bce043 Upgrade to Gradle 8.4
Closes gh-31375
2023-10-08 16:08:29 +02:00
Stéphane Nicoll ae731fbb78 Merge branch '6.0.x' 2023-10-05 16:57:04 +02:00
Stéphane Nicoll 19fd8159b2 Improve Javadoc of MethodParameter#getAnnotatedElement
This commit adds a reference to the method that can be used to get
the AnnotatedElement at the parameter level.

Closes gh-30397
2023-10-05 16:56:37 +02:00
Arjen Poutsma 59d123a18e Introduce OutputStream BodyInserter
This commit introduces a BodyInserter that inssert any bytes written to
an output stream to the body of an output message.

Closes gh-31184
2023-10-05 15:31:08 +02:00
Sam Brannen 913dc86e18 Polishing 2023-10-05 14:13:01 +02:00
Brian Clozel 130b1f44f7 Do not use javadoc.io for javadoc generation
The website has been unresponsive for quite some time, our build cannot
rely on this service right now.
2023-10-05 11:47:41 +02:00
Arjen Poutsma 1766d7598c Minor fixes in RestTemplate to RestClient migration guide
See gh-23269
2023-10-05 10:53:31 +02:00
Sam Brannen 95139fca76 Polishing 2023-10-04 17:39:14 +02:00
Sam Brannen 0afcb4dfed Revise "Introduce class-level execution phases for @⁠Sql"
This commit revises the previous commit as follows.

- Remove hasTestMethod() from TestContext and instead introduce a new
  variant of createDelegatingTransactionAttribute() in
  TestContextTransactionUtils which accepts a boolean
  `includeMethodName` flag.

- Add missing @⁠TestMethodOrder declaration to
  AfterTestClassSqlScriptsTests to ensure that the test methods are
  always executed in the required order.

- Polish Javadoc and add missing @⁠since tags.

Closes gh-27285
2023-10-04 17:39:14 +02:00
Andreas Ahlenstorf 5aa2d0515e Introduce class-level execution phases for @⁠Sql
This commit introduces BEFORE_TEST_CLASS and AFTER_TEST_CLASS execution
phases for @⁠Sql.

See gh-27285
2023-10-04 16:39:21 +02:00
Arjen Poutsma 2b47b8942d Added RestTemplate to RestClient migration guide
Closes gh-23269
2023-10-04 14:22:23 +02:00
rstoyanchev 4a10fa67a5 Expose HttpRequest from ClientResponse
Closes gh-28397
2023-10-04 13:05:09 +01:00
rstoyanchev ef8d1db403 Improve exception handling in startCallableProcessing
Absorb any exception from the submission to the executor. It will be
handled in the resulting ASYNC dispatch.

Closes gh-30232
2023-10-04 13:05:09 +01:00
rstoyanchev a3636affa2 ResponseBodyEmitter allows complete after non-IOException
Closes gh-30687
2023-10-04 13:05:09 +01:00
Stéphane Nicoll 37d03e536f Merge pull request #31354 from ralph-riedel
* pr/31354:
  Polish "Use schema-based config in sql-error-codes.xml"
  Use schema-based config in sql-error-codes.xml

Closes gh-31354
2023-10-04 13:17:36 +02:00
Stéphane Nicoll 61f27dafee Polish "Use schema-based config in sql-error-codes.xml"
See gh-31354
2023-10-04 13:12:56 +02:00
ralph.riedel c52645905a Use schema-based config in sql-error-codes.xml
This commit replaces the reference to the beans DTD in
sql-error-codes.xml with the preferred schema-based configuration
approach.

See gh-31354
2023-10-04 13:10:40 +02:00
Brian Clozel 28c97610c2 Polish reflection hints on bean registration interfaces
This commit ensures that we register reflection hints on interfaces in
the entire type hierarchy, including extended interfaces.

Closes gh-31350
2023-10-03 16:02:29 +02:00
Sam Brannen 74fc8bd12d Polish SimpleAliasRegistryTests
See gh-31348
2023-10-03 15:29:22 +02:00
Enrico Freni d507590abf Add missing unit tests for SimpleAliasRegistry
Closes gh-31348
2023-10-03 15:13:42 +02:00
Kai Zander e8b42c5439 Optimize uses of onErrorResume()
This commit replaces uses of onErrorResume() with
- onErrorMap() in places where onErrorResume() is just used to map to a
  different exception.
- onErrorComplete() where onErrorResume() just maps to Mono.empty().
- onErrorReturn() where onErrorResum() just maps to Mono.just().

Closes gh-31352
2023-10-03 14:42:24 +02:00
Brian Clozel 14c5228288 Remove reflection hints workarounds for GraalVM issues
This commit removes the previously introduced reflection hints that were
working around known issues in GraalVM.
Spring Framework 6.1 will require recent maintenance versions of GraalVM
and should not contribute such hints anymore.

Closes gh-30394
2023-10-03 13:37:26 +02:00
Brian Clozel 1fd54912d2 Polish reflection hints on bean registration interfaces
This commit ensures that we register reflection hints on interfaces in
the entire type hierarchy.

Closes gh-31350
2023-10-03 11:24:47 +02:00
Brian Clozel b832df6087 Add reflection hints for bean registration interfaces
Prior to this commit, the bean registration AOT contributions would
register introspection and invocation hints on both declared and public
methods for bean types. The bean introspection algorithm also looks at
default methods implemented by interfaces when collecting bean property
information.

This commit ensures that introspection hints are registered for all
implemented interfaces when registering beans.

Closes gh-31350
2023-10-02 19:33:05 +02:00
Sam Brannen c45bf3c061 Merge branch '6.0.x' 2023-10-02 17:30:29 +02:00
Sam Brannen 147abc91a5 Polish BeanPropertyRowMapper Javadoc 2023-10-02 17:29:26 +02:00
Stéphane Nicoll 263931656b Merge pull request #31351 from izeye
* pr/31351:
  Add Javadoc since for ExponentialBackOff.DEFAULT_MAX_ATTEMPTS

Closes gh-31351
2023-10-02 17:04:17 +02:00
Johnny Lim 4a802c4e1f Add Javadoc since for ExponentialBackOff.DEFAULT_MAX_ATTEMPTS
See gh-31351
2023-10-02 17:04:05 +02:00
Stéphane Nicoll 699947c496 Merge branch '6.0.x' 2023-10-02 15:09:12 +02:00
Stéphane Nicoll e12eb9436d Fix description of default behavior in BeanPropertyRowMapper
Closes gh-29285
2023-10-02 15:07:09 +02:00
Henning Poettker 9cab6c90a9 Allow custom observation convention for RestClient
This commit allows to use a custom `ObservationConvention`
in the `DefaultRestClient`, and to set it through the
`RestClient.Builder`.

Closes gh-31325
2023-10-02 14:55:01 +02:00
Sam Brannen c356ce2637 Polishing 2023-10-01 16:42:51 +02:00
Sam Brannen 9f8293b9c9 Fix copy-n-paste error 2023-10-01 13:05:25 +02:00
Sam Brannen dbf6f7dc9d Polish ExpressionState[Tests] 2023-09-30 11:45:20 +02:00
rstoyanchev 8fa428f825 Skip reconstructing body from request params if query present
This allows restoring optimization in StringHttpMessageConverter
that was undone in 23162b for 6.0.x.

Closes gh-31327
2023-09-29 18:01:18 +01:00
rstoyanchev a6ab636614 Merge branch '6.0.x' 2023-09-29 18:00:52 +01:00
Sam Brannen 95838e18cc Clean up (boolean) (Boolean) casts in tests 2023-09-29 18:16:04 +02:00
rstoyanchev 23162bb306 Undo optimization from 12fe2c that can cause regression
Closes gh-31327
2023-09-29 17:15:23 +01:00
Sam Brannen c3795731b5 Merge branch '6.0.x' 2023-09-29 17:48:15 +02:00
Sam Brannen 35f458fa5f Improve diagnostics for negative repeated text count in SpEL
Due to the changes in gh-31341, if the repeat count in a SpEL
expression (using the repeat operator '*') is negative, we throw a
SpelEvaluationException with the MAX_REPEATED_TEXT_SIZE_EXCEEDED
message which is incorrect and misleading.

Prior to gh-31341, a negative repeat count resulted in an
IllegalArgumentException being thrown by String#repeat(), which was
acceptable in terms of diagnostics, but that did not make it
immediately clear to the user what the underlying cause was.

In light of the above, this commit improves diagnostics for a negative
repeated text count in SpEL expressions by throwing a
SpelEvaluationException with a new NEGATIVE_REPEATED_TEXT_COUNT error
message.

Closes gh-31342
2023-09-29 17:45:21 +02:00
Sam Brannen cddff46165 Merge branch '6.0.x' 2023-09-29 16:53:01 +02:00
Sam Brannen 8e83f93bcb Improve diagnostics for repeated text size overflow in SpEL
If the resulting size of repeated text in a SpEL expression (using the
repeat operator '*') would exceed MAX_REPEATED_TEXT_SIZE, we currently
throw a SpelEvaluationException with the
MAX_REPEATED_TEXT_SIZE_EXCEEDED message.

However, if the calculation of the repeated text size results in
integer overflow, our max size check fails to detect that, and
String#repeat(int) throws a preemptive OutOfMemoryError from which the
application immediately recovers.

To improve diagnostics for users, this commit ensures that we
consistently throw a SpelEvaluationException with the
MAX_REPEATED_TEXT_SIZE_EXCEEDED message when integer overflow occurs.

Closes gh-31341
2023-09-29 16:50:19 +02:00
Juergen Hoeller a3e13c8ba8 Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/util/backoff/ExponentialBackOff.java
2023-09-29 15:01:43 +02:00
Juergen Hoeller 407113945d Polishing 2023-09-29 14:58:02 +02:00
Juergen Hoeller 4cf5c7796d Explicit note on local bean access within @PostConstruct method
Closes gh-27876
2023-09-29 14:57:40 +02:00
Juergen Hoeller 847e8a2b23 Restore auto-commit mode if not done by driver
Closes gh-31268
2023-09-29 14:57:17 +02:00
Sam Brannen 985eb5b8a1 Merge branch '6.0.x' 2023-09-29 13:52:44 +02:00
Sam Brannen 9aab4a60f5 Support safe navigation operator with void methods in SpEL
Prior to this commit the Spring Expression Language (SpEL) was able to
properly parse an expression that uses the safe navigation operator
(?.) with a method that has a `void` return type (for example,
"myObject?.doSomething()"); however, SpEL was not able to evaluate or
compile such expressions.

This commit addresses the evaluation issue by selectively not boxing
the exit type descriptor (for inclusion in the generated bytecode) when
the method's return type is `void`.

This commit addresses the compilation issue by pushing a null object
reference onto the stack in the generated byte code when the method's
return type is `void`.

Closes gh-27421
2023-09-29 13:49:48 +02:00
Sam Brannen 1fe2216c59 Test status quo for null-safe Void method references in SpEL 2023-09-29 13:36:38 +02:00
Sam Brannen 5ff9e6955c Test status quo for void function references in SpEL 2023-09-29 13:36:38 +02:00
Sam Brannen 0cb4043aac Polishing 2023-09-29 13:36:38 +02:00
Stéphane Nicoll 9e144afc0d Merge pull request #31328 from vpavic
* pr/31328:
  Polish "Fix regression in JmsAccessor#setSessionAcknowledgeMode"
  Fix regression in JmsAccessor#setSessionAcknowledgeMode

Closes gh-31328
2023-09-29 08:43:26 +02:00
Stéphane Nicoll 95e6902aef Polish "Fix regression in JmsAccessor#setSessionAcknowledgeMode"
See gh-31328
2023-09-29 08:42:56 +02:00
Vedran Pavic 11c2cde62e Fix regression in JmsAccessor#setSessionAcknowledgeMode
This commit partially reverts 3b8dd0a5, which introduced a strict
validation in JmsAccessor#setSessionAcknowledgeMode that prevents use
of vendor-specific acknowledge modes.

See gh-31328
2023-09-29 08:42:38 +02:00
rstoyanchev a2c5fed494 Make targetType in UknownContentTypeException transient
Closes gh-31283
2023-09-28 16:52:03 +01:00
Stéphane Nicoll ce9ca700f3 Enable test in AbstractAspectJAdvisorFactoryTests
See gh-24190
2023-09-28 15:46:47 +02:00
Juergen Hoeller ef61b4eff3 SimpleAsyncTaskScheduler runs fixed-delay tasks on scheduler thread
Closes gh-31334
2023-09-28 14:34:01 +02:00
Juergen Hoeller 86b764d4d2 Expose public shouldHandle(ApplicationEvent) method
Closes gh-31295
2023-09-28 14:33:26 +02:00
Juergen Hoeller 38a0e17ede Prefer query(Class) method in javadoc example
See gh-26594
2023-09-28 14:33:20 +02:00
Stéphane Nicoll b9bbfb79a4 Merge branch '6.0.x' 2023-09-28 09:32:28 +02:00
Stéphane Nicoll 6030e62766 Merge pull request #31330 from jihuayu
* pr/31330:
  Add missing `conversionService` field in doc example

Closes gh-31330
2023-09-28 09:32:20 +02:00
纪华裕 867b9f61b2 Add missing conversionService field in doc example
See gh-31330
2023-09-28 09:30:50 +02:00
Sam Brannen 515d8aae94 Merge branch '6.0.x' 2023-09-27 16:43:56 +02:00
Sam Brannen 6300fb37ad Include '?' for null-safe navigation in SpEL AST representations
Prior to this commit, if a Spring Expression Language (SpEL) expression
contained property, field, or method references using the null-safe
navigation operator (?.), the generated AST String representation
incorrectly omitted the '?' characters.

For example, 'myProperty?.myMethod()' had a generated AST string
representation of 'myProperty.myMethod()'.

This commit addresses this by introducing isNullSafe() in
MethodReference and reworking the logic in
CompoundExpression.toStringAST().

Closes gh-31326
2023-09-27 16:42:27 +02:00
Sam Brannen 0d22569422 Polishing 2023-09-27 16:34:18 +02:00
rstoyanchev 957b6b2caf Use URI String as fallback in ReactorClientHttpConnector
Closes gh-31033
2023-09-27 14:01:35 +01:00
Sam Brannen 47ed4e6c78 Merge branch '6.0.x' 2023-09-27 13:19:39 +02:00
Sam Brannen 06658c3c71 Restore zero capacity support in ConcurrentLruCache
Since the rewrite of ConcurrentLruCache in Spring Framework 6.0, an
attempt to create a ConcurrentLruCache with zero capacity results in an
IllegalArgumentException even though the documentation states that zero
capacity indicates "no caching, always generating a new value".

This commit restores the ability to configure a ConcurrentLruCache with
zero capacity and introduces corresponding tests (which were first
verified against the 5.3.x branch to ensure backward compatibility).

See gh-26320
Closes gh-31317
2023-09-27 13:18:30 +02:00
Sam Brannen 45d8aadb0a Polishing 2023-09-27 10:19:51 +02:00
Stéphane Nicoll b5db730ca0 Merge pull request #31267 from kang-hl
* pr/31267:
  Update copyright year of changed file
  Optimize MessageSourceSupport

Closes gh-31267
2023-09-27 09:16:57 +02:00
Stéphane Nicoll 182f9117aa Update copyright year of changed file
See gh-31267
2023-09-27 09:14:20 +02:00
kanghailin 08271fa445 Optimize MessageSourceSupport
See gh-31267
2023-09-27 09:13:53 +02:00
Stéphane Nicoll 6486c2a537 Merge pull request #31320 from chaewon121
* pr/31320:
  Polish contribution
  Polish Conditional Statements

Closes gh-31320
2023-09-27 09:01:58 +02:00
Stéphane Nicoll 7a05d23597 Polish contribution
See gh-31320
2023-09-27 08:58:11 +02:00
chaewon121 d6a105c151 Polish Conditional Statements
See gh-31320
2023-09-27 08:57:55 +02:00
Sam Brannen d50ec68ad7 Polish contribution
See gh-31248
2023-09-26 13:49:03 +02:00
Lee Jaeheon 6d2d8a36c2 Introduce initialize() in AbstractRouting[DataSource|ConnectionFactory]
This commit introduces initialize() methods in
AbstractRoutingDataSource and AbstractRoutingConnectionFactory as an
alternative to invoking afterPropertiesSet().

Closes gh-31248
2023-09-26 13:20:11 +02:00
Stéphane Nicoll af0b39a722 Merge pull request #31282 from sephiroth-j
* pr/31282:
  Polish "Use `singleOrEmpty()` instead of `buffer()`"
  Use `singleOrEmpty()` instead of `buffer()`

Closes gh-31282
2023-09-26 12:37:42 +02:00
Stéphane Nicoll f9291214ec Polish "Use singleOrEmpty() instead of buffer()"
See gh-31282
2023-09-26 12:37:28 +02:00
Ronny Perinke cbfb99fef2 Use singleOrEmpty() instead of buffer()
This commit avoids fetching and buffering results in temporary `List` buffers.

See gh-31282
2023-09-26 12:37:28 +02:00
rstoyanchev 2e2a62a23c Polishing 2023-09-26 11:34:40 +01:00
rstoyanchev af7fe013b6 MockMvcHttpConnector supports RequestPostProcessor's
Closes gh-31298
2023-09-26 11:34:40 +01:00
Stéphane Nicoll 0f6b018e97 Merge branch '6.0.x' 2023-09-26 12:30:05 +02:00
Stéphane Nicoll a37abd5e54 Provide best-effort toString for Lazy resolved message
Previously, MessagingMessageListenerAdapter or any adapter relying on
the default MessagingMessageConverter would log an incoming message
with a toString of the Message that does not provide any extra
information. This is due to the default implementation providing a
lazy resolution message that only attempts to extract the payload
when necessary.

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

Closes gh-21265
2023-09-26 12:29:00 +02:00
Sam Brannen 225c9062a1 Merge branch '6.0.x' 2023-09-25 20:19:11 +02:00
Sam Brannen 18456dec52 Reintroduce FastClass in CGLIB class names for @⁠Configuration classes
Given a @⁠Configuration class named org.example.AppConfig which
contains @⁠Bean methods, in Spring Framework 5.3.x and previous
versions, the following classes were created when generating the CGLIB
proxy.

org.example.AppConfig$$EnhancerBySpringCGLIB$$fd7e9baa
org.example.AppConfig$$FastClassBySpringCGLIB$$3fec86e
org.example.AppConfig$$EnhancerBySpringCGLIB$$fd7e9baa$$FastClassBySpringCGLIB$$82534900

Those class names indicate that 1 class was generated for the proxy for
the @⁠Configuration class itself and that 2 additional FastClass
classes were generated to support proxying of @⁠Bean methods in
superclasses.

However, since Spring Framework 6.0, the following classes are created
when generating the CGLIB proxy.

org.example.AppConfig$$SpringCGLIB$$0
org.example.AppConfig$$SpringCGLIB$$1
org.example.AppConfig$$SpringCGLIB$$2

The above class names make it appear that 3 proxy classes are generated
for each @⁠Configuration class, which is misleading.

To address that and to align more closely with how such generated
classes were named in previous versions of the framework, this commit
modifies SpringNamingPolicy so that generated class names once again
include "FastClass" when the generated class is for a CGLIB FastClass
as opposed to the actual proxy for the @⁠Configuration class.

Consequently, with this commit the following classes are created when
generating the CGLIB proxy.

org.example.AppConfig$$SpringCGLIB$$0
org.example.AppConfig$$SpringCGLIB$$FastClass$$0
org.example.AppConfig$$SpringCGLIB$$FastClass$$1

Closes gh-31272
2023-09-25 20:17:10 +02:00
Sam Brannen d17c75a7ef Test status quo for SpringNamingPolicy
See gh-31272
2023-09-25 20:14:29 +02:00
Sam Brannen f547b6ad2a Polishing 2023-09-25 20:14:29 +02:00
Sam Brannen 7aae97bcd4 Revise NO_VIOLATIONS_DETECTED in SpringExtension to clarify intent
See gh-31305
See gh-30962
See gh-30456
2023-09-25 16:48:58 +02:00
Stéphane Nicoll d36c4f75e3 Merge branch '6.0.x' 2023-09-25 15:27:20 +02:00
Stéphane Nicoll e1bd13d3d6 Fix note on CGLIB supported method visibility
CGLIB do support package-private and protected methods now so the
note in the reference doc should be changed accordingly.

Closes gh-25001
2023-09-25 15:27:07 +02:00
Stéphane Nicoll daa902bf20 Merge pull request #31305 from alidandach
* pr/31305:
  Use Objects.equals() for null-safe string comparison

Closes gh-31305
2023-09-25 08:33:05 +02:00
ali dandach 1d12c74042 Use Objects.equals() for null-safe string comparison
See gh-31305
2023-09-25 08:28:33 +02:00
Sam Brannen bc3d98565c Update copyright headers 2023-09-23 13:36:41 +02:00
Sam Brannen a88d5d1c62 Polishing 2023-09-23 13:36:30 +02:00
Sam Brannen d0a088f9dc Clean up warnings in tests 2023-09-23 13:30:05 +02:00
Sam Brannen ebd4f1b45b Merge branch '6.0.x' 2023-09-23 12:41:19 +02:00
Sam Brannen 08237da4b4 Simplify equals() implementation in PerTargetInstantiationModelPointcut
For equivalence, we only need to compare the preInstantiationPointcut
fields since they include the declaredPointcut fields. In addition, we
should not compare the aspectInstanceFactory fields since
LazySingletonAspectInstanceFactoryDecorator does not implement equals().

See gh-31238
2023-09-23 12:40:28 +02:00
Sam Brannen bc03088f69 Merge branch '6.0.x' 2023-09-22 18:18:11 +02:00
Sam Brannen f7496a393d Expand scope of equals() in PerTargetInstantiationModelPointcut
This commit expands the scope of equality checks in the implementation
of equals() for PerTargetInstantiationModelPointcut to include all
fields instead of just the pointcut expression for the declared
pointcut.

See gh-31238
2023-09-22 18:17:07 +02:00
Sam Brannen 64b4a3cf0d Update KeyHolder in JdbcClient when using positional parameters
Prior to this commit, DefaultJdbcClient updated the supplied KeyHolder
when using named parameters but not for positional parameters.

This commit refactors the creation of the
PreparedStatementCreatorFactory so that the PreparedStatementCreator
properly creates a PreparedStatement which returns generated keys.

Closes gh-31297
2023-09-22 17:21:21 +02:00
Sam Brannen 4841e52205 Rename constants in JdbcClientIndexedParameterTests 2023-09-22 16:49:46 +02:00
Brian Clozel f0686094ff Merge branch '6.0.x' 2023-09-22 11:33:30 +02:00
Brian Clozel 0f92ba1663 Fix typo in ref docs for pattern comparison
Closes gh-31294
2023-09-22 11:32:50 +02:00
Brian Clozel 1e5e8db0e0 Add missing reflection hint in BeanRegistrationsAotContribution
Prior to this commit, the `BeanRegistrationsAotContribution` would only
contribute introspection hints for declared methods. This does not cover
inherited public methods.

This commit adds the missing hint on public methods.

Fixes gh-31293
2023-09-22 10:36:38 +02:00
Brian Clozel db5ba8562f Upgrade SDKMAN to 17.0.8.1 2023-09-22 09:45:46 +02:00
Brian Clozel 8708a21143 Configure Gradle toolchain auto-provisioning
This commit configures the Foojay resolver plugin in the Gradle build in
order to auto-provision a required JDK distribution if it's not present
already on the host.

Currently the Spring Framework build requires both a JDK 17 and a JDK 21
distribution to build artifacts.

Closes gh-30474
2023-09-22 09:44:12 +02:00
Brian Clozel 0aec9f12ce Upgrade to Gradle Enterprise 3.14 2023-09-22 09:43:44 +02:00
Brian Clozel d926769a5e Fix copyright headers
See gh-30137
2023-09-22 09:36:38 +02:00
Brian Clozel 1afb6f1861 Upgrade to Java 21 in CI image 2023-09-22 09:02:12 +02:00
rstoyanchev 6b35d43020 Polishing contribution
Closes gh-30113
2023-09-20 18:50:33 +01:00
Andreas Bergander 732f0a6a77 DefaultServletHttpRequestHandler supports DispatcherType.INCLUDE
See gh-30113
2023-09-20 18:50:32 +01:00
rstoyanchev cc296c5033 Polishing contribution
Closes gh-30137
2023-09-20 18:44:33 +01:00
Joakim Mohn a1c4fb3840 Lenient URI encoding handling in ForwardedHeaderTransformer
See gh-30137
2023-09-20 18:44:33 +01:00
rstoyanchev 0f7c406a86 Suppress handler mapping logging for introspector
Closes gh-30349
2023-09-20 18:44:33 +01:00
rstoyanchev 2530efd1c7 SseEmitter support for multiline String
Closes gh-30965
2023-09-20 18:44:33 +01:00
Sam Brannen 9350091163 Merge branch '6.0.x'
# Conflicts:
#	spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJPointcutAdvisor.java
#	spring-tx/src/test/java/org/springframework/transaction/annotation/AnnotationTransactionInterceptorTests.java
2023-09-20 17:06:35 +02:00
Sam Brannen 865fa33927 Cache CGLIB proxy classes properly again
The introduction of AdvisedSupport.AdvisorKeyEntry in Spring Framework
6.0.10 resulted in a regression regarding caching of CGLIB generated
proxy classes. Specifically, equality checks for the proxy class cache
became based partially on identity rather than equivalence. For
example, if an ApplicationContext was configured to create a
class-based @Transactional proxy, a second attempt to create the
ApplicationContext resulted in a duplicate proxy class for the same
@Transactional component.

On the JVM this went unnoticed; however, when running Spring
integration tests within a native image, if a test made use of
@⁠DirtiesContext, a second attempt to create the test
ApplicationContext resulted in an exception stating, "CGLIB runtime
enhancement not supported on native image." This is because Test AOT
processing only refreshes a test ApplicationContext once, and the
duplicate CGLIB proxy classes are only requested in subsequent
refreshes of the same ApplicationContext which means that duplicate
proxy classes are not tracked during AOT processing and consequently
not included in a native image.

This commit addresses this regression as follows.

- AdvisedSupport.AdvisorKeyEntry is now based on the toString()
  representations of the ClassFilter and MethodMatcher in the
  corresponding Pointcut instead of the filter's and matcher's
  identities.

- Due to the above changes to AdvisorKeyEntry, ClassFilter and
  MethodMatcher implementations are now required to implement equals(),
  hashCode(), AND toString().

- Consequently, the following now include proper equals(), hashCode(),
  and toString() implementations.

  - CacheOperationSourcePointcut
  - TransactionAttributeSourcePointcut
  - PerTargetInstantiationModelPointcut

Closes gh-31238
2023-09-20 16:56:09 +02:00
Sam Brannen 9120f87897 Consolidate AspectJ test fixtures 2023-09-20 16:47:05 +02:00
Sam Brannen edd1e9134f Polishing 2023-09-20 16:47:05 +02:00
김희망 6caef9bb3c Refine ServerRequest.queryParamOrNull implementation
Closes gh-31264
2023-09-20 15:51:09 +02:00
Brian Clozel a97ff39088 Add reflection hint on Publisher for bean destroy support
Prior to this commit, `DisposableBeanAdapter` supported reactive bean
destroy methods by detected if `Publisher` is available on the
classpath. The AOT engine did not contribute a reflection hint for this
call.

This commit ensures that this reflection hint is registered in all
cases, even if there are no destroy methods detected on beans.

Fixes gh-31278
2023-09-20 14:43:12 +02:00
Juergen Hoeller d46c26d903 Call Lifecycle.stop() for already started beans on failed refresh
Closes gh-20028
2023-09-19 16:45:58 +02:00
Arjen Poutsma ecd3f191b6 Refactoring external contribution
Created abstract CharSequence decoder, which is extended by
StringDecoder and CharBufferDecoder.

See gh-29741
2023-09-19 16:24:07 +02:00
Markus Heiden 59771318ce Introduce CharBufferDecoder
This commit introduces the CharBufferDecoder.

Closes gh-29741
2023-09-19 16:24:07 +02:00
Brian Clozel 103c6b8bda Add missing reflection hint on Eclipse FileLocator
`PathMatchingResourcePatternResolver` is reflecting on
`org.eclipse.core.runtime.FileLocator` and invoking methods on it for
OSGi support. While this use case is highly unlikely in native images,
registering the reflection entry by itself should be enough.

Fixes gh-31271
2023-09-19 16:06:43 +02:00
Brian Clozel 7af9ce4f03 Add resource hint for spring.properties
Fixes gh-31270
2023-09-19 15:57:59 +02:00
Brian Clozel 4c343ef796 Add missing reflection hints on Kotlin classes
This commit adds the relevant reflection hints required by
`KotlinDetector`; this class is trying to detect both `kotlin.Metadata`
and `kotlin.reflect.full.KClasses`.

Fixes gh- 31269
2023-09-19 15:49:46 +02:00
Brian Clozel a1f4cdf54e Add missing reflection hint on MonetaryAmount
Fixes gh-31266
2023-09-19 15:48:23 +02:00
Brian Clozel 8074f938b1 Add missing reflection hints on Jakarta types
This commit adds reflection hints for `jakarta.inject.Provider` and
ensures that hints are always contributed even if jakarta classes are
not on the classpath.

Fixes gh-31259
2023-09-19 15:46:13 +02:00
Brian Clozel e53c2c6331 Reduce nested class lookups in ClassUtils
Prior to this commit, `ClassUtils#forName` would always attempt to
resolve the given class name as a nested type. For example, searching
for `org.example.Spring` would try to resolve:

* `org.example.Spring`
* if not available, try `org.example$Spring` as well

Java classes usually start with uppercase letters, so this additional
lookup can be costly and not very useful.

This commit only attempts nested class lookups when the previous segment
starts with an uppercase. So `org.example.Spring.Issue` will look for
`org.example.Spring$Issue`, but `org.example.Spring` will not.

Closes gh-31258
2023-09-19 15:12:53 +02:00
Stéphane Nicoll 05500373e2 Merge branch '6.0.x' 2023-09-18 17:02:26 +02:00
Stéphane Nicoll fef3cf8e58 Review AOT-generated code for beanClass and targetType
This commit reviews when an AOT-generated bean definition defines a
beanClass or targetType. Previously, a beanClass was not consistently
set which could lead to issues.

Closes gh-31242
2023-09-18 16:58:01 +02:00
Sébastien Deleuze 4128f4d5c9 Print JVM restoration time in DefaultLifecycleProcessor
Closes gh-31252
2023-09-18 10:57:09 +02:00
Stéphane Nicoll 2fbcff8919 Prevent ValueLoaderEntryProcessor to be created for each get call
Closes gh-31250
2023-09-18 09:27:16 +02:00
Stéphane Nicoll f79bc7b14d Implement JCacheCache#putIfAbsent as atomic operation
This commit modifies putIfAbsent to use an EntryProcessor that
guarantees that the operation is atomic.

Closes gh-21591
2023-09-18 09:09:47 +02:00
Stéphane Nicoll 57a4628934 Polish log message
See gh-29773
2023-09-18 08:28:10 +02:00
Stéphane Nicoll 6e5c4ef864 Merge pull request #29773 from qpakzk
* pr/29773:
  Log attempt at proxying final methods to WARN instead of INFO

Closes gh-29773
2023-09-18 08:27:12 +02:00
Sangwon Hong fcbe5fa73f Log attempt at proxying final methods to WARN instead of INFO
See gh-29773
2023-09-18 08:25:37 +02:00
Sam Brannen 7bf520fa8d Make utility methods consistently static in DispatcherServlet
See gh-31244
2023-09-16 18:38:24 +02:00
Sam Brannen d30ad794ab Update copyright headers
See gh-31245
2023-09-16 18:16:27 +02:00
shin-mallang 3d0f55273c Replace double spaces w/ single spaces in code & comments in spring-webmvc
Except for meaningful double spaces (for example, to align the
indentation of comments), this commit replaces all unnecessary double
spaces with single spaces in the spring-webmvc module.

Closes gh-31245
2023-09-16 18:13:32 +02:00
Sam Brannen 56688ab361 Polish contribution
See gh-31244
2023-09-16 18:09:18 +02:00
shin-mallang 3932f91117 Use List#isEmpty() in DispatcherServlet
This commit uses !isEmpty() instead of size() > 0.

Closes gh-31244
2023-09-16 18:04:30 +02:00
Sam Brannen 293e6ddf85 Polishing 2023-09-16 15:25:16 +02:00
Sam Brannen b05e46d502 Update copyright headers 2023-09-16 15:23:10 +02:00
Sébastien Deleuze 20df52e543 Merge branch '6.0.x' 2023-09-15 18:16:26 +02:00
Sébastien Deleuze ce0923b946 Remove Reactor Netty 2 from integration tests
Closes gh-31243
2023-09-15 18:15:26 +02:00
Brian Clozel 7ecbdc19a5 Merge branch '6.0.x' 2023-09-15 17:54:06 +02:00
Brian Clozel 227049824c Fix RuntimeHintsPredicates matching rules
Prior to this commit, the `RuntimeHintsPredicates` would assume that
registering introspection or invocation hints for "all declared methods"
on a type would also include "all public methods". This is not true, as
the Java reflection API itself behaves differently.
`getDeclaredMethods()` does not return a superset of `getMethods()`, as
the latter can return inherited methods, but not the former.
Same reasoning applies to fields.

This commit fixes the hints predicates to only match if the correct hint
has been registered.

Fixes gh-31224
2023-09-15 17:50:53 +02:00
Juergen Hoeller aa1360b154 Complete set of constructors with consistent javadoc
Closes gh-31234
2023-09-15 17:45:13 +02:00
Marten Deinum e42e89c04f Add constructors to take ObjectMapper
Prior to this commit in the message converters it was possible
to set a pre-configured ObjectMapper. However the constructor
would still create and configure an ObjectMapper.

With the added constructor it is now possible to directly
construct the message converter with the proper ObjectMapper.
This prevents the this additional ObjectMapper to be constructed.
2023-09-15 17:19:51 +02:00
Stéphane Nicoll f628c601a7 Merge pull request #28132 from ctailor2
* pr/28132:
  Polish "Allow batch update to take a KeyHolder"
  Allow batch update to take a KeyHolder

Closes gh-28132
2023-09-15 16:46:36 +02:00
Stéphane Nicoll c21a9b94c5 Polish "Allow batch update to take a KeyHolder"
See gh-28132
2023-09-15 16:46:21 +02:00
Chirag Tailor 78db5dd516 Allow batch update to take a KeyHolder
See gh-28132
2023-09-15 16:38:17 +02:00
Arjen Poutsma 056de7e898 Enable disabled multi-part Netty 2 tests
See gh-31110
2023-09-15 14:20:12 +02:00
Arjen Poutsma 81ebc3a6f3 MultipartParser should respect read position
This commit ensures that the MultipartParser takes a buffer's read
position into account.

Closes gh-31110
2023-09-15 14:20:12 +02:00
Arjen Poutsma 8f130316d2 MultipartParser should respect read position
This commit ensures that the MultipartParser takes a buffer's read
position into account.

Closes gh-31110
2023-09-15 13:46:04 +02:00
Stéphane Nicoll 6d948d03e5 Remove outdated declaration
See gh-25933
2023-09-15 11:19:51 +02:00
Stéphane Nicoll c3d1a886de Merge pull request #23651 from runeflobakk
* pr/23651:
  Polish contribution
  Add default methods to MailSender and JavaMailSender when appropriate

Closes gh-23651
2023-09-15 10:28:43 +02:00
Stéphane Nicoll 978c409d85 Polish contribution
See gh-23651
2023-09-15 10:25:16 +02:00
Rune Flobakk f67fad4c14 Add default methods to MailSender and JavaMailSender when appropriate
send(..) -methods of JavaMailSenderImpl which is only delegating to
other methods are pulled up as default methods in the interfaces
JavaMailSender and MailSender, to make these interfaces require fewer
methods to implement.

See gh-23651
2023-09-15 10:25:06 +02:00
Stéphane Nicoll 3c4eef1d73 Merge pull request #31237 from ghainesii
* pr/31237:
  Add missing period in RestClient documentation

Closes gh-31237
2023-09-15 08:58:14 +02:00
ghainesii 0a324ea9a7 Add missing period in RestClient documentation
See gh-31237
2023-09-15 08:57:47 +02:00
Niharika Tiwari 9d7f9b5284 Improve wording in Javadoc for @⁠Autowired
#31235
2023-09-14 17:45:03 +02:00
Juergen Hoeller 4746f587ea Merge branch '6.0.x'
# Conflicts:
#	gradle.properties
2023-09-14 16:51:52 +02:00
Juergen Hoeller 54c4f1b226 Reset findLoadedClassMethod in case of makeAccessible failing
Closes gh-31232
2023-09-14 16:45:16 +02:00
Yanming Zhou 46397381ba Eliminate synchronized block to avoid thread pinning in SingletonSupplier 2023-09-14 16:37:32 +02:00
Sam Brannen 09b1e5edf6 Extract instantiateComponents() method in AbstractTestContextBootstrapper 2023-09-14 14:52:35 +02:00
Spring Builds 062c6241e1 Next development version (v6.0.13-SNAPSHOT) 2023-09-14 08:03:11 +00:00
Juergen Hoeller 59961960dd Merge branch '6.0.x' 2023-09-14 09:30:40 +02:00
Juergen Hoeller a51eb29e50 Clarify IN clause resolution with List/Iterable parameter
Closes gh-31228
2023-09-14 09:24:18 +02:00
Stephane Nicoll 727f69ae70 Merge branch '6.0.x' 2023-09-13 21:25:14 +02:00
Stephane Nicoll 92b6c5df4f Upgrade to Context Propagation 1.1.0-M4
Closes gh-31220
2023-09-13 21:10:46 +02:00
Stephane Nicoll e109c55192 Upgrade to Reactor 2023.0.0-M3
Closes gh-31219
2023-09-13 21:10:46 +02:00
Stephane Nicoll 8f21c228b8 Upgrade to Micrometer 1.12.0-M3
Closes gh-31218
2023-09-13 21:10:46 +02:00
Sam Brannen a220c545fc Support declarative ContextCustomizerFactory registration in the TCF
Prior to this commit, it was only possible to register a
ContextCustomizerFactory in the TestContext framework (TCF) via the
SpringFactoriesLoader mechanism.

This commit introduces support for declarative registration of a
ContextCustomizerFactory local to a test class via a new
@ContextCustomizerFactories annotation.

Closes gh-26148
2023-09-13 19:59:50 +02:00
Sam Brannen 99a50e7cea Polishing 2023-09-13 19:52:17 +02:00
Sébastien Deleuze 68ba55bea9 Fix ModelInitializerKotlinTests
See gh-30894
2023-09-13 18:30:01 +02:00
Stephane Nicoll 50d4a44dfc Upgrade to Context Propagation 1.0.5
Closes gh-31223
2023-09-13 18:19:06 +02:00
Stephane Nicoll ebf2cef94e Upgrade to Reactor 2022.0.11
Closes gh-31222
2023-09-13 18:17:52 +02:00
Stephane Nicoll c89002a0fb Upgrade to Micrometer 1.10.11
Closes gh-31221
2023-09-13 18:16:59 +02:00
Sébastien Deleuze bb85d9b5e4 Merge branch '6.0.x' 2023-09-13 18:07:59 +02:00
Sébastien Deleuze 29a4dabbe7 Support @ModelAttribute with suspending function in WebFlux
Closes gh-30894
2023-09-13 17:59:39 +02:00
Sam Brannen a678be80ea Merge branch '6.0.x' 2023-09-13 17:51:02 +02:00
Sam Brannen f5f8eab405 Remove duplicated section links for test annotations
Since the auto-generated "Section Summary" includes the exact same
links, there's no need to manually duplicate them.
2023-09-13 17:50:12 +02:00
Juergen Hoeller 550f05c9dc Merge branch '6.0.x'
# Conflicts:
#	spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java
2023-09-13 17:28:54 +02:00
Juergen Hoeller 659500bc1f Polishing 2023-09-13 17:27:32 +02:00
Juergen Hoeller 4235a11c4f Throw IllegalArgumentException for unsupported Duration values
Closes gh-31210
2023-09-13 17:15:32 +02:00
Juergen Hoeller 966b0a92c6 Defensively call Resource.getFile() for fallback resolution
Closes gh-31216
2023-09-13 17:14:04 +02:00
Sam Brannen 5bcbcb3049 Simplify SynthesizedMergedAnnotationInvocationHandler.invoke() 2023-09-13 17:14:03 +02:00
Sam Brannen fe7355d5b0 Polishing 2023-09-13 17:04:39 +02:00
Sam Brannen a271d5ec15 Use nullSafeHashCode() in SynthesizedMergedAnnotationInvocationHandler
In light of the refinements to ObjectUtils, this commit updates
SynthesizedMergedAnnotationInvocationHandler to use
ObjectUtils.nullSafeHashCode() and removes the now obsolete code in
SynthesizedMergedAnnotationInvocationHandler.

See gh-29051
2023-09-13 16:50:58 +02:00
Sam Brannen af13967e2a Polishing 2023-09-13 16:50:58 +02:00
Juergen Hoeller ae8a353041 Reject iterable/collection value for positional parameter
Closes gh-31215
2023-09-13 16:50:01 +02:00
Juergen Hoeller 8f6c56fe9a Support for one-time tasks with just @Scheduled(initialDelay=...)
Closes gh-31211
2023-09-13 16:48:54 +02:00
Sam Brannen e63e3a6d28 Delete obsolete constants 2023-09-13 16:13:09 +02:00
Sam Brannen fa1dd74aff Merge branch '6.0.x' 2023-09-13 16:10:29 +02:00
Sam Brannen 4ca70256d6 Backport polishing 2023-09-13 16:09:59 +02:00
Sam Brannen 5dacf688b2 Polishing 2023-09-13 16:01:11 +02:00
Sam Brannen e5f18798ca Revert deprecation of [Simple]CommandLinePropertySource
This commit reverts the deprecation of CommandLinePropertySource and
SimpleCommandLinePropertySource, since we have discovered that Spring
Boot actively uses SimpleCommandLinePropertySource in
org.springframework.boot.SpringApplication.

Closes gh-31207
2023-09-13 15:58:00 +02:00
Stephane Nicoll 01f717375b Introduce ObjectUtils#nullSafeHash(Object... element)
This commit deprecates the various nullSafeHashCode methods taking array
types as they are superseded by Arrays.hashCode now. This means that
the now only remaining nullSafeHashCode method does not trigger a
warning only if the target type is not an array. At the same time, there
are multiple use of this method on several elements, handling the
accumulation of hash codes.

For that reason, this commit also introduces a nullSafeHash that takes
an array of elements. The only difference between Objects.hash is that
this method handles arrays.

The codebase has been reviewed to use any of those two methods when it
is possible.

Closes gh-29051
2023-09-13 15:14:34 +02:00
Stephane Nicoll f2e898d35d Polish 2023-09-13 14:30:01 +02:00
rstoyanchev bd4b3866fc Revise solution for WebFlux JettyRequestUpgradeStrategy
See gh-30344
2023-09-13 13:25:13 +01:00
Sam Brannen c23795a8a6 Update copyright headers 2023-09-13 13:57:51 +02:00
Sam Brannen c598f0565a Deprecate CommandLinePropertySource and associated implementations
Closes gh-31207
2023-09-13 13:56:24 +02:00
Sam Brannen e7cf54d4e2 Revise SpEL inline collection caching improvements
This commit revises the contribution for gh-25921 in the following ways.

- Use instanceof pattern matching

- Use List.of() and Map.of()

- Add missing @⁠since tags

- Polish Javadoc

- Rename isNegativeNumber() to isNegativeNumberLiteral()

- Restructure InlineCollectionTests using @⁠Nested, etc.

- Fix testListWithVariableNotCached() test: it previously set a SpEL
  "variable" but tested a "property" in the root context object, which
  effectively did not test anything.

- Introduce additional tests: listWithPropertyAccessIsNotCached(),
  mapWithVariableIsNotCached(), and mapWithPropertyAccessIsNotCached().
2023-09-13 13:35:41 +02:00
Sam Brannen 2cc1ee78c1 Polishing 2023-09-13 13:33:21 +02:00
rstoyanchev 1f1f222b8b Partial revert of 1f8913a9
For WebFlux we can't use ServletContextAware.

See gh-30344
2023-09-13 12:05:09 +01:00
rstoyanchev 74182cd3d6 Ensure correct detection of Jetty WebSocket server 2023-09-13 09:34:07 +01:00
rstoyanchev 1f8913a96c Support Jetty WebSocket server parameters
Closes gh-30344
2023-09-13 09:34:07 +01:00
rstoyanchev 29e3acc887 Re-enable Jetty in spring-websocket tests 2023-09-13 09:34:07 +01:00
Sébastien Deleuze 5d454390f0 Polishing
See gh-25921
2023-09-13 10:29:32 +02:00
Semyon Danilov 6f9546722a Improve SpEL inline collection caching
This commit fixes SpEL inline collection caching with
with negative keys or values.

Closes gh-25921
2023-09-13 10:29:01 +02:00
Sébastien Deleuze 6548cee20a Document CoWebFilter.COROUTINE_CONTEXT_ATTRIBUTE
See gh-27522
2023-09-12 19:27:49 +02:00
Sébastien Deleuze abb296c7d2 Remove Java code dependency on CoWebFilter
To avoid compilation errors in Eclipse which does
not support Java code dependency on Kotlin code.

See gh-27522
2023-09-12 19:27:49 +02:00
Sam Brannen b6fdfe8ee3 Remove duplicated terms in documentation
... using the following RegEx to find them:

(?<!\S)(\w+)(?:\s+\1)+(?!\S)
2023-09-12 19:00:28 +02:00
Sam Brannen 345910591a Polishing 2023-09-12 15:08:11 +02:00
Arjen Poutsma 9df735b3ab Merge pull request #30028 from yuzawa-san:request-predicate-commit
* gh-30028:
  Polishing external contribution
  Improve attribute handling in RequestPredicates
2023-09-12 12:36:23 +02:00
Arjen Poutsma c5c843696b Polishing external contribution 2023-09-12 12:34:44 +02:00
James Yuzawa 39786e4790 Improve attribute handling in RequestPredicates
This commit changes the way request attributes are handled in
RequestPredicates. Previously, the AND/OR/NOT predicates copied all
attributes in a map, and restored that when the delegate predicate(s)
failed.
Now, we only set the attributes when all delegates have succeeded.

Closes gh-30028
2023-09-12 12:34:44 +02:00
Rossen Stoyanchev ed172d6269 ByteBuffer handling for Jetty WebSocket messages
Closes gh-31182
2023-09-12 10:08:57 +01:00
rstoyanchev f51838b6ba Polishing spring-websocket tests 2023-09-12 10:08:57 +01:00
Brian Clozel 19588d413d Auto-detect observability beans in WebHttpHandlerBuilder
This commit ensures that both `ObservationRegsitry` and
`ServerRequestObservationConvention` beans are automatically detected in
the application context if they are unique. This aligns with the
existing behavior for all other builder methods.

Closes gh-31205
2023-09-11 21:17:14 +02:00
Sébastien Deleuze dfd631e662 Merge branch '6.0.x' 2023-09-11 18:10:13 +02:00
Sébastien Deleuze c892ce5537 Refine CORS documentation for wildcard processing
This commit adds a reference documentation section dedicated
to CORS credentialed requests and related wildcard processing.

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

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

See gh-31143
2023-09-11 18:07:31 +02:00
Juergen Hoeller 3099710087 Merge branch '6.0.x'
# Conflicts:
#	spring-r2dbc/src/main/java/org/springframework/r2dbc/connection/R2dbcTransactionManager.java
#	spring-r2dbc/src/test/java/org/springframework/r2dbc/connection/R2dbcTransactionManagerUnitTests.java
2023-09-11 17:40:11 +02:00
Juergen Hoeller db7654225e Polishing 2023-09-11 17:36:57 +02:00
Juergen Hoeller 78fce80c43 AnnotationUtils.clearCache() includes all annotation caches
Closes gh-31170
2023-09-11 17:36:32 +02:00
Juergen Hoeller 268043e9c9 Align abstract method signatures with original Commons Logging API
Closes gh-31166
2023-09-11 17:36:07 +02:00
Juergen Hoeller 2880e6fba5 Consistently release savepoint after nested transaction
Closes gh-31133
2023-09-11 17:36:00 +02:00
Sam Brannen a199654a62 Use MergedAnnotations API in AnnotationBeanNameGenerator where feasible
AnnotationBeanNameGenerator was written before the introduction of the
MergedAnnotations API and therefore heavily relies on the
AnnotationMetadata abstraction and various helper methods for ASM
compatibility.

However, recent work on determineBeanNameFromAnnotation() has made it
apparent that we should use the MergedAnnotations API directly in
AnnotationBeanNameGenerator where feasible in order to avoid
unnecessary, repeated iterations/streams over the same annotation
metadata.

Closes gh-31203
2023-09-11 17:20:01 +02:00
Stephane Nicoll bf5ce82254 Move custom code fragments requirements at the right place
This commit moves the check on bean definitions having an instance
supplier where they are actually used.

Closes gh-31200
2023-09-11 17:13:04 +02:00
Stephane Nicoll 66a571fe27 Make constructorOrFactory method resolution optional
This commit allows a custom code fragment to provide the code to
create a bean without relying on ConstructorResolver. This is especially
important for use cases that derive from the default behaviour and
provide an instance supplier with the regular runtime scenario.

This is a breaking change for code fragments providing a custom
implementation of the related methods. As it turns out, almost all of
them did not need the Executable argument. Configuration class parsing
is the exception, where it needs to provide a different constructor in
the case of the proxy. To make this use case possible,
InstanceSupplierCodeGenerator has been made public.

Closes gh-31117
2023-09-11 15:55:22 +02:00
Sam Brannen fceed9f3e5 Remove @Nullable on attributes parameter in isStereotypeWithNameValue() 2023-09-11 14:54:55 +02:00
christophejan 8d4ea72e4e Skip release connection after nested with existing transaction 2023-09-11 14:20:37 +02:00
Sam Brannen 5c7bf0c2fe Add tests for MethodInvoker behavior in the TestContext framework
See gh-31199
2023-09-11 13:15:21 +02:00
Sam Brannen 4aeeacb4c2 Simplify and rename TestContextManager[ListenerExecutionOrder]Tests 2023-09-11 13:11:16 +02:00
rstoyanchev 38a9c2ceeb Polishing contribution
See gh-31164
2023-09-11 11:27:25 +01:00
Dmitrii Bocharov fe8e6d3d5a Merge MultipartFileArgumentResolver into RequestPartArgumentResolver
Also add test with Optional parameter for a RequestPart argument.

See gh-31164

Signed-off-by: Dmitrii Bocharov <bdshadow@gmail.com>
2023-09-11 11:27:25 +01:00
Brian Clozel f83c609436 Polish
This commit replaces the initial allocation size for the content caching
buffer by a `FastByteArrayOutputStream`. With this variant, allocations
are cheap and we don't need to apply heuristics anymore to guess the
best initial buffer size.

See gh-29775
2023-09-11 10:58:01 +02:00
Ryan Rupp 6de0be16c2 Optimize initial buffer size in ContentCachingRequestWrapper
Prior to this commit, the initial buffer size for content caching
allocated in `ContentCachingRequestWrapper` would be:

* the request content length, if available in request headers
* the cache limit size as configured on the wrapper

The latter is really an upper bound and should not be considered as a
good default in most cases. This commit ensures that the request content
length is still used if available, but uses a default 1024 size if it's
not.

While this change will probably cause more reallocations as the buffer
grows, this will avoid large allocations in many cases and should
overall help with GC.

Closes gh-29775
2023-09-11 10:36:40 +02:00
Sam Brannen ed83461021 Support parameter injection in @[Before|After]Transaction methods
Prior to this commit, @​BeforeTransaction and @​AfterTransaction
methods could not accept any arguments. This is acceptable with testing
frameworks such as JUnit 4 and TestNG that do not provide support for
parameter injection. However, users of JUnit Jupiter have become
accustomed to being able to accept arguments in lifecycle methods
annotated with JUnit's @​BeforeEach, @​AfterEach, etc.

As a follow up to the previous commit (see gh-31199), this commit
introduces first-class support for parameter injection in
@​BeforeTransaction and @​AfterTransaction methods, as demonstrated in
the following example.

@​BeforeTransaction
void verifyInitialDatabaseState(@Autowired DataSource dataSource) {
	// Use the DataSource to verify the initial DB state
}

Closes gh-30736
2023-09-10 20:15:26 +02:00
Sam Brannen 41904d46ad Introduce MethodInvoker API for TestExecutionListeners
In order to be able to support parameter injection in
@​BeforeTransaction and @​AfterTransaction methods (see gh-30736), this
commit introduces a MethodInvoker API for TestExecutionListeners as a
generic mechanism for delegating to the underlying testing framework to
invoke methods.

The default implementation simply invokes the method without arguments,
which allows TestExecutionListeners using this mechanism to operate
correctly when the underlying testing framework is JUnit 4, TestNG, etc.

A JUnit Jupiter specific implementation is registered in the
SpringExtension which delegates to the
ExtensionContext.getExecutableInvoker() mechanism introduced in JUnit
Jupiter 5.9. This allows a TestExecutionListener to transparently
benefit from registered ParameterResolvers in JUnit Jupiter (including
the SpringExtension) when invoking user methods, effectively providing
support for parameter injection for arbitrary methods.

Closes gh-31199
2023-09-10 20:15:12 +02:00
Sam Brannen 0ebdd8cb98 Polishing 2023-09-10 20:15:04 +02:00
Sam Brannen b082f546ec Polishing 2023-09-10 14:59:21 +02:00
liaozan 9728b8cefd Use Method#isDefault to find default methods in interfaces
Closes gh-31197
2023-09-10 14:53:05 +02:00
Sam Brannen 6ca01e15cf Polishing 2023-09-10 14:50:47 +02:00
Toshiaki Maki 588b5a45f8 Pass correct SqlParameterSource to NamedParameterJdbcTemplate in DefaultJdbcClient
Prior to this commit, when using RowCallbackHandler or ResultSetExtractor in JdbcClient
and passing a parameter to paramSource(), an exception was thrown stating "No value
supplied for the SQL parameter 'xxxxxx'" because the SqlParameterSource used internally
was the wrong one.

Closes gh-31195
2023-09-10 14:42:54 +02:00
Sam Brannen 436c7136e9 Polish TransactionAssert 2023-09-10 14:37:28 +02:00
Sam Brannen 7305692005 Merge branch '6.0.x' 2023-09-10 14:37:01 +02:00
Zakaria Shahen 11dc11e989 Fix typo in comment in XML configuration example
Closes gh-31194
2023-09-10 14:36:17 +02:00
Sam Brannen 0f36c5fd6a Polishing 2023-09-08 20:12:44 +02:00
Sam Brannen 60d05d4204 Polishing 2023-09-08 19:29:28 +02:00
Sam Brannen dfea3d05aa Revise support for JSR-330 and Jakarta @Inject for autowiring test constructors
Closes gh-29851
2023-09-08 19:29:28 +02:00
Florian Lehmann 8dd857a84d Support @Inject from JSR-330 & Jakarta for autowiring test constructors
See gh-29851
2023-09-08 19:26:39 +02:00
Brian Clozel 0f945873a3 Only reset response buffer for error handling
Prior to this commit, `DispatcherServlet` would completely reset the
response (status, headers and body) before handling errors within Spring
MVC. This can cause unintended consequences when Servlet Filters added
response headers before the error happened. Such response headers might
be still required in case of error handling.

This commit changes the complete reset of the response to only resetting
the response buffer, if possible.

Closes gh-31154
See gh-31104
2023-09-08 18:47:21 +02:00
Sébastien Deleuze 88ee8fc92f Upgrade to CRaC 1.4.0
Closes gh-31190
2023-09-08 17:53:08 +02:00
Sam Brannen 154aec7d75 Merge branch '6.0.x' 2023-09-08 17:22:16 +02:00
Sam Brannen 10de295a72 Document StandardTypeLocator configuration to support user types
Prior to this commit, it was unclear to users and third parties that it
is necessary to manually configure a StandardTypeLocator with a
specific ClassLoader to ensure that the SpEL expression parser is able
to reliably locate user types.

For example, the StandardBeanExpressionResolver in the spring-context
module configures a StandardTypeLocator using the bean ClassLoader of
the corresponding BeanFactory.

This commit improves the documentation to raise awareness of this fact.

Closes gh-26253
2023-09-08 17:19:51 +02:00
Sam Brannen a11b8039c5 Merge branch '6.0.x' 2023-09-08 16:31:11 +02:00
Sam Brannen 1227fe5774 Polishing 2023-09-08 16:30:53 +02:00
Sam Brannen f0b1133b12 Merge branch '6.0.x' 2023-09-08 16:12:29 +02:00
Sam Brannen ea41051651 Do not invoke [Map|Collection].isEmpty() in nullSafeConciseToString()
gh-30810 introduced explicit support for collections and maps in
ObjectUtils.nullSafeConciseToString() by invoking isEmpty() on a Map or
Collection to determine which concise string representation should be
used. However, this caused a regression in which an exception was
thrown if the Map or Collection was a proxy generated by
AbstractFactoryBean to support <util:set />, <util:list />, and
<util:map /> in XML configuration.

This commit addresses this set of regressions by always returning
"[...]" or "{...}" for a Collection or Map, respectively, disregarding
whether the map is empty or not.

Closes gh-31138
2023-09-08 16:03:00 +02:00
Stephane Nicoll 91f65e63b4 Merge pull request #30068 from enimiste
* pr/30068:
  Polish "Add return type check on GetterPointcut"
  Add return type check on GetterPointcut

Closes gh-30068
2023-09-08 15:37:07 +02:00
Stephane Nicoll 3e424e3ce7 Polish "Add return type check on GetterPointcut"
See gh-30068
2023-09-08 15:30:52 +02:00
Sam Brannen 311c58ea2d Polish [Standard]TypeLocator 2023-09-08 15:21:48 +02:00
Sam Brannen 40f1cf67bd Polish DefaultClientResponseTests and suppress "unchecked" warnings 2023-09-08 15:21:48 +02:00
Sam Brannen 6da9aed055 Update copyright header 2023-09-08 15:21:48 +02:00
Enimiste d1dfac4e5d Add return type check on GetterPointcut
See gh-30068
2023-09-08 15:20:53 +02:00
Sam Brannen c9e13575ca Use switch expression and constants in CallMetaDataProviderFactory 2023-09-08 14:05:03 +02:00
Sam Brannen 762d903aad Convert TableMetaData to a record
This simplifies the code and also improves diagnostics while debugging.
2023-09-08 14:04:47 +02:00
Sam Brannen 47d760845b Add missing @Nullable declaration 2023-09-08 14:00:52 +02:00
Sam Brannen ab5d46411a Introduce identifierNameToUse() in GenericCallMetaDataProvider 2023-09-08 13:59:46 +02:00
Sam Brannen 4df3eb4670 Polish Javadoc 2023-09-08 13:59:10 +02:00
Sam Brannen 5a87f555f8 Update copyright headers 2023-09-08 13:57:41 +02:00
Sébastien Deleuze 5fd356e44f Remove outdated @Suppress("DEPRECATION") annotations
See gh-31127
2023-09-08 13:18:16 +02:00
Sébastien Deleuze 6f38e90048 Merge branch '6.0.x' 2023-09-08 13:08:14 +02:00
Sébastien Deleuze 12a01a680b Document some non-nullable Kotlin extensions can throw NoSuchElementException
Closes gh-31189
2023-09-08 13:07:58 +02:00
rstoyanchev b0d4931d5d Merge branch '6.0.x' 2023-09-08 10:07:35 +01:00
rstoyanchev 740f3b797f Polishing
See gh-31185
2023-09-08 10:07:21 +01:00
Sébastien Deleuze 4c621826bd Merge branch '6.0.x' 2023-09-08 10:51:36 +02:00
Sébastien Deleuze ab48b88f91 Refine BeanValidationBeanRegistrationAotProcessor logging
This commit prints a log message at debug level without
a stacktrace for TypeNotPresentException and uses
warn level instead of error level for other exceptions
since the processing of such bean will just be skipped.

Closes gh-31147
2023-09-08 10:50:57 +02:00
rstoyanchev e0c4347cc6 Merge branch '6.0.x' 2023-09-08 09:18:24 +01:00
rstoyanchev eda35e8074 Add note to the interceptor section of the MVC config
Closes gh-31185
2023-09-08 09:17:59 +01:00
rstoyanchev 53133d949d Polishing contribution
Closes gh-29509
2023-09-08 08:28:26 +01:00
tianshuang a1ce5dac0b Execute preflight checks before interceptor chain
See gh-29509
2023-09-08 08:28:26 +01:00
Sébastien Deleuze da7ad71b7f Refine ReactorResourceFactory Javadoc
Provides more details about stop/restart
scenario.

See gh-31178
2023-09-08 09:12:35 +02:00
Yanming Zhou 94a49c4ed3 Log warning if ResponseStatus 'reason' is set and handler returns value
When a handler method is annotated with `@ResponseStatus(reason="...")`,
Spring MVC will use `HttpServletResponse#sendError` to complete the
response. As a result, the Servlet container will send an HTML error
page and any existing data in the response buffer will be cleared.

This commit clarifies the `@ResponseStatus` Javadoc and ensures that a
message is logged at the WARN level if a handler method is annotated
like this and still returns a non-Void value. In this case, the return
value will be ignored and developers should be aware of this fact.

See gh-31113
Closes gh-31121
2023-09-07 19:00:26 +02:00
Brian Clozel bc6954255b Merge branch '6.0.x' 2023-09-07 17:28:08 +02:00
Brian Clozel e4887f3ed9 Upgrade Ubuntu in CI image
Upgrade to ubuntu:jammy-20230816
2023-09-07 17:27:41 +02:00
Sam Brannen c3a0022c9e Polish DefaultClientResponseTests and suppress "unchecked" warnings 2023-09-07 17:09:31 +02:00
Brian Clozel b02e1bb935 Update CI pipeline for api docs publication
See gh-31049
2023-09-07 17:00:20 +02:00
Sam Brannen ac3a466607 Merge branch '6.0.x' 2023-09-07 16:50:50 +02:00
Sam Brannen 1cdbd68aec Revise FilePatternResourceHintsRegistrar API and improve documentation
This commit revises the FilePatternResourceHintsRegistrar API and
introduces List<String> overrides of various var-args methods used with
the new builder API.

Closes gh-29161
2023-09-07 16:45:50 +02:00
Sam Brannen 453c0e5191 Backport changes from main 2023-09-07 16:45:50 +02:00
rstoyanchev fefbeeeb18 Merge branch '6.0.x' 2023-09-07 15:27:56 +01:00
rstoyanchev a6b567a630 Polishing 2023-09-07 15:27:40 +01:00
rstoyanchev 7a516170ef WebClientResponseException supports decoding empty content
Closes gh-31179
2023-09-07 15:27:40 +01:00
Brian Clozel 244c069ea8 Polish
See gh-31173
2023-09-07 16:07:52 +02:00
Brian Clozel 3686c457bb Polish Aggregate Javadoc task
Closes gh-31173
2023-09-07 15:29:25 +02:00
Arjen Poutsma 7b5effecf3 Reference documentation for RestClient
In addition to providing reference documentation for the `RestClient`,
this commit also shortens the `RestTemplate` section.

Closes gh-30826
2023-09-07 14:28:56 +02:00
Sam Brannen e42902b742 Stop referring to JDO and outdated JDBC versions in documentation
Closes gh-31183
2023-09-07 13:26:38 +02:00
Sam Brannen 05790e36db Polish StandardTypeLocatorTests 2023-09-07 13:26:38 +02:00
Sébastien Deleuze 578fdbe97a Merge branch '6.0.x' 2023-09-07 13:19:32 +02:00
shin-mallang 249f6f2da5 Polish resolveArgument method in RequestResponseBodyMethodProcessor
Closes gh-31175
2023-09-07 13:09:40 +02:00
Sébastien Deleuze ada76bd7bf Add an assertion to AopUtils.KotlinDelegate#invokeSuspendingFunction
See gh-22462
2023-09-07 12:30:47 +02:00
Sébastien Deleuze b0aa004d9d Propagate CoroutineContext in CoWebFilter
This provides an elegant and dynamic way to customize the
CoroutineContext in WebFlux with the annotation programming
model.

Closes gh-27522
2023-09-07 12:08:12 +02:00
Sébastien Deleuze 9d768a89d2 Make ReactorClientHttpConnector lifecycle-aware
With this commit, ReactorClientHttpConnector now implements
SmartLifecycle which optionally allows recreating the HttpClient
after ReactorResourceFactory has been updated.

Closes gh-31180
2023-09-06 17:48:22 +02:00
Sébastien Deleuze ab2ad746b5 Polish ReactorResourceFactoryTests
See gh-31178
2023-09-06 16:01:06 +02:00
Sébastien Deleuze 125b8e7418 Make ReactorResourceFactory lifecycle-aware
With this commit, ReactorResourceFactory now implements
Lifecycle which allows supporting JVM Checkpoint Restore
in Spring Boot with Reactor Netty server, and helps
to support Reactor Netty client as well.

Closes gh-31178
2023-09-06 14:14:07 +02:00
Sébastien Deleuze 2a916a3869 Polish ReactorResourceFactoryTests 2023-09-06 14:14:07 +02:00
rstoyanchev 2bc93710f3 Reactive support in MethodValidationInterceptor
Closes gh-20781
2023-09-06 12:54:06 +01:00
rstoyanchev b110a39e88 Polishing MethodValidator contract 2023-09-06 12:54:06 +01:00
Sam Brannen 734d113b11 Ensure configuration methods in SimpleJdbcInsert support method chaining
Prior to this commit, the withoutTableColumnMetaDataAccess() and
includeSynonymsForTableColumnMetaData() methods in SimpleJdbcInsert
incorrectly declared a SimpleJdbcInsertOperations return type, which
prevented method chaining when the instance was declared to be of type
SimpleJdbcInsert.

This commit changes the return types of those methods to
SimpleJdbcInsert to benefit from covariant return types like the rest
of the configuration methods in SimpleJdbcInsert.

Closes gh-31177
2023-09-06 11:37:50 +02:00
Sam Brannen 0a7166234d Polishing 2023-09-06 11:37:50 +02:00
Sam Brannen 552e7fb1d5 Test another scenario 2023-09-06 11:10:44 +02:00
Johnny Lim 884975e094 Polish JMS observation instrumentation
See gh-30335
Closes gh-31172
2023-09-05 17:18:02 +02:00
Sébastien Deleuze adb73389a8 Merge branch '6.0.x' 2023-09-05 16:32:15 +02:00
Johnny Lim 73766c01e6 Add Javadoc since tags in FilePatternResourceHintsRegistrar
See gh-29161
Closes gh-31174
2023-09-05 16:31:46 +02:00
Sam Brannen 7dc0653f38 Revise quoted identifier support in SimpleJdbcInsert
Prior to this commit and the previous commit, SimpleJdbcInsert did not
provide built-in support for "quoted identifiers". Consequently, if any
column names conflicted with keywords or functions from the underlying
database, you had to manually quote the column names when specifying
them via `usingColumns(...)`, and there was unfortunately no way to
quote schema and table names.

The previous commit provided rudimentary support for quoted SQL
identifiers (schema, table, and column names) by querying
java.sql.DatabaseMetaData.getIdentifierQuoteString() to determine the
quote string. It also introduced `usingEscaping(boolean)` in
`SimpleJdbcInsertOperations` to enable the feature. However, it
incorrectly quoted the schema and table names together, and it did not
take into account the fact that a quoted identifier should respect the
casing (uppercase vs. lowercase) of the underlying database's metadata.

This commit revises quoted identifier support in `SimpleJdbcInsert` by:

- renaming `usingEscaping(boolean)` to `usingQuotedIdentifiers()`

- quoting schema and table names separately

- respecting the casing (uppercase vs. lowercase) of the underlying
  database's metadata when quoting identifiers

- introducing integration tests against an in-memory H2 database

See gh-13874
Closes gh-24013
2023-09-05 13:29:40 +02:00
Kita, Maksim d39034754f Support quoted identifiers in SimpleJdbcInsert
See gh-24013
2023-09-05 13:29:40 +02:00
Sam Brannen 070590cb11 Introduce TableMetaDataProvider.columnNameToUse(String) 2023-09-05 13:29:40 +02:00
Sam Brannen 4c45f37166 Polish simple JDBC support classes 2023-09-05 11:36:48 +02:00
Sam Brannen fad70aa252 Update copyright headers 2023-09-04 14:30:44 +02:00
rstoyanchev 0c714e3a78 Fix documentation syntax issue
See gh-16917
2023-09-04 13:25:19 +01:00
rstoyanchev b068742ec8 Support method validation for Lists in WebMvc and WebFlux
Closes gh-31120
2023-09-04 13:22:09 +01:00
Arjen Poutsma 6597727c86 Upgrade to Jetty 12
This commit upgrades Spring Framework to Jetty 12.0.1, and Reactive HTTP
 Client 4.0.0.

Closes gh-30698
2023-09-04 14:03:29 +02:00
Sam Brannen 210b42b7d8 Polishing 2023-09-04 12:42:16 +02:00
Brian Clozel 5fb567a37e Fix missing URI template from client observations in ResTemplateAdapter
Prior to this commit, the `RestTemplateAdapter` would manually expand
templated URIs. This means that the `RestTemplate` instance itself would
never see the templated URIs and could not record it in the client
observations at runtime.

This commit ensures that when URI templates are available, the adapter
uses the correct `exchange` method variant.

Fixes gh-31144
2023-09-04 11:45:35 +02:00
Sam Brannen e8fd29091c Register hints for @TestPropertySource factory
This commit updates MergedContextConfigurationRuntimeHints so that it
registers hints for a custom PropertySourceFactory.

Closes gh-31160
2023-09-03 16:59:58 +02:00
Sam Brannen 7882d265c6 Polishing 2023-09-03 16:59:58 +02:00
Juergen Hoeller 759e3d4aa6 Adapt to PreparedStatementCreator for JdbcClient update operation
See gh-31122
2023-09-03 02:32:01 +02:00
Juergen Hoeller 9b50e7ded6 Merge branch '6.0.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
2023-09-03 01:27:18 +02:00
Juergen Hoeller 278f228688 Upgrade to Groovy 4.0.14, Tomcat 10.1.13, Jetty 11.0.16, Netty 4.1.97, Undertow 2.3.8, Mockito 5.5 2023-09-03 01:25:47 +02:00
Juergen Hoeller c0c4298048 Polishing 2023-09-03 01:14:55 +02:00
Juergen Hoeller 61f89a1f04 Refine note on listener container setup with CachingConnectionFactory
Closes gh-25503
2023-09-03 01:13:51 +02:00
Juergen Hoeller 855fe39b7f Use PreparedStatementCreator for query/update with indexed params
Closes gh-31122
2023-09-03 00:44:11 +02:00
Juergen Hoeller 7595465c21 Lazily obtain Validator from original Supplier
Closes gh-31137
2023-09-03 00:42:52 +02:00
Juergen Hoeller d6e167d16e Raise log level to warn when enhancement cannot apply
Closes gh-31102
2023-09-03 00:42:38 +02:00
Sam Brannen 23a0903b5c Add missing comma and polishing 2023-09-02 19:34:20 +02:00
Sam Brannen a96aeb69c1 Merge branch '6.0.x' 2023-09-02 19:08:36 +02:00
Sam Brannen 3e3f05109f Polishing 2023-09-02 19:06:10 +02:00
Sam Brannen 2d1d14b145 Add /framework-*/build to .gitignore
Due to the introduction of the `framework-api` project in the main branch,
we now have 3 `framework-*` projects that should be ignored. I have
therefore removed `/framework-bom/build` and `/framework-docs/build` and
added `/framework-*/build` to ignore all 3 framework projects.

See gh-31049
2023-09-02 18:28:24 +02:00
Sébastien Deleuze 03650e7d58 Merge branch '6.0.x' 2023-09-01 12:52:59 +02:00
Sébastien Deleuze 1641cb75e2 Refine Reactor field precomputing on native
This commit refines Reactor field precomputing on native
to only compute at build-time fields in the reactor.core
package, since doing so in reactor.netty has unwanted side
effects like Epoll always disabled.

Closes gh-31141
2023-09-01 12:52:27 +02:00
Sébastien Deleuze 0aa4dc11f1 Add missing graal-sdk dependency to spring-orm
See gh-29549
2023-09-01 12:47:47 +02:00
Sébastien Deleuze 81607238ce Use consistently @since 6.1 2023-09-01 12:33:21 +02:00
Sébastien Deleuze 63a20be502 Optimize Hibernate native footprint by making ByteBuddy unreachable
As a workaround before a proper solution the Spring team is trying to
find with the Hibernate team in a future version of Hibernate, this
commit introduces 2 GraalVM substitutions that should allow to remove
ByteBuddy reachability with Hibernate 6.3.

Closes gh-29549
2023-09-01 12:29:16 +02:00
Marten Deinum acd34df0d5 Fix WebFlux blocking configuration documentation
BlockingExecutionConfigurer#setExecutor takes an AsyncTaskExecutor
not an Executor as the documentation states. With this commit,
this has been corrected.

Closes gh-31150
2023-09-01 10:29:47 +02:00
Sam Brannen 093d6a1bec Merge branch '6.0.x' 2023-08-31 13:40:31 +02:00
Sam Brannen c01e1b8901 Document purpose of the name attribute in @PropertySource
Closes gh-30195
2023-08-31 13:39:22 +02:00
Sam Brannen 2e4e43b5bd Polish org.springframework.core.env.PropertySource
See gh-30195
2023-08-31 13:38:13 +02:00
Anton-Vasilev 1ee18e74fc Fix typo in RestClient Javadoc
Closes gh-31145
2023-08-31 09:43:06 +02:00
Brian Clozel 0d7c9b7c93 Attempt to reset Servlet response in DispatcherServlet
This is a follow-up change related to gh-31104.
This change reverts the changes previously made in
`ExceptionHandlerExceptionResolver` and instead attempts to reset the
response directly in `DispatcherServlet` in order to cover all types or
exception handling.

Unlike the previous change, we decided to continue even if the response
was already committed: exception handlers will have a chance to be
called, even if it means they'll have to operate on a garbled response.
This change will cause less disruption, in case existing exception
handlers were relying on this behavior.

See gh-31104
2023-08-30 19:41:46 +02:00
rstoyanchev 32f128b6ba Add create static factory method to WebClientAdapter
Closes gh-31120
2023-08-30 16:37:28 +01:00
Alec Musasa dc7179c528 Fix typo in reference documentation intro
Closes gh-31135
2023-08-30 14:39:42 +02:00
Brian Clozel da1d00be7a Fix dependency management in framework-docs module
See gh-31049
2023-08-30 13:19:11 +02:00
Brian Clozel c93ae250f9 Stop publishing distribution zip artifact
Prior to this commit, the Spring Framework build would publish several
zip artifacts:

* a "*-schema.zip" containing all the XSD schemas produced
* a "*-docs.zip" containing the API docs
* a "*-dist.zip" containing all of the above, plus module jars

Since the reference docs are now produced by Antora in a separate
process, the "*-docs.zip" does not contain the reference docs anymore.
But it still contains the API docs which are automatically fetched from
the artifact repository and published on the docs.spring.io website.

This commit intends to update the current arrangement and optimize the
build.

First, the "*-dist.zip" is not published anymore, since it cannot be
consumed anyway by the community: repo.spring.io does not distribute
release artifacts publicly, developers are expected to get them from
Maven Central. This arrangement is quite dated anyway and is not really
useful in current application build setups.

The generation of API docs is moved to a new "framework-api" module,
separating it from the reference docs module ("framework-docs") which
contains Java, Kotlin and Asciidoctor sources. This removes the custom
javadoc aggregation task and instead uses a dedicated Gradle plugin.

This change also adds a new `-PskipDocs` Gradle project property that
skips entirely the documentation tasks (javadoc, kdocs) as well as the
"distrbution" tasks managed in the framework-api module.
This allows developers to publish locally a SNAPSHOT of Spring Framework
without creating the entire documentation distribution. This is
particularly useful for local testing.

For example, `$ ./gradlew pTML -PskipDocs`.

Closes gh-31049
2023-08-30 12:15:23 +02:00
Brian Clozel 9133e61687 Polish
See gh-31104
2023-08-29 16:55:38 +02:00
lihan 1d7cbfa415 Attempt to reset Servlet response before calling ExceptionHandlers
Prior to this commit, the `ExceptionHandlerExceptionResolver` would
resolve exceptions and handle them by writing to the HTTP response body,
even if the request was already partially handled and content was
written to the response body.

This could result in HTTP responses with some content for the intended
application response, then other content for the handled exception.
This would happen especially when the error would be raised while
writing to the response (for example when serializing content).

This commit attempts to reset the HTTP response before handling the
exception. This effectively resets the response buffer for the body as
well as response headers. If the response is already committed, the
Servlet container raises an exception and the exception handling is
skipped altogether in order to avoid garbled responses.

Closes gh-31104
2023-08-29 16:50:38 +02:00
Anna Buyevich 376a8989f5 Add more tests to DefaultClientRequestObservationConvention
Closes gh-31125
2023-08-29 14:09:46 +02:00
Sébastien Deleuze 38392233ba Add context function to CoRouterFunctionDsl
This new function allows to customize the CoroutineContext
potentially dynamically based on the incoming
ServerRequest.

Closes gh-27010
2023-08-29 12:59:35 +02:00
Brian Clozel 64ff37f42c Update JDK21 release candidate download URL 2023-08-29 11:28:47 +02:00
Brian Clozel f5a356c9c6 Add ContextPropagatingTaskDecorator
Prior to this commit, `@Async` and `@EventListener` annotated methods
would lose the the logging and observation contexts whenever their
execution was scheduled on a different Thread.

The Context Propagation library supports this use case and can propagate
context values in ThreadLocals, Reactor Context and more.

This commit introduces a new `TaskDecorator` implementation that
leverages the Context Propagation library. When configured on a
`TaskExecutor`, this allows to properly propagate context value through
the execution of the task.

This implementation is completely optional and requires the
"io.micrometer:context-propagation" library on the classpath. Enabling
this feature must be done consciously and sometimes selectively, as
context propagation introduces some overhead.

Closes gh-31130
2023-08-29 11:21:47 +02:00
Sébastien Deleuze d47c7f9552 Propagate CoroutineContext in coRouter filters
Closes gh-26977
2023-08-29 10:40:32 +02:00
Sébastien Deleuze bcf11e8919 Replace Reactive awaitSingle() usages by the Mono variant
Closes gh-31127
2023-08-29 09:49:44 +02:00
Sam Brannen af03fa7657 Reinstate support for javax.* annotations in component indexer
- for consistency with the changes made in e1826d2322

See gh-31090
2023-08-28 18:22:21 +02:00
Sam Brannen bfd918d16c Deprecate convention-based @Component stereotype names in favor of @AliasFor
When use of the deprecated feature is detected, a WARNING log message
will be generated analogous to the following.

WARN o.s.c.a.AnnotationBeanNameGenerator - Support for convention-based
stereotype names is deprecated and will be removed in a future version
of the framework. Please annotate the 'value' attribute in
@org.springframework.context.annotation.AnnotationBeanNameGeneratorTests$ConventionBasedComponent1
with @AliasFor(annotation=Component.class) to declare an explicit alias
for @Component's 'value' attribute.

See gh-31089
Closes gh-31093
2023-08-28 18:02:15 +02:00
Stephane Nicoll 2d377155ab Merge pull request #26725 from Jinhui-Z
* pr/26725:
  Polish "Introduce reverse on ClassFilter and MethodFilter"
  Introduce reverse on ClassFilter and MethodFilter

Closes gh-26725
2023-08-28 15:07:10 +02:00
Stephane Nicoll 1f6fd16dae Polish "Introduce reverse on ClassFilter and MethodFilter"
See gh-26725
2023-08-28 15:05:27 +02:00
Jinhui-Z 13e62d0b8e Introduce reverse on ClassFilter and MethodFilter
See gh-26725
2023-08-28 15:05:27 +02:00
Sam Brannen c91841883c Upgrade to Checkstyle 10.12.3 2023-08-28 14:52:49 +02:00
Sam Brannen 9e4b95ef3c Upgrade to spring-javaformat-checkstyle 0.0.39 2023-08-28 14:50:28 +02:00
Sam Brannen 9b44413f2d Merge branch '6.0.x' 2023-08-28 14:48:45 +02:00
Sam Brannen 6876c284f4 Upgrade to Checkstyle 10.12.3 2023-08-28 14:43:40 +02:00
Sam Brannen b167152108 Upgrade to spring-javaformat-checkstyle 0.0.39 2023-08-28 14:43:05 +02:00
Arjen Poutsma 76c032cc11 Schedule blocking ResourceHttpMessageWriter operations on bounded elastic
This commit schedules blocking I/O operations on the bounded elastic
scheduler, which includes retrieving the content length and writing
the resource (region).

Closes gh-30928
2023-08-28 12:54:52 +02:00
Sébastien Deleuze 3ccbe3d1cb Refine documentation contribution
Closes gh-28758
2023-08-28 12:14:35 +02:00
Nheyll 411b355f2c Document buffering with a WebClient filter
See gh-28758
2023-08-28 12:14:28 +02:00
Sébastien Deleuze 499f57ebc5 Fix formatting errors 2023-08-28 10:12:45 +02:00
Sébastien Deleuze 349674ef5e Adapt tests for Jackson ParameterNamesModule
Closes gh-27511
2023-08-28 09:39:53 +02:00
Sam Kruglov 2f43f77dd1 Add ParameterNamesModule to "well known" jackson modules
See gh-27511
2023-08-28 09:36:36 +02:00
Sam Brannen f054c2e804 Polishing 2023-08-27 19:29:21 +02:00
Sam Brannen 95453a4427 Merge branch '6.0.x' 2023-08-27 19:03:16 +02:00
Sam Brannen bbf73848b5 Update warning for use of convention-based annotation attribute overrides
See gh-28761
2023-08-27 19:02:57 +02:00
Sam Brannen 4e2d9252e5 Allow component name to be specified in @[Rest]ControllerAdvice
This commit builds on the recently added support for using @AliasFor to
override the `value` attribute in `@Component, and allows a custom
component name to be specified in both @ControllerAdvice and
@RestControllerAdvice via new `name` attributes.

See gh-31089
Closes gh-21108
2023-08-27 18:06:08 +02:00
Stephane Nicoll e239753a1b Merge branch '6.0.x' 2023-08-27 18:03:59 +02:00
Stephane Nicoll 1af259f928 Merge pull request #29753 from perlun
* pr/29753:
  Polish "Make sure NoUniqueBeanDefinitionException to be serializable"
  Make sure NoUniqueBeanDefinitionException to be serializable

Closes gh-29753
2023-08-27 18:03:44 +02:00
Stephane Nicoll 1396daa4b6 Polish "Make sure NoUniqueBeanDefinitionException to be serializable"
See gh-29753
2023-08-27 17:59:27 +02:00
Per Lundberg 1b409d5290 Make sure NoUniqueBeanDefinitionException to be serializable
See gh-29753
2023-08-27 17:56:58 +02:00
Sam Brannen ff104b6de0 Look up @Component stereotype names using @AliasFor semantics
Although gh-20615 introduced the use of @AliasFor for @Component(value) in the built-in
stereotype annotations (@Service, @Controller, @Repository, @Configuration, and
@RestController), prior to this commit the framework did not actually rely on @AliasFor
support when looking up a component name via stereotype annotations. Rather, the
framework had custom annotation parsing logic in
AnnotationBeanNameGenerator#determineBeanNameFromAnnotation() which effectively ignored
explicit annotation attribute overrides configured via @AliasFor.

This commit revises AnnotationBeanNameGenerator#determineBeanNameFromAnnotation() so that
it first looks up @Component stereotype names using @AliasFor semantics before falling
back to the "convention-based" component name lookup strategy.

Consequently, the name of the annotation attribute that is used to specify the bean name
is no longer required to be `value`, and custom stereotype annotations can now declare an
attribute with a different name (such as `name`) and annotate that attribute with
`@AliasFor(annotation = Component.class, attribute = "value")`.

Closes gh-31089
2023-08-27 17:17:52 +02:00
Sam Brannen d189e169cc Polish CompositePropertySource[Tests] 2023-08-27 14:08:39 +02:00
Stephane Nicoll 7c508a4cd3 Merge pull request #27670 from asgh
* pr/27670:
  Use Arrays.deepToString for toString in SimpleKey

Closes gh-27670
2023-08-26 18:14:35 +02:00
asgh 9d7bd9520c Use Arrays.deepToString for toString in SimpleKey
See gh-27670
2023-08-26 18:10:42 +02:00
Stephane Nicoll ce4a5b1f06 Merge pull request #27236 from Shawyeok
* pr/27236:
  Polish "Improve performance of CompositePropertySource#getPropertyNames"
  Improve performance of CompositePropertySource#getPropertyNames

Closes gh-27236
2023-08-26 17:49:32 +02:00
Stephane Nicoll 5c691960a2 Polish "Improve performance of CompositePropertySource#getPropertyNames"
See gh-27236
2023-08-26 17:46:19 +02:00
shawyeok b67a381fbe Improve performance of CompositePropertySource#getPropertyNames
Create LinkedHashSet with a initialCapacity, prevent under the hood
table resize cost in continuous add operations. Reduce bootstrap time
in the case of large properties.

See gh-27236
2023-08-26 17:46:19 +02:00
Sam Brannen e1826d2322 Reinstate support for @javax.annotation.ManagedBean & @javax.inject.Named
This commit reinstates support for the legacy JSR-250
@javax.annotation.ManagedBean and JSR-330 @javax.inject.Named
annotations with regard to component name lookups and component
scanning.

Closes gh-31090
2023-08-26 17:16:00 +02:00
Sam Brannen aaa0a2be63 Test status quo for @Components with multiple declared names 2023-08-26 17:15:47 +02:00
Sam Brannen 71ba7bc5e0 Polishing 2023-08-26 17:15:39 +02:00
Stephane Nicoll e18f1f5d9c Merge pull request #27154 from Li0n13
* pr/27154:
  Polish "Avoid calling executeBatch() with an empty batch"
  Avoid calling executeBatch() with an empty batch

Closes gh-27154
2023-08-26 17:09:39 +02:00
Stephane Nicoll f9cffcce05 Polish "Avoid calling executeBatch() with an empty batch"
See gh-27154
2023-08-26 17:05:39 +02:00
Li0n13 2d7bf83d8d Avoid calling executeBatch() with an empty batch
See gh-27154
2023-08-26 17:05:20 +02:00
Stephane Nicoll a6b0c75cae Merge branch '6.0.x' 2023-08-26 16:41:21 +02:00
Stephane Nicoll ca14202d78 Merge pull request #27115 from gnagy
* pr/27115:
  Update copyright of changed file
  Allow null attribute value in Model.set()

Closes gh-27115
2023-08-26 16:41:05 +02:00
Stephane Nicoll 7231f22c23 Update copyright of changed file
See gh-27115
2023-08-26 16:39:25 +02:00
Gergely Nagy 3470240ef0 Allow null attribute value in Model.set()
See gh-27115
2023-08-26 16:38:19 +02:00
Sam Brannen e0c3b1ae1d Merge branch '6.0.x' 2023-08-26 15:28:50 +02:00
Sam Brannen 7598bca799 Revise Checkstyle rules to prohibit use of assertions other than AssertJ
Closes gh-31116
2023-08-26 15:28:25 +02:00
Sam Brannen f9588de247 Reinstate FailingBeforeAndAfterMethodsTestNGTests
The tests were ignored due to "Fails against TestNG 6.11"; however,
these tests pass against the current version of TestNG that we build
against (7.8.0).
2023-08-26 15:22:38 +02:00
Sam Brannen dac481da43 Test CollectionUtils.unmodifiableMultiValueMap only once
No need to test that feature as a parameterized test.
2023-08-26 14:56:17 +02:00
Sam Brannen 31a07e6fbf User AssertJ assertions 2023-08-26 14:56:16 +02:00
Sam Brannen ef01a078d3 Polishing 2023-08-26 14:55:15 +02:00
Sam Brannen 44167ecea4 Polish BackOff support 2023-08-26 14:44:46 +02:00
Stephane Nicoll 962f4d20b4 Merge pull request #27071 from garyrussell
* pr/27071:
  Polish "Add maxAttempts to ExponentialBackOff"
  Add maxAttempts to ExponentialBackOff

Closes gh-27071
2023-08-26 12:55:10 +02:00
Stephane Nicoll 609580bfb9 Polish "Add maxAttempts to ExponentialBackOff"
See gh-27071
2023-08-26 12:54:24 +02:00
Gary Russell f6a09f3fad Add maxAttempts to ExponentialBackOff
If you wish to stop after a certain number of attempts with an
`ExponentialBackOff` you have to calculate the `maxElapsedTime`
corresponding to the number of attempts.

Add a new property to make it more convenient to stop after a
certain number of attempts.

See gh-27071
2023-08-26 12:45:32 +02:00
Stephane Nicoll 48878619d2 Merge branch '6.0.x' 2023-08-26 10:18:04 +02:00
Stephane Nicoll 2b3539a6de Merge pull request #26761 from 1zg12
* pr/26761:
  Polish "Restore customization of PropertyResolver"
  Restore customization of PropertyResolver

Closes gh-26761
2023-08-26 10:17:45 +02:00
Stephane Nicoll 2731d4f100 Polish "Restore customization of PropertyResolver"
See gh-26761
2023-08-26 10:17:02 +02:00
lwpro2 00fffb7ab0 Restore customization of PropertyResolver
This commit reintroduces the ability to customize the PropertyResolver
to use in PropertySourcesPropertyResolver

See gh-26761
2023-08-26 10:09:42 +02:00
Stephane Nicoll 16cb296b35 Merge pull request #27335 from marschall
* pr/27335:
  Optimize for single TransactionSynchronization

Closes gh-27335
2023-08-26 09:56:47 +02:00
Philippe Marschall fd18c00e50 Optimize for single TransactionSynchronization
Optimize TransactionSynchronizationManager.getSynchronizations() to
avoid sorting and ArrayList creation in case of a single
TransactionSynchronization.

See gh-27335
2023-08-26 09:52:17 +02:00
Sam Brannen e737e6d9ba Update copyright headers 2023-08-25 17:07:17 +02:00
Sam Brannen 78d8fac05b Polishing 2023-08-25 17:06:57 +02:00
Sam Brannen 3efbbc5994 Merge branch '6.0.x' 2023-08-25 16:56:52 +02:00
Sam Brannen 89b7a6bf47 Skip searching of nonexistent directory in PathMatchingResourcePatternResolver
Prior to this commit, when PathMatchingResourcePatternResolver
processed a `file:` pattern (for example, `file:/app-config/**`) for a
`rootPath` that did not exist in the filesystem, the resolver attempted
to search the directory and logged a WARNING message similar to the
following when it failed to do so.

Failed to search in directory [/app-config/] for files matching pattern
[**]: java.nio.file.NoSuchFileException: /app-config/

To avoid unnecessary attempts to search a nonexistent directory,
PathMatchingResourcePatternResolver now skips searching of a nonexistent
directory and preemptively logs an INFO message similar to the
following.

Skipping search for files matching pattern [**]: directory [/app-config]
does not exist

Closes gh-31111
2023-08-25 16:54:10 +02:00
Sam Brannen 19570338c9 Ensure doFindPathMatchingFileResources() returns a mutable Set
This commit ensures that PathMatchingResourcePatternResolver's
doFindPathMatchingFileResources() method returns a mutable Set in order
to comply with the documented contract.
2023-08-25 16:53:00 +02:00
Brian Clozel fe2ef2ea6e Upgrade Java versions in CI build 2023-08-25 16:25:24 +02:00
Brian Clozel 35fc2df948 Instrument RestClient for Observability
This commit instruments the new `RestClient` HTTP client for
observability. Since this client is sharing its HTTP infrastructure with
`RestTemplate` and operates on the same request/response types, this
instrumentation reuses the Observation convention and context.
This choice makes sense since one can build a new `RestClient` instance
using a `RestTemplate` instance, effectively reusing the underlying
configuration.

Closes gh-31114
2023-08-25 16:23:04 +02:00
Stephane Nicoll 22fd6df711 Merge pull request #26028 from hzmpay
* pr/26028:
  Update copyright header of changed file
  Use computeIfAbsent in SpelCompiler and AdvisedSupport

Closes gh-26028
2023-08-25 16:17:49 +02:00
Stephane Nicoll 8432f777aa Update copyright header of changed file
See gh-26028
2023-08-25 16:13:27 +02:00
hzmpay cde476f90e Use computeIfAbsent in SpelCompiler and AdvisedSupport
See gh-26028
2023-08-25 16:12:08 +02:00
Stephane Nicoll 178cb429a8 Merge pull request #25478 from wind57
* pr/25478:
  Polish "Use Comparable instead of dedicated implementations"
  Use Comparable instead of dedicated implementations

Closes gh-25478
2023-08-25 14:47:53 +02:00
Stephane Nicoll 49cafe07ed Polish "Use Comparable instead of dedicated implementations"
See gh-25478
2023-08-25 14:44:57 +02:00
Eugene 33454a4007 Use Comparable instead of dedicated implementations
This commit deprecates ComparableComparator and NullSafeComparator in
favor of the available convenient implementation in the JDK.

See gh-25478
2023-08-25 14:41:27 +02:00
Stephane Nicoll d0fc6dd06d Merge pull request #17215 from chenqimiao
* pr/24773:
  Polish "Improve @Autowired method injection on mixed nullability args"
  Improve @Autowired method injection on mixed nullability args

Closes gh-17215
2023-08-25 12:52:40 +02:00
Stephane Nicoll 8efc7a958e Polish "Improve @Autowired method injection on mixed nullability args"
See gh-17215
2023-08-25 12:47:05 +02:00
陈其苗 32c0540424 Improve @Autowired method injection on mixed nullability args
See gh-17215
2023-08-25 12:44:16 +02:00
Sébastien Deleuze c8169e5cad Add Coroutines support to Spring AOP
This commit adds support for Kotlin Coroutines to Spring AOP
by leveraging CoroutinesUtils#invokeSuspendingFunction in
AopUtils#invokeJoinpointUsingReflection to convert it to the
equivalent Publisher return value, like in other parts of Spring
Framework.

That allows method interceptors with Reactive support to process
related return values.

CglibAopProxy#processReturnType and JdkDynamicAopProxy#invoke
take care of the conversion from the Publisher return value
to Kotlin Coroutines.

Reactive transactional and HTTP service interface support
have been refined to leverage those new generic capabilities.

Closes gh-22462
2023-08-25 11:53:18 +02:00
Stephane Nicoll 9b3f4567ee Merge pull request #25160 from midumitrescu
* pr/25160:
  Polish "Add additional tests for MultiValueMap"
  Add additional tests for MultiValueMap

Closes gh-25160
2023-08-25 11:50:10 +02:00
Stephane Nicoll 352c7cd8b3 Polish "Add additional tests for MultiValueMap"
See gh-25160
2023-08-25 11:46:54 +02:00
Mihai Dumitrescu 325edbec7d Add additional tests for MultiValueMap
See gh-25140
See gh-25160
2023-08-25 11:27:52 +02:00
Stephane Nicoll 2a37284c86 Merge pull request #24649 from stsypanov
* pr/24649:
  Polish "Skip non-overridden methods of Object.class"
  Skip non-overridden methods of Object.class

Closes gh-24649
2023-08-24 11:46:00 +02:00
Stephane Nicoll 95c43bb0ae Polish "Skip non-overridden methods of Object.class"
See gh-24649
2023-08-24 11:33:34 +02:00
stsypanov b91179d1b8 Skip non-overridden methods of Object.class
See gh-24649
2023-08-24 11:18:49 +02:00
Sébastien Deleuze 21613eabf1 Properly use Reactor Netty 2 in AbstractHttpHandlerIntegrationTests
Closes gh-31095
2023-08-24 10:46:43 +02:00
Sébastien Deleuze c564f27647 Upgrade to Kotlin Coroutines 1.7.3
Closes gh-31108
2023-08-24 09:17:22 +02:00
Sébastien Deleuze cf0a48692c Upgrade to Kotlin Serialization 1.6.0
Closes gh-31107
2023-08-24 09:17:22 +02:00
Sébastien Deleuze 1f437add0b Upgrade to Kotlin 1.9.10
Closes gh-31106
2023-08-24 09:17:22 +02:00
Stephane Nicoll 86e02a47fb Polish 2023-08-24 09:04:14 +02:00
Stephane Nicoll c809fda4ed Merge pull request #24633 from chenqimiao
* pr/24633:
  Add a unit test for getMostSpecificMethod of ClassUtils

Closes gh-24633
2023-08-23 20:50:49 +02:00
陈其苗 e7071c329a Add a unit test for getMostSpecificMethod of ClassUtils
See gh-24633
2023-08-23 20:45:02 +02:00
Juergen Hoeller 3c5dc19da3 Polishing 2023-08-23 19:09:46 +02:00
Juergen Hoeller ecc0a6d2db Merge branch '6.0.x' 2023-08-23 19:02:44 +02:00
Stephane Nicoll 5878a0741e Polish "Add factory to create a NamedThreadLocal with an initial value"
See gh-24705
2023-08-23 18:58:12 +02:00
陈其苗 e1d0176faa Add factory to create a NamedThreadLocal with an initial value
See gh-24705
2023-08-23 18:58:12 +02:00
Sébastien Deleuze b2a86cc42d Polishing
See gh-24311
2023-08-23 18:56:14 +02:00
Sébastien Deleuze f161bc798e Implement StringToRegexConverter in Java
This commit implements StringToRegexConverter in Java
in order to avoid circular dependencies between Java
and Kotlin codes that can break IDE support, and for
consistency with the rest of the codebase.

See gh-24311
2023-08-23 18:53:32 +02:00
Juergen Hoeller 906a9f7982 Polishing 2023-08-23 18:52:55 +02:00
Juergen Hoeller 6fed3a0d6b Consistently throw ParseException instead of IllegalStateException
Closes gh-31097
2023-08-23 18:50:52 +02:00
Stephane Nicoll 471e4d2b20 Merge pull request #24311 from valfirst
* pr/24311:
  Polish "Add support for converting String to Pattern"
  Add support for converting String to Pattern

Closes gh-24311
2023-08-23 18:13:54 +02:00
Stephane Nicoll a20a74817e Polish "Add support for converting String to Pattern"
See gh-24311
2023-08-23 18:13:41 +02:00
Valery Yatsynovich 06f6b45248 Add support for converting String to Pattern
See gh-24311
2023-08-23 18:13:41 +02:00
Sébastien Deleuze bb14dfa747 Merge branch '6.0.x' 2023-08-23 18:11:14 +02:00
Sébastien Deleuze 8934eb8464 Optimize ClassUtils#getMostSpecificMethod
This commit optimizes ClassUtils#getMostSpecificMethod which is
a method frequently invoked in typical Spring applications.

It refines ClassUtils#isOverridable by considering static and
final modifiers as non overridable and optimizes its implementation.

Closes gh-30272
2023-08-23 18:07:54 +02:00
Stephane Nicoll 8695fadbc0 Merge pull request #23692 from ttddyy
* pr/23692:
  Polish "Add a composite for TaskDecorator"
  Add a composite for TaskDecorator

Closes gh-23692
2023-08-23 16:05:01 +02:00
Stephane Nicoll 6e141cc23a Polish "Add a composite for TaskDecorator"
See gh-23692
2023-08-23 16:02:54 +02:00
Tadaya Tsuyukubo 5f581a9a68 Add a composite for TaskDecorator
See gh-23692
2023-08-23 16:02:41 +02:00
Stephane Nicoll 8f6d24efde Merge pull request #23914 from chenqimiao
* pr/23914:
  Polish "Rename earlyProxyReferences in AbstractAutoProxyCreator"
  Rename earlyProxyReferences in AbstractAutoProxyCreator

Closes gh-23914
2023-08-23 15:35:38 +02:00
Stephane Nicoll 5d5cd17d33 Polish "Rename earlyProxyReferences in AbstractAutoProxyCreator"
See gh-23914
2023-08-23 15:34:22 +02:00
陈其苗 67e3b1b531 Rename earlyProxyReferences in AbstractAutoProxyCreator
See gh-23914
2023-08-23 15:33:33 +02:00
rstoyanchev 35ba53e918 Unwrap validator if necessary in HandlerMethodValidator
See gh-31082
2023-08-23 14:55:59 +03:00
rstoyanchev 942800e8ec Refactor MethodValidationAdapter constructors
See gh-31082
2023-08-23 14:55:59 +03:00
rstoyanchev ff069de6d7 Expose unwrap method on SmartValidator
See gh-31082
2023-08-23 14:55:59 +03:00
Sébastien Deleuze c6c61d6485 Refine "checkpoint on refresh" error handling
Closes gh-31096
2023-08-23 12:33:13 +02:00
Stephane Nicoll bf2cdcb1f2 Merge branch '6.0.x' 2023-08-23 10:47:32 +02:00
Stephane Nicoll 4b9f89101d Clarify handling of several representations for JOpt options
See gh-22168
2023-08-23 10:46:21 +02:00
Stephane Nicoll 74175c1117 Merge pull request #30709 from kilink
* pr/30709:
  Polish "Get content as String for ContentCachingRequestWrapper"
  Get content as String for ContentCachingRequestWrapper

Closes gh-30709
2023-08-22 19:13:55 +02:00
Stephane Nicoll 4695bd332a Polish "Get content as String for ContentCachingRequestWrapper"
See gh-30709
2023-08-22 19:11:26 +02:00
Patrick Strawderman d9b8826142 Get content as String for ContentCachingRequestWrapper
This commits adds a getContentAsString method to
ContentCachingRequestWrapper that uses the configured charset without
copying the underlying byte array.

See gh-30709
2023-08-22 18:51:39 +02:00
Stephane Nicoll d529eee889 Merge branch '6.0.x' 2023-08-22 17:02:00 +02:00
Stephane Nicoll b204f2e396 Merge pull request #30107 from izeye
* pr/30107:
  Use IllegalStateException in ReactiveTestTransactionManager.doCommit()

Closes gh-30107
2023-08-22 17:01:15 +02:00
Johnny Lim 112f755e17 Use IllegalStateException in ReactiveTestTransactionManager.doCommit()
See gh-30107
2023-08-22 17:00:11 +02:00
Stephane Nicoll 26485b0e7d Merge branch '6.0.x' 2023-08-22 16:57:37 +02:00
Stephane Nicoll 542d0ef0b4 Merge pull request #31091 from aahlenst
* pr/31091:
  Fix invalid type name in RSocket code example

Closes gh-31091
2023-08-22 16:57:21 +02:00
Andreas Ahlenstorf 452b2df849 Fix invalid type name in RSocket code example
See gh-31091
2023-08-22 16:55:59 +02:00
Stephane Nicoll 18813de69f Merge pull request #1822 from x-x-z
* pr/1822:
  Polish "Add Basic Authorization for UrlResource"
  Add Basic Authorization for UrlResource

Closes gh-1822
2023-08-22 16:43:37 +02:00
Stephane Nicoll f95a1f49df Polish "Add Basic Authorization for UrlResource"
See gh-1822
2023-08-22 16:38:00 +02:00
Denis Kostin ac9ca412c8 Add Basic Authorization for UrlResource
See gh-1822
2023-08-22 16:12:31 +02:00
Stephane Nicoll 9c175608e5 Merge pull request #31076 from 70825
* pr/31076:
  Polish "Wrap ternary operator within parentheses"
  Wrap ternary operator within parentheses

Closes gh-31076
2023-08-22 15:55:53 +02:00
Stephane Nicoll 2b76c4d847 Polish "Wrap ternary operator within parentheses"
See gh-31076
2023-08-22 15:40:16 +02:00
70825 6712c044b1 Wrap ternary operator within parentheses
See gh-31076
2023-08-22 15:15:05 +02:00
Sam Brannen a55b50b512 Simplify implementation of AnnotationMetadata.getMetaAnnotationTypes()
Since an annotation cannot be extended in Java, there is no need to use
the INHERITED_ANNOTATIONS SearchStrategy to search for meta-annotations
on an annotation.
2023-08-22 14:58:19 +02:00
Sam Brannen 2935ff8f97 Fix Javadoc for AnnotationMetadata.getMetaAnnotationTypes() 2023-08-22 14:50:58 +02:00
Sam Brannen aedd909ef6 Test status quo for component name lookups for Jakarta annotations 2023-08-22 11:49:08 +02:00
Sam Brannen d8523cb033 Polishing 2023-08-22 11:49:08 +02:00
Sam Brannen 5e171d3cf5 Polish reference documentation for JdbcClient 2023-08-21 16:51:14 +02:00
Sam Brannen 5f893cadc5 Merge branch '6.0.x' 2023-08-21 16:03:52 +02:00
Sam Brannen 229b4782ee Add @Nullable in doSetValue() in Argument[Type]PreparedStatementSetter
This commit adds @Nullable to the argValue parameters in the
doSetValue() methods in ArgumentPreparedStatementSetter and
ArgumentTypePreparedStatementSetter.

Closes gh-31086
2023-08-21 16:01:42 +02:00
Sam Brannen ad1554a631 Polishing 2023-08-21 16:01:22 +02:00
Toshiaki Maki 8f7d61650d Add @Nullable to value in param() methods in JdbcClient
Closes gh-31084
2023-08-21 15:50:38 +02:00
Juergen Hoeller c2bdc23b5e Merge branch '6.0.x' 2023-08-21 15:45:22 +02:00
Juergen Hoeller 8be77cc650 Revise documentation for cache infrastructure setup
Closes gh-28250
2023-08-21 15:42:50 +02:00
Juergen Hoeller 26da0e49e4 Show example for CaffeineCacheManager async cache setup
See gh-28250
2023-08-21 15:39:02 +02:00
Sam Brannen 583d92e69a Merge branch '6.0.x' 2023-08-21 15:19:27 +02:00
Sam Brannen d0d0ed0578 Update copyright headers 2023-08-21 15:18:04 +02:00
Sam Brannen 9911d91f08 Add implementation note
See gh-31083
2023-08-21 15:17:57 +02:00
Sam Brannen 758dddce3b Merge branch '6.0.x' 2023-08-21 14:18:38 +02:00
Sam Brannen 620a87bcbc Polishing 2023-08-21 14:17:05 +02:00
Yanming Zhou 368036cab4 Allow overriding dynamic property from enclosing class in nested test class
Prior to this commit, a dynamic property registered via a
@DynamicPropertySource method in a @Nested test class was not able to
override a property registered via a @DynamicPropertySource method in
the enclosing class.

See gh-26091
Closes gh-31083
2023-08-21 14:03:24 +02:00
Juergen Hoeller 430cc2edc0 Merge branch '6.0.x' 2023-08-21 12:38:43 +02:00
Juergen Hoeller 8a6c0cd221 Polishing 2023-08-21 12:37:58 +02:00
Juergen Hoeller b0fc2fe473 Document destroy method inference more prominently
Closes gh-29546
2023-08-21 12:32:45 +02:00
Juergen Hoeller 2952cb95f5 Document custom SimpleApplicationEventMulticaster setup
Closes gh-29996
2023-08-21 12:32:33 +02:00
Sam Brannen 1e3099759e Polishing 2023-08-20 19:32:07 +02:00
Harry Yang 0e0c298dcf Optimize InlineMap and InlineList in SpEL
- Make InlineList#constant and InlineMap#constant final.

- Add more assertions for InlineMap tests.

Closes gh-30251
2023-08-20 17:52:27 +02:00
Sam Brannen baf367831f Add @AliasFor tip to Javadoc for @TestPropertySource 2023-08-19 15:40:31 +02:00
Sam Brannen 8f71bea553 Avoid unnecessary synchronization in SequencedProperties 2023-08-19 15:32:37 +02:00
Sam Brannen 94d9a71bb5 Polishing 2023-08-19 15:21:55 +02:00
Sébastien Deleuze 11abd8b04f Merge branch '6.0.x' 2023-08-18 17:25:50 +02:00
Sébastien Deleuze c91708c1c0 Add missing proxy hints for Hibernate native query
This commit contributes proxy hints needed by
SharedEntityManagerCreator for
org.hibernate.query.sql.internal.NativeQueryImpl interfaces.

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

Closes gh-29603
2023-08-18 17:22:57 +02:00
Sam Brannen 74130d007b Ensure direct @PropertySource annotations override meta-annotations
Prior to this commit, there was an issue with the semantics of property
source overrides. Specifically, a @PropertySource annotation present as
a meta-annotation on a @Configuration class was registered with higher
precedence than a @PropertySource annotation declared closer to (or
directly on) the @Configuration class. Consequently, there was no way
for a "local" @PropertySource annotation to override properties
registered via @PropertySource as a meta-annotation.

This commit addresses this issue by introducing a new overloaded
getMergedRepeatableAnnotationAttributes() variant in
AnnotatedTypeMetadata that allows the caller to supply a
sortByReversedMetaDistance flag. When set to `true`, the annotation
search results will be sorted in reversed order based on each
annotation's meta distance, which effectively orders meta-annotations
before annotations that are declared directly on the underlying element.

ConfigurationClassParser and AnnotationConfigUtils have been updated to
use this new repeatable annotation search method for @PropertySource.

Closes gh-31074
2023-08-18 16:43:44 +02:00
Sam Brannen 285c92bb03 Store reversedMetaDistance Comparator in static field 2023-08-18 16:33:51 +02:00
Sam Brannen ee6998ba52 Polishing 2023-08-18 16:21:50 +02:00
Stephane Nicoll 9583d18896 Merge branch '6.0.x' 2023-08-18 15:39:49 +02:00
Stephane Nicoll 47b1a2bc55 Clarify usage of FilePatternResourceHintsRegistrar
This commit review the API using a builder to make it more clear what
the registrar does.

Closes gh-29161
2023-08-18 15:35:20 +02:00
Sébastien Deleuze 334b1548b7 Merge branch '6.0.x'
Adapt gh-31045 fix to the main branch, and throw a
WebExchangeBindException instead of a ServerWebInputException.
2023-08-18 15:11:16 +02:00
Sébastien Deleuze e6565c600a Refine type conversion errors in ModelAttributeMethodProcessor
This commit turns TypeMismatchException thrown in
ModelAttributeMethodArgumentResolver#createAttribute into
proper ServerWebInputException in order get HTTP response
with 400 Bad Request status code instead of 500 Internal error.

Closes gh-31045
2023-08-18 14:31:43 +02:00
Sébastien Deleuze 8af9648c43 Polish ModelAttributeMethodArgumentResolverTests 2023-08-18 12:47:44 +02:00
Sam Brannen 3dcac0cf80 Clean up / Suppress warnings 2023-08-18 12:46:17 +02:00
Sam Brannen ca118ca4a0 Introduce overloaded methods in JdbcTestUtils that accept JdbcClient
Closes gh-31066
2023-08-18 12:20:57 +02:00
Sam Brannen e0fb777325 Introduce var-args params() method in JdbcClient's StatementSpec
Closes gh-31070
2023-08-18 12:00:28 +02:00
Sam Brannen 48e94f535c Polish JdbcClient 2023-08-18 12:00:28 +02:00
Sam Brannen 77067d0e6b Revise JdbcTestUtils method signatures to accept JdbcOperations
Closes gh-31065
2023-08-18 12:00:28 +02:00
Juergen Hoeller 1a137c2e61 Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/util/StringUtils.java
2023-08-18 11:27:03 +02:00
Juergen Hoeller c5bdd9d79d Optimize whitespace checks in StringUtils
Closes gh-31067
2023-08-18 11:25:48 +02:00
Sam Brannen f43f1e12f1 Merge branch '6.0.x' 2023-08-17 17:59:30 +02:00
Sam Brannen 9efa99e0d8 Update link to "Method visibility and @Transactional in proxy mode"
See gh-31057
See gh-25582
2023-08-17 17:54:44 +02:00
Sam Brannen 957eb021d7 Upgrade to Gradle 8.3
Closes gh-31061
2023-08-17 17:32:05 +02:00
Arjen Poutsma 34477b4f03 Schedule FreeMarker template lookup on bounded elastic scheduler
This commit makes sure that FreeMarker template lookups, which
potentially block, are scheduled on the bounded elastic scheduler.

Closes gh-30903
2023-08-17 16:42:44 +02: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 Li 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 Bhatt 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
danu 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
4153 changed files with 185329 additions and 112834 deletions
+3
View File
@@ -3,6 +3,8 @@ name: Backport Bot
on:
issues:
types: [labeled]
pull_request:
types: [labeled]
push:
branches:
- '*.x'
@@ -13,6 +15,7 @@ jobs:
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)
+4 -3
View File
@@ -21,15 +21,14 @@ derby.log
/build
buildSrc/build
/spring-*/build
/framework-bom/build
/framework-docs/build
/framework-*/build
/integration-tests/build
/src/asciidoc/build
spring-test/test-output/
# Maven artifacts
pom.xml
target/
/target/
# Eclipse artifacts, including WTP generated manifests
bin
@@ -50,3 +49,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.5-librca
java=17.0.8.1-librca
+6 -6
View File
@@ -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 [framework-docs/src/docs/asciidoc](framework-docs/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 :framework-docs:asciidoctor` and then browse the result under
`framework-docs/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="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-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](framework-docs/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
+39 -93
View File
@@ -1,24 +1,24 @@
plugins {
id 'io.spring.nohttp' version '0.0.10'
id 'io.freefair.aspectj' version '6.5.0.3' apply false
id 'io.freefair.aspectj' version '8.4' apply false
// kotlinVersion is managed in gradle.properties
id 'org.jetbrains.kotlin.plugin.serialization' version "${kotlinVersion}" apply false
id 'org.jetbrains.dokka' version '1.7.20'
id 'org.asciidoctor.jvm.convert' version '3.3.2' apply false
id 'org.asciidoctor.jvm.pdf' version '3.3.2' 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.42.0'
id 'com.github.johnrengelman.shadow' version '7.1.2' apply false
id 'de.undercouch.download' version '5.1.0'
id 'me.champeau.jmh' version '0.6.6' apply false
id 'com.github.ben-manes.versions' version '0.49.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.2' apply false
id 'me.champeau.mrjar' version '0.1.1'
}
ext {
moduleProjects = subprojects.findAll { it.name.startsWith("spring-") }
javaProjects = subprojects - project(":framework-bom") - project(":framework-platform")
javaProjects = subprojects.findAll { !it.name.startsWith("framework-") }
}
configure(allprojects) { project ->
apply plugin: "org.springframework.build.localdev"
group = "org.springframework"
repositories {
mavenCentral()
maven {
@@ -28,7 +28,6 @@ configure(allprojects) { project ->
includeGroup 'io.projectreactor.netty'
}
}
maven { url "https://repo.spring.io/libs-spring-framework-build" }
if (version.contains('-')) {
maven { url "https://repo.spring.io/milestone" }
}
@@ -44,16 +43,7 @@ configure(allprojects) { project ->
}
}
configure([rootProject] + javaProjects) { project ->
group = "org.springframework"
apply plugin: "java"
apply plugin: "java-test-fixtures"
apply plugin: "checkstyle"
apply plugin: 'org.springframework.build.conventions'
apply from: "${rootDir}/gradle/toolchains.gradle"
apply from: "${rootDir}/gradle/ide.gradle"
configure(allprojects - project(":framework-platform")) {
configurations {
dependencyManagement {
canBeConsumed = false
@@ -62,36 +52,19 @@ configure([rootProject] + javaProjects) { project ->
}
matching { it.name.endsWith("Classpath") }.all { it.extendsFrom(dependencyManagement) }
}
test {
useJUnitPlatform()
include(["**/*Tests.class", "**/*Test.class"])
systemProperty("java.awt.headless", "true")
systemProperty("testGroups", project.properties.get("testGroups"))
systemProperty("io.netty.leakDetection.level", "paranoid")
systemProperty("io.netty5.leakDetectionLevel", "paranoid")
systemProperty("io.netty5.leakDetection.targetRecords", "32")
systemProperty("io.netty5.buffer.lifecycleTracingEnabled", "true")
systemProperty("io.netty5.buffer.leakDetectionEnabled", "true")
jvmArgs(["--add-opens=java.base/java.lang=ALL-UNNAMED",
"--add-opens=java.base/java.util=ALL-UNNAMED"])
}
checkstyle {
toolVersion = "10.4"
configDirectory.set(rootProject.file("src/checkstyle"))
}
tasks.named("checkstyleMain").configure {
maxHeapSize = "1g"
}
tasks.named("checkstyleTest").configure {
maxHeapSize = "1g"
}
dependencies {
dependencyManagement(enforcedPlatform(dependencies.project(path: ":framework-platform")))
}
}
configure([rootProject] + javaProjects) { project ->
apply plugin: "java"
apply plugin: "java-test-fixtures"
apply plugin: 'org.springframework.build.conventions'
apply from: "${rootDir}/gradle/toolchains.gradle"
apply from: "${rootDir}/gradle/ide.gradle"
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-api")
testImplementation("org.junit.jupiter:junit-jupiter-params")
testImplementation("org.junit.platform:junit-platform-suite-api")
@@ -105,43 +78,38 @@ 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/",
"https://fasterxml.github.io/jackson-core/javadoc/2.14/",
"https://fasterxml.github.io/jackson-databind/javadoc/2.14/",
"https://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.14/",
"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.9.1/api/ are in named modules.
//
// "https://junit.org/junit5/docs/5.9.1/api/",
// "https://junit.org/junit5/docs/5.10.1/api/",
"https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/",
"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/",
//"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.
"https://www.javadoc.io/doc/com.google.code.findbugs/jsr305/3.0.2/"
// 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[]
}
@@ -151,27 +119,5 @@ configure(moduleProjects) { project ->
configure(rootProject) {
description = "Spring Framework"
apply plugin: "io.spring.nohttp"
apply plugin: 'org.springframework.build.api-diff'
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" }
}
}
tasks.named("checkstyleNohttp").configure {
maxHeapSize = "1g"
}
}
+10 -2
View File
@@ -1,5 +1,6 @@
plugins {
id 'java-gradle-plugin'
id 'checkstyle'
}
repositories {
@@ -17,10 +18,13 @@ ext {
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
implementation("org.jetbrains.kotlin:kotlin-compiler-embeddable:${kotlinVersion}")
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 {
@@ -33,6 +37,10 @@ gradlePlugin {
id = "org.springframework.build.conventions"
implementationClass = "org.springframework.build.ConventionsPlugin"
}
localDevPlugin {
id = "org.springframework.build.localdev"
implementationClass = "org.springframework.build.dev.LocalDevelopmentPlugin"
}
optionalDependenciesPlugin {
id = "org.springframework.build.optional-dependencies"
implementationClass = "org.springframework.build.optional.OptionalDependenciesPlugin"
+27
View File
@@ -0,0 +1,27 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" "https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="com.puppycrawl.tools.checkstyle.Checker">
<!-- Root Checks -->
<module name="io.spring.javaformat.checkstyle.check.SpringHeaderCheck">
<property name="fileExtensions" value="java"/>
<property name="headerType" value="apache2"/>
<property name="headerCopyrightPattern" value="20\d\d-20\d\d"/>
<property name="packageInfoHeaderType" value="none"/>
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck"/>
<!-- TreeWalker Checks -->
<module name="com.puppycrawl.tools.checkstyle.TreeWalker">
<!-- Imports -->
<module name="com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck">
<property name="processJavadoc" value="true"/>
</module>
<!-- Modifiers -->
<module name="com.puppycrawl.tools.checkstyle.checks.modifier.ModifierOrderCheck"/>
</module>
</module>
+1
View File
@@ -1 +1,2 @@
org.gradle.caching=true
javaFormatVersion=0.0.39
@@ -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.5");
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 + "**");
}
});
}
}
@@ -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.
@@ -25,10 +25,8 @@ 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.
*
* When the {@link JavaBasePlugin} is applied, the conventions in {@link TestConventions}
* are applied.
* When the {@link JavaBasePlugin} is applied, the conventions in {@link JavaConventions}
* are 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.
*
@@ -38,8 +36,10 @@ 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-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.
@@ -24,7 +24,10 @@ import org.gradle.api.Plugin;
import org.gradle.api.Project;
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;
import org.gradle.jvm.toolchain.JvmVendorSpec;
/**
* {@link Plugin} that applies conventions for compiling Java sources in Spring Framework.
@@ -68,6 +71,10 @@ public class JavaConventions {
* @param project the current project
*/
private void applyJavaCompileConventions(Project project) {
project.getExtensions().getByType(JavaPluginExtension.class).toolchain(toolchain -> {
toolchain.getVendor().set(JvmVendorSpec.BELLSOFT);
toolchain.getLanguageVersion().set(JavaLanguageVersion.of(17));
});
project.getTasks().withType(JavaCompile.class)
.matching(compileTask -> compileTask.getName().equals(JavaPlugin.COMPILE_JAVA_TASK_NAME))
.forEach(compileTask -> {
@@ -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,6 +16,8 @@
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;
@@ -26,8 +28,8 @@ 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} plugins is applied so that flaky tests
* are retried 3 times when running on the CI.
* <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
@@ -40,13 +42,37 @@ class TestConventions {
}
private void configureTestConventions(Project project) {
project.getPlugins().apply(TestRetryPlugin.class);
project.getTasks().withType(Test.class,
(test) -> project.getPlugins().withType(TestRetryPlugin.class, (testRetryPlugin) -> {
TestRetryTaskExtension testRetry = test.getExtensions().getByType(TestRetryTaskExtension.class);
testRetry.getFailOnPassedAfterRetry().set(true);
testRetry.getMaxRetries().set(isCi() ? 3 : 0);
}));
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() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.build.api;
import java.io.File;
@@ -131,10 +132,11 @@ public class ApiDiffPlugin implements Plugin<Project> {
}
private File getOutputFile(String baseLineVersion, Project project) {
Path outDir = Paths.get(project.getRootProject().getBuildDir().getAbsolutePath(),
"reports", "api-diff",
String buildDirectoryPath = project.getRootProject()
.getLayout().getBuildDirectory().getAsFile().get().getAbsolutePath();
Path outDir = Paths.get(buildDirectoryPath, "reports", "api-diff",
baseLineVersion + "_to_" + project.getRootProject().getVersion());
return project.file(outDir.resolve(project.getName() + ".html").toString());
}
}
}
@@ -0,0 +1,49 @@
/*
* 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.dev;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaBasePlugin;
/**
* {@link Plugin} that skips documentation tasks when the {@code "-PskipDocs"} property is defined.
*
* @author Brian Clozel
*/
public class LocalDevelopmentPlugin implements Plugin<Project> {
private static final String SKIP_DOCS_PROPERTY = "skipDocs";
@Override
public void apply(Project target) {
if (target.hasProperty(SKIP_DOCS_PROPERTY)) {
skipDocumentationTasks(target);
target.subprojects(this::skipDocumentationTasks);
}
}
private void skipDocumentationTasks(Project project) {
project.afterEvaluate(p -> {
p.getTasks().matching(task -> {
return JavaBasePlugin.DOCUMENTATION_GROUP.equals(task.getGroup())
|| "distribution".equals(task.getGroup());
})
.forEach(task -> task.setEnabled(false));
});
}
}
@@ -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 java.util.Collections;
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;
/**
* 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));
});
});
}
}
@@ -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.
@@ -19,7 +19,7 @@ package org.springframework.build.optional;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.tasks.SourceSetContainer;
@@ -40,10 +40,10 @@ public class OptionalDependenciesPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
Configuration optional = project.getConfigurations().create("optional");
Configuration optional = project.getConfigurations().create(OPTIONAL_CONFIGURATION_NAME);
optional.setCanBeConsumed(false);
optional.setCanBeResolved(false);
project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> {
project.getPlugins().withType(JavaBasePlugin.class, (javaBasePlugin) -> {
SourceSetContainer sourceSets = project.getExtensions().getByType(JavaPluginExtension.class)
.getSourceSets();
sourceSets.all((sourceSet) -> {
@@ -53,4 +53,4 @@ public class OptionalDependenciesPlugin implements Plugin<Project> {
});
}
}
}
@@ -1,3 +1,19 @@
/*
* 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.shadow;
import java.io.File;
+1 -1
View File
@@ -17,4 +17,4 @@ changelog:
- "type: dependency-upgrade"
contributors:
exclude:
names: ["bclozel", "jhoeller", "poutsma", "rstoyanchev", "sbrannen", "sdeleuze", "snicoll"]
names: ["bclozel", "jhoeller", "poutsma", "rstoyanchev", "sbrannen", "sdeleuze", "snicoll", "simonbasle"]
+3 -3
View File
@@ -1,4 +1,4 @@
FROM ubuntu:focal-20220922
FROM ubuntu:jammy-20231004
ADD setup.sh /setup.sh
ADD get-jdk-url.sh /get-jdk-url.sh
@@ -6,7 +6,7 @@ RUN ./setup.sh
ENV JAVA_HOME /opt/openjdk/java17
ENV JDK17 /opt/openjdk/java17
ENV JDK18 /opt/openjdk/java18
ENV JDK19 /opt/openjdk/java19
ENV JDK21 /opt/openjdk/java21
ENV JDK22 /opt/openjdk/java22
ENV PATH $JAVA_HOME/bin:$PATH
+5 -5
View File
@@ -3,13 +3,13 @@ set -e
case "$1" in
java17)
echo "https://github.com/bell-sw/Liberica/releases/download/17.0.5+8/bellsoft-jdk17.0.5+8-linux-amd64.tar.gz"
echo "https://download.bell-sw.com/java/17.0.9+11/bellsoft-jdk17.0.9+11-linux-amd64.tar.gz"
;;
java18)
echo "https://github.com/bell-sw/Liberica/releases/download/18.0.2.1%2B1/bellsoft-jdk18.0.2.1+1-linux-amd64.tar.gz"
java21)
echo "https://download.bell-sw.com/java/21.0.1+12/bellsoft-jdk21.0.1+12-linux-amd64.tar.gz"
;;
java19)
echo "https://github.com/bell-sw/Liberica/releases/download/19.0.1%2B11/bellsoft-jdk19.0.1+11-linux-amd64.tar.gz"
java22)
echo "https://download.java.net/java/early_access/jdk22/19/GPL/openjdk-22-ea+19_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 java19
for jdk in java17 java21 java22
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
+32 -79
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,22 +113,22 @@ 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
- name: repo-status-jdk19-build
context: jdk21-build
- name: repo-status-jdk22-build
type: github-status-resource
icon: eye-check-outline
source:
repository: ((github-repo-name))
access_token: ((github-ci-status-token))
branch: ((branch))
context: jdk19-build
context: jdk22-build
- name: slack-alert
type: slack-notification
icon: slack
@@ -176,7 +164,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
@@ -218,26 +206,22 @@ jobs:
threads: 8
artifact_set:
- include:
- "/**/framework-docs-*.zip"
- "/**/framework-api-*.zip"
properties:
"zip.name": "spring-framework"
"zip.displayname": "Spring Framework"
"zip.deployed": "false"
- include:
- "/**/framework-docs-*-docs.zip"
- "/**/framework-api-*-docs.zip"
properties:
"zip.type": "docs"
- include:
- "/**/framework-docs-*-dist.zip"
properties:
"zip.type": "dist"
- include:
- "/**/framework-docs-*-schema.zip"
- "/**/framework-api-*-schema.zip"
properties:
"zip.type": "schema"
get_params:
threads: 8
- name: jdk18-build
- name: jdk21-build
serial: true
public: true
plan:
@@ -245,7 +229,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
@@ -254,26 +238,24 @@ 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: jdk19-build
- name: jdk22-build
serial: true
public: true
plan:
- get: ci-image
- get: git-repo
- get: every-morning
trigger: true
- put: repo-status-jdk19-build
- put: repo-status-jdk22-build
params: { state: "pending", commit: "git-repo" }
- do:
- task: check-project
@@ -282,48 +264,17 @@ jobs:
privileged: true
timeout: ((task-timeout))
params:
TEST_TOOLCHAIN: 19
TEST_TOOLCHAIN: 22
<<: *build-project-task-params
on_failure:
do:
- put: repo-status-jdk19-build
- put: repo-status-jdk22-build
params: { state: "failure", commit: "git-repo" }
- put: slack-alert
params:
<<: *slack-fail-params
- put: repo-status-jdk19-build
- put: repo-status-jdk22-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:
@@ -365,6 +316,7 @@ jobs:
params:
RELEASE_TYPE: M
<<: *github-task-params
<<: *docker-resource-source
- put: github-pre-release
params:
<<: *changelog-task-params
@@ -403,6 +355,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
@@ -447,6 +400,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
@@ -464,6 +418,7 @@ jobs:
file: git-repo/ci/tasks/generate-changelog.yml
params:
RELEASE_TYPE: RELEASE
<<: *docker-resource-source
<<: *github-task-params
- put: github-release
params:
@@ -471,10 +426,8 @@ jobs:
groups:
- name: "builds"
jobs: ["build", "jdk18-build", "jdk19-build"]
jobs: ["build", "jdk21-build", "jdk22-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,JDK22 \
--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:
+2
View File
@@ -5,6 +5,8 @@ image_resource:
source:
repository: springio/github-changelog-generator
tag: '0.0.8'
username: ((docker-hub-username))
password: ((docker-hub-password))
inputs:
- name: git-repo
- name: artifactory-repo
+3 -1
View File
@@ -4,7 +4,9 @@ image_resource:
type: registry-image
source:
repository: springio/concourse-release-scripts
tag: '0.3.4'
tag: '0.4.0'
username: ((docker-hub-username))
password: ((docker-hub-password))
inputs:
- name: git-repo
- name: artifactory-repo
+119
View File
@@ -0,0 +1,119 @@
plugins {
id 'java-platform'
id 'io.freefair.aggregate-javadoc' version '8.3'
}
description = "Spring Framework API Docs"
apply from: "${rootDir}/gradle/publications.gradle"
repositories {
maven {
url "https://repo.spring.io/release"
}
}
dependencies {
moduleProjects.each { moduleProject ->
javadoc moduleProject
}
}
javadoc {
title = "${rootProject.description} ${version} API"
options {
encoding = "UTF-8"
memberLevel = JavadocMemberLevel.PROTECTED
author = true
header = rootProject.description
use = true
overview = "$rootProject.rootDir/framework-docs/src/docs/api/overview.html"
destinationDir = file("${project.buildDir}/docs/javadoc-api")
splitIndex = true
links(rootProject.ext.javadocLinks)
addBooleanOption('Xdoclint:syntax,reference', true) // only check syntax and reference with doclint
addBooleanOption('Werror', true) // fail build on Javadoc warnings
}
maxMemory = "1024m"
doFirst {
classpath += files(
// ensure the javadoc process can resolve types compiled from .aj sources
project(":spring-aspects").sourceSets.main.output
)
classpath += files(moduleProjects.collect { it.sourceSets.main.compileClasspath })
}
}
/**
* Produce KDoc for all Spring Framework modules in "build/docs/kdoc"
*/
rootProject.tasks.dokkaHtmlMultiModule.configure {
dependsOn {
tasks.named("javadoc")
}
moduleName.set("spring-framework")
outputDirectory.set(project.file("$buildDir/docs/kdoc-api"))
includes.from("$rootProject.rootDir/framework-docs/src/docs/api/dokka-overview.md")
}
/**
* Zip all Java docs (javadoc & kdoc) into a single archive
*/
tasks.register('docsZip', Zip) {
dependsOn = ['javadoc', rootProject.tasks.dokkaHtmlMultiModule]
group = "distribution"
description = "Builds -${archiveClassifier} archive containing api and reference " +
"for deployment at https://docs.spring.io/spring-framework/docs/."
archiveBaseName.set("spring-framework")
archiveClassifier.set("docs")
from("src/dist") {
include "changelog.txt"
}
from(javadoc) {
into "javadoc-api"
}
from(rootProject.tasks.dokkaHtmlMultiModule.outputDirectory) {
into "kdoc-api"
}
}
/**
* Zip all Spring Framework schemas into a single archive
*/
tasks.register('schemaZip', Zip) {
group = "distribution"
archiveBaseName.set("spring-framework")
archiveClassifier.set("schema")
description = "Builds -${archiveClassifier} archive containing all " +
"XSDs for deployment at https://springframework.org/schema."
duplicatesStrategy DuplicatesStrategy.EXCLUDE
moduleProjects.each { module ->
def Properties schemas = new Properties();
module.sourceSets.main.resources.find {
(it.path.endsWith("META-INF/spring.schemas") || it.path.endsWith("META-INF\\spring.schemas"))
}?.withInputStream { schemas.load(it) }
for (def key : schemas.keySet()) {
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
assert shortName != key
File xsdFile = module.sourceSets.main.resources.find {
(it.path.endsWith(schemas.get(key)) || it.path.endsWith(schemas.get(key).replaceAll('\\/', '\\\\')))
}
assert xsdFile != null
into(shortName) {
from xsdFile.path
}
}
}
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact docsZip
artifact schemaZip
}
}
}
+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'
+44 -233
View File
@@ -1,25 +1,47 @@
plugins {
id 'kotlin'
id 'io.spring.antora.generate-antora-yml' version '0.0.1'
id 'org.antora' version '1.0.0'
}
description = "Spring Framework Docs"
apply plugin: 'kotlin'
apply plugin: 'org.asciidoctor.jvm.convert'
apply plugin: 'org.asciidoctor.jvm.pdf'
apply from: "${rootDir}/gradle/ide.gradle"
apply from: "${rootDir}/gradle/publications.gradle"
configurations {
asciidoctorExtensions
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 {
api(project(":spring-context"))
api(project(":spring-web"))
implementation(project(":spring-core-test"))
implementation("org.assertj:assertj-core")
tasks.named("generateAntoraYml") {
asciidocAttributes = project.provider( {
return ["spring-version": project.version ]
} )
}
checkstyle {
sourceSets = []
tasks.register("generateAntoraResources") {
dependsOn 'generateAntoraYml'
}
jar {
@@ -30,230 +52,19 @@ javadoc {
enabled = false
}
dependencies {
asciidoctorExtensions "io.spring.asciidoctor.backends:spring-asciidoctor-backends:0.0.3"
}
repositories {
maven {
url "https://repo.spring.io/release"
}
}
/**
* Produce Javadoc for all Spring Framework modules in "build/docs/javadoc"
*/
task api(type: Javadoc) {
group = "Documentation"
description = "Generates aggregated Javadoc API documentation."
title = "${rootProject.description} ${version} API"
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")
dependsOn {
moduleProjects.collect {
it.tasks.getByName("jar")
}
}
doFirst {
classpath = files(
// ensure the javadoc process can resolve types compiled from .aj sources
project(":spring-aspects").sourceSets.main.output
)
classpath += files(moduleProjects.collect { it.sourceSets.main.compileClasspath })
}
options {
encoding = "UTF-8"
memberLevel = JavadocMemberLevel.PROTECTED
author = true
header = rootProject.description
use = true
overview = "framework-docs/src/docs/api/overview.html"
splitIndex = true
links(project.ext.javadocLinks)
addBooleanOption('Xdoclint:syntax', true) // only check syntax with doclint
addBooleanOption('Werror', true) // fail build on Javadoc warnings
}
source moduleProjects.collect { project ->
project.sourceSets.main.allJava
}
maxMemory = "1024m"
destinationDir = file("$buildDir/docs/javadoc")
implementation(project(":spring-core-test"))
implementation("org.assertj:assertj-core")
}
/**
* Produce KDoc for all Spring Framework modules in "build/docs/kdoc"
*/
rootProject.tasks.dokkaHtmlMultiModule.configure {
dependsOn {
tasks.getByName("api")
}
moduleName.set("spring-framework")
outputDirectory.set(project.file("$buildDir/docs/kdoc"))
}
asciidoctorj {
version = '2.4.3'
fatalWarnings ".*"
options doctype: 'book', eruby: 'erubis'
attributes([
icons: 'font',
idprefix: '',
idseparator: '-',
revnumber: project.version,
sectanchors: '',
sectnums: '',
'spring-version': project.version
])
}
/**
* Generate the Spring Framework Reference documentation from
* "src/docs/asciidoc" in "build/docs/ref-docs/html5".
*/
asciidoctor {
baseDirFollowsSourceDir()
configurations "asciidoctorExtensions"
sources {
include '*.adoc'
}
outputDir "$buildDir/docs/ref-docs/html5"
outputOptions {
backends "spring-html"
}
logDocuments = true
resources {
from(sourceDir) {
include 'images/*.png'
}
}
}
/**
* Generate the Spring Framework Reference documentation from "src/docs/asciidoc"
* in "build/docs/ref-docs/pdf".
*/
asciidoctorPdf {
baseDirFollowsSourceDir()
configurations 'asciidoctorExtensions'
sources {
include 'spring-framework.adocbook'
}
outputDir "$buildDir/docs/ref-docs/pdf"
forkOptions {
jvmArgs += ["--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", "--add-opens", "java.base/java.io=ALL-UNNAMED"]
}
logDocuments = true
}
/**
* Zip all docs (API and reference) into a single archive
*/
task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'asciidoctorPdf', rootProject.tasks.dokkaHtmlMultiModule]) {
group = "Distribution"
description = "Builds -${archiveClassifier} archive containing api and reference " +
"for deployment at https://docs.spring.io/spring-framework/docs/."
archiveBaseName.set("spring-framework")
archiveClassifier.set("docs")
from("src/dist") {
include "changelog.txt"
}
from (api) {
into "javadoc-api"
}
from ("$asciidoctor.outputDir") {
into "reference/html"
}
from ("$asciidoctorPdf.outputDir") {
into "reference/pdf"
}
from (rootProject.tasks.dokkaHtmlMultiModule.outputDirectory) {
into "kdoc-api"
}
}
/**
* Zip all Spring Framework schemas into a single archive
*/
task schemaZip(type: Zip) {
group = "Distribution"
archiveBaseName.set("spring-framework")
archiveClassifier.set("schema")
description = "Builds -${archiveClassifier} archive containing all " +
"XSDs for deployment at https://springframework.org/schema."
duplicatesStrategy DuplicatesStrategy.EXCLUDE
moduleProjects.each { module ->
def Properties schemas = new Properties();
module.sourceSets.main.resources.find {
(it.path.endsWith("META-INF/spring.schemas") || it.path.endsWith("META-INF\\spring.schemas"))
}?.withInputStream { schemas.load(it) }
for (def key : schemas.keySet()) {
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
assert shortName != key
File xsdFile = module.sourceSets.main.resources.find {
(it.path.endsWith(schemas.get(key)) || it.path.endsWith(schemas.get(key).replaceAll('\\/','\\\\')))
}
assert xsdFile != null
into (shortName) {
from xsdFile.path
}
}
}
}
/**
* Create a distribution zip with everything:
* docs, schemas, jars, source jars, javadoc jars
*/
task distZip(type: Zip, dependsOn: [docsZip, schemaZip]) {
group = "Distribution"
archiveBaseName.set("spring-framework")
archiveClassifier.set("dist")
description = "Builds -${archiveClassifier} archive, containing all jars and docs, " +
"suitable for community download page."
ext.baseDir = "spring-framework-${project.version}";
from("src/docs/dist") {
include "readme.txt"
include "license.txt"
include "notice.txt"
into "${baseDir}"
expand(copyright: new Date().format("yyyy"), version: project.version)
}
from(zipTree(docsZip.archiveFile)) {
into "${baseDir}/docs"
}
from(zipTree(schemaZip.archiveFile)) {
into "${baseDir}/schema"
}
moduleProjects.each { module ->
into ("${baseDir}/libs") {
from module.jar
if (module.tasks.findByPath("sourcesJar")) {
from module.sourcesJar
}
if (module.tasks.findByPath("javadocJar")) {
from module.javadocJar
}
}
}
}
distZip.mustRunAfter moduleProjects.check
publishing {
publications {
mavenJava(MavenPublication) {
artifact docsZip
artifact schemaZip
artifact distZip
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

@@ -0,0 +1,612 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generated by Microsoft Visio 11.0, SVG Export, v1.0 spring-overview.svg Page-1 -->
<svg
xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="6.4728541in"
height="5.9522467in"
viewBox="0 0 466.04561 428.56238"
xml:space="preserve"
class="st5"
id="svg5499"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="mvc-splitted-contexts.svg"
style="font-size:12px;overflow:visible;color-interpolation-filters:sRGB;fill:none;fill-rule:evenodd;stroke-linecap:square;stroke-miterlimit:3"
inkscape:export-filename="/Users/seb/Workspace/spring-framework/src/asciidoc/images/mvc-splitted-contexts.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"><metadata
id="metadata5713"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="https://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs5711"><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker9162"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path9164" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker8834"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path8836" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker8518"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path8520" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker8214"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path8216" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker7922"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path7924" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker7641"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path7644" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker7373"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path7375" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker7117"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path7119" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker6873"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path6875" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker6641"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path6643" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker6421"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path6423" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker6213"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path6215" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker6017"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path6019" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5833"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5835" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5661"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5663" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5501"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5503" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5353"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5355" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5217"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5219" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5093"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5095" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker4981"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path4983" /></marker><marker
inkscape:stockid="Arrow2Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Mend"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always"><path
id="path7394"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.6) rotate(180) translate(0,0)" /></marker><marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker8121"
style="overflow:visible;"
inkscape:isstock="true"><path
id="path8123"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) rotate(180) translate(1,0)" /></marker><marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker8033"
style="overflow:visible;"
inkscape:isstock="true"><path
id="path8035"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" /></marker><marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker7957"
style="overflow:visible;"
inkscape:isstock="true"><path
id="path7959"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" /></marker><marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;"
inkscape:isstock="true"><path
id="path7376"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" /></marker><marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Lend"
style="overflow:visible;"
inkscape:isstock="true"><path
id="path7388"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) rotate(180) translate(1,0)" /></marker><marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lend"
style="overflow:visible;"
inkscape:isstock="true"><path
id="path7370"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.8) rotate(180) translate(12.5,0)" /></marker></defs><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1680"
inkscape:window-height="1005"
id="namedview5709"
showgrid="false"
inkscape:zoom="1.1640492"
inkscape:cx="134.86698"
inkscape:cy="203.59898"
inkscape:window-x="84"
inkscape:window-y="176"
inkscape:window-maximized="0"
inkscape:current-layer="g5503"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" /><v:documentProperties
v:langID="1033"
v:viewMarkup="false" /><style
type="text/css"
id="style5501"><![CDATA[
.st1 {fill:#969696;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st2 {fill:#dde2cd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st3 {fill:#000000;font-family:Arial;font-size:2.50001em;font-weight:bold}
.st4 {font-size:0.333333em;font-weight:normal}
.st5 {fill:none;fill-rule:evenodd;font-size:12;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
]]></style><g
v:mID="0"
v:index="1"
v:groupContext="foregroundPage"
id="g5503"
transform="matrix(0.99998201,0,0,1.0824094,-40.812382,-98.908648)"><rect
style="fill:#dde2cd;fill-opacity:1;stroke:#000000;stroke-width:1.53790233;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6599"
width="382.68423"
height="146.09897"
x="87.884865"
y="148.26482" /><v:userDefs><v:ud
v:nameU="SchemeName"
v:val="VT4(Default)" /></v:userDefs><rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.53790233;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect5725"
width="464.31128"
height="374.11411"
x="41.684383"
y="112.3262" /><title
id="title5505">Page-1</title><v:pageProperties
v:drawingScale="0.0393701"
v:pageScale="0.0393701"
v:drawingUnits="24"
v:shadowOffsetX="8.50394"
v:shadowOffsetY="-8.50394" /><v:layer
v:name="Connector"
v:index="0" /><rect
style="fill:#dde2cd;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.53790233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect5715"
width="322.8194"
height="43.63184"
x="119.95335"
y="-135.66222"
transform="scale(1,-1)" /><text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:30.7580471px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="168.843"
y="124.32391"
id="text5717"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan5719"
x="168.843"
y="124.32391"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:23.06853676px;font-family:sans-serif;-inkscape-font-specification:sans-serif">DispatcherServlet</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="89.770851"
y="181.20923"
id="text6589"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan6591"
x="89.770851"
y="181.20923"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:23.06853676px;font-family:sans-serif;-inkscape-font-specification:sans-serif">Servlet WebApplicationContext</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="260.00443"
y="198.41273"
id="text6593"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan6595"
x="260.00443"
y="198.41273"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426838px;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle">(containing controllers, view resolvers,</tspan><tspan
sodipodi:role="line"
x="260.00443"
y="212.83057"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426838px;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle"
id="tspan6597">and other web-related beans)</tspan></text>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6620"
width="82.040657"
height="36.72575"
x="114.52653"
y="-259.43161"
transform="scale(1,-1)" /><rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.89166164;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6622"
width="87.843979"
height="36.697304"
x="223.39864"
y="-287.19809"
transform="scale(1,-1)" /><rect
transform="scale(1,-1)"
y="-264.81918"
x="117.92834"
height="36.72575"
width="82.040657"
id="rect6614"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="121.24728"
y="260.14957"
id="text6616"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan6618"
x="121.24728"
y="260.14957"
style="font-size:11.53426838px">Controllers</tspan></text>
<text
transform="scale(1.0403984,0.96117025)"
sodipodi:linespacing="125%"
id="text6624"
y="282.70709"
x="219.61203"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:11.53426838px"
y="282.70709"
x="219.61203"
id="tspan6626"
sodipodi:role="line">ViewResolver</tspan></text>
<rect
transform="scale(1,-1)"
y="-259.30249"
x="332.5405"
height="36.577778"
width="114.4539"
id="rect6628"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.0161339;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="327.51276"
y="255.28464"
id="text6630"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan6632"
x="327.51276"
y="255.28464"
style="font-size:11.53426838px">HandlerMapping</tspan></text>
<rect
y="338.69724"
x="87.803261"
height="121.5683"
width="382.84744"
id="rect6634"
style="fill:#dde2cd;fill-opacity:1;stroke:#000000;stroke-width:1.53790233;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
transform="scale(1.0403984,0.96117025)"
sodipodi:linespacing="125%"
id="text6636"
y="376.61673"
x="108.61351"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:23.06853676px;font-family:sans-serif;-inkscape-font-specification:sans-serif"
y="376.61673"
x="108.61351"
id="tspan6638"
sodipodi:role="line">Root WebApplicationContext</tspan></text>
<text
transform="scale(1.0403984,0.96117025)"
sodipodi:linespacing="125%"
id="text6640"
y="395.35812"
x="260.93863"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
id="tspan6644"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426838px;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle"
y="395.35812"
x="260.93863"
sodipodi:role="line">(containing middle-tier services, datasources, etc.)</tspan></text>
<rect
transform="scale(1,-1)"
y="-440.06805"
x="164.32933"
height="36.72575"
width="82.040657"
id="rect6648"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6650"
width="82.040657"
height="36.72575"
x="167.73116"
y="-445.45563"
transform="scale(1,-1)" /><text
transform="scale(1.0403984,0.96117025)"
sodipodi:linespacing="125%"
id="text6652"
y="448.55054"
x="175.87148"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:11.53426838px"
y="448.55054"
x="175.87148"
id="tspan6654"
sodipodi:role="line">Services</tspan></text>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.88435173;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6656"
width="86.393044"
height="36.704323"
x="306.86328"
y="-439.60837"
transform="scale(1,-1)" /><rect
transform="scale(1,-1)"
y="-444.99475"
x="310.26624"
height="36.701977"
width="86.876686"
id="rect6658"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.88679528;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="305.30771"
y="448.55054"
id="text6660"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan6662"
x="305.30771"
y="448.55054"
style="font-size:11.53426838px">Repositories</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.76895118px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 265.33234,295.60379 c 0,42.65169 0,42.65169 0,0 z"
id="path7643"
inkscape:connector-curvature="0" /><path
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.46028023;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
d="m 270.43505,294.70585 c 0,39.4721 0,39.87903 0,39.87903"
id="path7645"
inkscape:connector-curvature="0" /><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="352.55331"
y="333.03622"
id="text4963"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
x="352.55331"
y="333.03622"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426838px;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle"
id="tspan4965">Delegates if no bean found</tspan></text>
</g></svg>

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

+1
View File
@@ -0,0 +1 @@
../../../src
+441
View File
@@ -0,0 +1,441 @@
* 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/context-customizers.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-contextcustomizerfactories.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-spring/annotation-disabledinaotmode.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,7 +1,5 @@
[[appendix]]
= Appendix
include::attributes.adoc[]
include::page-layout.adoc[]
This part of the reference documentation covers topics that apply to multiple modules
within the core Spring Framework.
@@ -27,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
@@ -41,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
@@ -62,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].
|===
@@ -1,5 +1,11 @@
:chomp: default headers packages
// 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
@@ -7,10 +13,6 @@
: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
// Spring portfolio Links
: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
// Third-party Links
:docs-graalvm: https://www.graalvm.org/22.3/reference-manual
:gh-rsocket: https://github.com/rsocket
@@ -1,7 +1,5 @@
[[spring-core]]
= Core Technologies
include::attributes.adoc[]
include::page-layout.adoc[]
This part of the reference documentation covers all the technologies that are
absolutely integral to the Spring Framework.
@@ -20,24 +18,13 @@ is also provided.
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-beans.adoc[leveloffset=+1]
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-aot.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`, `pertarget`, and
`pertypewithin` instantiation models; `percflow` and `percflowbelow` 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 (advice 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.
@@ -1,11 +1,11 @@
[[core.aot]]
[[aot]]
= Ahead of Time Optimizations
This chapter covers Spring's Ahead of Time (AOT) optimizations.
For AOT support specific to integration tests, see <<testing.adoc#testcontext-aot, Ahead of Time Support for Tests>>.
For AOT support specific to integration tests, see xref:testing/testcontext-framework/aot.adoc[Ahead of Time Support for Tests].
[[core.aot.introduction]]
[[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.
@@ -16,7 +16,11 @@ 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.
** `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:
@@ -28,7 +32,7 @@ A Spring AOT processed application typically generates:
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.
[[core.aot.basics]]
[[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`]:
@@ -44,7 +48,7 @@ The `RuntimeHints` instance can also be used to generate the relevant GraalVM na
Those steps are covered in greater detail in the sections below.
[[core.aot.refresh]]
[[aot.refresh]]
== Refresh for AOT Processing
Refresh for AOT processing is supported on all `GenericApplicationContext` implementations.
@@ -52,15 +56,15 @@ An application context is created with any number of entry points, usually in th
Let's look at a basic example:
include::code:AotProcessingSample[tag=myapplication]
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 <<beans-introduction,regular `refresh`>>.
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]
include-code::./AotProcessingSample[tag=aotcontext]
In this mode, <<beans-factory-extension-factory-postprocessors,`BeanFactoryPostProcessor` implementations>> are invoked as usual.
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.
@@ -72,9 +76,9 @@ These are:
* `SmartInstantiationAwareBeanPostProcessor` implementations determine a more precise bean type if necessary.
This makes sure to create any proxy that will be required at runtime.
One 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.
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.
[[core.aot.bean-factory-initialization-contributions]]
[[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.
@@ -97,7 +101,7 @@ If such a bean is registered using an `@Bean` factory method, ensure the method
====
[[core.aot.bean-registration-contributions]]
[[aot.bean-registration-contributions]]
=== Bean Registration AOT Contributions
A core `BeanFactoryInitializationAotProcessor` implementation is responsible for collecting the necessary contributions for each candidate `BeanDefinition`.
@@ -106,7 +110,7 @@ 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 <<beans-factory-extension-bpp-examples-aabpp,`AutowiredAnnotationBeanPostProcessor`>> implements this interface to generate code that injects members annotated with `@Autowired`.
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.
@@ -122,8 +126,11 @@ This is the default behavior, since tuning the generated code for a bean definit
Taking our previous example, let's assume that `DataSourceConfiguration` is as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@Configuration(proxyBeanMethods = false)
public class DataSourceConfiguration {
@@ -135,12 +142,16 @@ Taking our previous example, let's assume that `DataSourceConfiguration` is as f
}
----
======
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"]
.Java
----
/**
* Bean definitions for {@link DataSourceConfiguration}
@@ -175,6 +186,7 @@ The AOT engine will convert the configuration class above to code similar to the
}
}
----
======
NOTE: The exact code generated may differ depending on the exact nature of your bean definitions.
@@ -183,8 +195,183 @@ There is a bean definition for `dataSourceConfiguration` and one for `dataSource
When a `datasource` instance is required, a `BeanInstanceSupplier` is called.
This supplier invokes the `dataSource()` method on the `dataSourceConfiguration` bean.
[[aot.bestpractices]]
== Best Practices
[[core.aot.hints]]
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.
@@ -195,11 +382,15 @@ Consequently, if the application needs to load a resource, it must be referenced
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"]
.Java
----
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).
@@ -208,14 +399,14 @@ For cases that the core container cannot infer, you can register such hints prog
A number of convenient annotations are also provided for common use cases.
[[core.aot.hints.import-runtime-hints]]
[[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[]
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.
@@ -223,7 +414,7 @@ This way, if the component is not contributed to the `BeanFactory`, the hints wo
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.
[[core.aot.hints.reflective]]
[[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.
@@ -237,7 +428,7 @@ 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.
[[core.aot.hints.register-reflection-for-binding]]
[[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.
@@ -246,8 +437,11 @@ A typical use case is the use of DTOs that the container cannot infer, such as u
`@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"]
.Java
----
@Component
public class OrderService {
@@ -259,15 +453,16 @@ The following example registers `Account` for serialization.
}
----
======
[[core.aot.hints.testing]]
[[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]
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.
@@ -279,11 +474,11 @@ For more targeted discovery and testing, Spring Framework ships a dedicated modu
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[]
include-code::./SampleReflection[]
We can then write a unit test (no native compilation required) that checks our contributed hints:
include::code:SampleReflectionRuntimeHintsTests[]
include-code::./SampleReflectionRuntimeHintsTests[]
If you forgot to contribute a hint, the test will fail and provide some details about the invocation:
@@ -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,672 @@
[[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.
[WARNING]
=====
Only one such element should be defined for a given application with the properties
that it needs. Several property placeholders can be configured as long as they have distinct
placeholder syntax (`${...}`).
If you need to modularize the source of properties used for the replacement, you should
not create multiple properties placeholders. Rather, each module should contribute a
`PropertySource` to the `Environment`. Alternatively, you can create your own
`PropertySourcesPlaceholderConfigurer` bean that gathers the properties to use.
=====
[[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