Compare commits

...

1200 Commits

Author SHA1 Message Date
Brian Clozel 908707ae28 Release v6.2.0-RC3 2024-10-24 11:03:16 +02:00
Sam Brannen 2d028c39b4 Align with naming in ReflectionTestUtils 2024-10-24 10:25:18 +02:00
Juergen Hoeller fe6d9145e5 Avoid hard dependency on Spring AOP for mock resolution
Closes gh-33774
2024-10-23 21:26:06 +02:00
rstoyanchev c160e89d9d Merge branch '6.1.x' 2024-10-23 19:09:53 +01:00
rstoyanchev bbe362c0e6 Allow null from RestClient exchange methods
Closes gh-33779
2024-10-23 19:08:54 +01:00
rstoyanchev bff76d756b Refactor implementation of retrieve in RestClient
Closes gh-33777
2024-10-23 18:59:07 +01:00
Sam Brannen 8fa99dcbdd Polishing 2024-10-23 17:16:41 +02:00
Sam Brannen 5bf179b851 Remove proxyTargetAware attribute from @⁠MockitoSpyBean
This commit removes the proxyTargetAware attribute from @⁠MockitoSpyBean
while keeping the underlying feature in tact (i.e., transparent
verification for spies created via @⁠MockitoSpyBean).

Closes gh-33775
2024-10-23 16:39:01 +02:00
Brian Clozel 20d21a8251 Rework links to Spring Boot in reference docs
Closes gh-33776
2024-10-23 16:10:37 +02:00
Sam Brannen d8a6423c0c Support transparent verification for @⁠MockitoSpyBean
Prior to this commit, SpringAopBypassingVerificationStartedListener
provided partial support for transparent verification for Mockito spies
created via @⁠MockitoSpyBean when the spy is wrapped in a Spring AOP
proxy. However, attempting to actually verify invocations for a spy
resulted in an exception from Mockito since MockUtil.isMock() returned
false in such scenarios.

This commit addresses that by introducing a SpringMockResolver that
resolves mocks by walking the Spring AOP proxy chain until the target
or a non-static proxy is found.

SpringMockResolver is automatically registered whenever the spring-test
JAR is on the classpath, allowing Mockito to transparently resolve mocks
wrapped in Spring AOP proxies.

Closes gh-33774
2024-10-23 15:51:35 +02:00
Sam Brannen c85689b308 Polishing 2024-10-23 14:01:52 +02:00
Sam Brannen 982f7f8f58 Verify @⁠MockitoBean & @⁠MockitoSpyBean can be used Spring AOP proxies
Use cases not yet supported with @⁠MockitoSpyBean are currently @⁠Disabled.

See gh-33742
2024-10-23 13:54:11 +02:00
rstoyanchev d05f880d74 Fix test causing failure in RestClientObservationTests
See gh-33697
2024-10-23 12:24:28 +01:00
rstoyanchev 2b113e3fd0 Minor refactoring
Closes gh-33697
2024-10-23 11:38:19 +01:00
rstoyanchev 73e5aa38ec Polishing contribution
See gh-33697
2024-10-23 11:38:19 +01:00
Nicklas Wiegandt a0af708c03 Add cookie support to RestClient
See gh-33697
2024-10-23 11:38:18 +01:00
Brian Clozel d8c153a9d1 Remove support for Resin Servlet container
This commit removes all references to the Resin Servlet container, as it
is not supported as of Spring Framework 6.0 because we require a
JakartaEE baseline.

Closes gh-33772
2024-10-23 10:10:29 +02:00
Brian Clozel 1ba773170d Merge branch '6.1.x' 2024-10-23 09:26:40 +02:00
Brian Clozel 4a81f2c904 Remove HTTP parts workaround for Resin
A workaround was added for the Resin Servlet container in gh-13937.
This avoids attempting to delete parts that are not named, because the
`part.delete()` call would fail for non-file entries. This can be
problematic for files that are unnamed as they might not be removed by
the Framework.

This commit removes this workaround as Resin is not supported anymore.

Fixes gh-33511
2024-10-23 09:24:30 +02:00
Juergen Hoeller 081d0b33d4 Consistently sort jar entries in doFindPathMatchingJarResources
Includes consistent clearCache() behavior for manifest entries.

Closes gh-33771
See gh-33705
2024-10-22 21:29:22 +02:00
Phillip Webb 1c69a3c521 Fix PathMatchingResourcePatternResolver manifest classpath discovery
Update `PathMatchingResourcePatternResolver` so that in addition to
searching the `java.class.path` system property for classpath enties,
it also searches the `MANIFEST.MF` files from within those jars.

Prior to this commit, the `addClassPathManifestEntries()` method
expected that the JVM had added `Class-Path` manifest entries to the
`java.class.path` system property, however, this did not always happen.

The updated code now performs a deep search by loading `MANIFEST.MF`
files from jars discovered from the system property. To deal with
potential performance issue, loaded results are also now cached.

The updated code has been tested with Spring Boot 3.3 jars extracted
using `java -Djarmode=tools`.

See gh-33705
2024-10-22 21:10:29 +02:00
rstoyanchev b7fc4bc5c8 Polishing contribution
Closes gh-33716
2024-10-22 17:37:45 +01:00
Ilya Serkov 657e002ed7 Fix HttpHeaders.setHost() to remove the header
See gh-33716
2024-10-22 17:37:44 +01:00
rstoyanchev 9252e741e1 Default webmvc handling of disconnected client errors
Closes gh-33753
2024-10-22 15:47:29 +01:00
rstoyanchev 5271f5b8a1 Polishing 2024-10-22 14:50:33 +01:00
Sam Brannen 626f4279f6 Merge branch '6.1.x' 2024-10-22 13:11:39 +02:00
Sam Brannen fb0a108254 Improve Javadoc for core SpEL APIs 2024-10-22 13:04:29 +02:00
Sam Brannen c98f314665 Throw ParseException for unsupported character in SpEL expression
Prior to this commit, the SpEL Tokenizer threw an IllegalStateException
when an unsupported character was detected in a SpEL expression;
however, the Javadoc for ExpressionParser.parseExpression() states that
it throws a ParseException if an exception occurred during parsing.

This commit addresses that issue by throwing a SpelParseException for
an unsupported character in a SpEL expression, using a new
UNSUPPORTED_CHARACTER enum constant in SpelMessage.

Closes gh-33767
2024-10-22 13:03:08 +02:00
Stéphane Nicoll 382b51a8d4 Polish 2024-10-22 11:33:52 +02:00
Sébastien Deleuze 2b0c1fa210 Improve the discoverability of Java and Kotlin APIs
This commit add external links in the refdoc to Java
and Kotlin APIs to make them more discoverable.

Closes gh-32835
2024-10-22 08:40:28 +02:00
Brian Clozel ec895534c5 Merge branch '6.1.x' 2024-10-21 18:34:49 +02:00
Sehwan Lim d22924c728 Fix incorrect regex rendering in MVC controller documentation
This commit fixes the issue where the regex pattern in the reference documentation
was not rendering correctly for the `/projects/{project:[a-z]+}/versions` mapping.

Closes gh-33766
2024-10-21 18:32:44 +02:00
Juergen Hoeller 267d3a36ae Merge branch '6.1.x'
# Conflicts:
#	spring-context/src/main/java/org/springframework/instrument/classloading/jboss/JBossLoadTimeWeaver.java
2024-10-21 18:14:50 +02:00
Juergen Hoeller e235e661d8 Polishing 2024-10-21 18:13:42 +02:00
Juergen Hoeller 09fe0adb40 Load-time weaving support for WildFly 24+
Closes gh-33728
2024-10-21 18:13:34 +02:00
Sam Brannen 1784ccb200 Upgrade to JUnit 5.11.3
Closes gh-33764
2024-10-21 16:58:14 +02:00
Sébastien Deleuze 57eb4823d2 Stop submitting Antora UI PR for 6.0.x and main branches
Closes gh-33765
2024-10-21 16:54:04 +02:00
Brian Clozel ab2f1f8885 Merge branch '6.1.x' 2024-10-21 16:20:57 +02:00
Brian Clozel 84e762b470 Fix double accounting of JMS process observations
Prior to this commit, the instrumentation of the processing of JMS
messages would happen a different levels of the hierarchy, accounting
for alli known implementations, `SimpleMessageListenerContainer` and
`DefaultMessageListenerContainer` as well as various use cases and
`MessageListener` variants.

Unfortunately, this instrumentation could lead to observing JMS
processing twice in some cases, and would not be consistent about the
scope of what's observed.

This commit moves the instrumentation basics into the
`AbstractMessageListenerContainer` but leaves the actual observation
calls to the public implementations.

Fixes gh-33758
2024-10-21 16:09:58 +02:00
Juergen Hoeller a1dd2e7c96 Merge branch '6.1.x' 2024-10-21 15:39:10 +02:00
Juergen Hoeller e90a2da05d Clarify defensive impact of allowEagerInit flag for type matching
Closes gh-33740
2024-10-21 15:38:25 +02:00
Juergen Hoeller ee1fe8a1e9 Consistently evaluate defaultCandidate flag on constructors and methods
Closes gh-33762
2024-10-21 13:53:28 +02:00
Sam Brannen 6f9413ba31 Merge branch '6.1.x' 2024-10-21 12:20:59 +02:00
Sam Brannen d48f388c6a Polish Javadoc for @⁠DateTimeFormat 2024-10-21 12:19:35 +02:00
RollW 6c93c67dd4 Add Kotlin code samples to the AOT documentation
Closes gh-33761
2024-10-21 11:21:05 +02:00
Sam Brannen 599d53465b Merge branch '6.1.x' 2024-10-20 17:43:45 +02:00
Sam Brannen bbbb7c396e Update Date/Time formatting tests for pre/post JDK 20
This commit updates our Date/Time formatting/printing tests to
demonstrate that the use of fallback patterns can help mitigate
locale-based parsing/formatting issues beginning with JDK 20.

The documentation within the tests is intentionally rather thorough for
two reasons:

1. We need to understand exactly what it is we are testing and why the
   tests are written that way.

2. We may re-use parts of the documentation and examples in forthcoming
   documentation that we will provide to users.

See gh-33151
2024-10-20 17:35:37 +02:00
Sam Brannen 68d9e5d81a Merge branch '6.1.x' 2024-10-19 15:03:15 +02:00
Sam Brannen d72c8b32b7 Ignore duplicate @⁠Priority values when determining highest priority
Prior to this commit, DefaultListableBeanFactory's
determineHighestPriorityCandidate() method sometimes failed to
determine the highest priority candidate if duplicate priority
candidates were detected whose priority was not the highest priority in
the candidate set. In addition, the bean registration order affected
the outcome of the algorithm: if the highest priority was detected
before other duplicate priorities were detected, the algorithm
succeeded in determining the highest priority candidate.

This commit addresses those shortcomings by ignoring duplicate
@⁠Priority values unless the duplication is for the highest priority
encountered, in which case a NoUniqueBeanDefinitionException is still
thrown to signal that multiple beans were found with the same "highest
priority".

Closes gh-33733
2024-10-19 14:54:29 +02:00
Sam Brannen 23f19a0fad Add link to existing bug report 2024-10-19 13:06:21 +02:00
Sam Brannen 14c476bd42 Verify @⁠MockitoBean can replace Spring AOP advised beans
See gh-33742
2024-10-18 17:53:44 +02:00
Sam Brannen a8b36f7ad5 Verify @⁠MockitoBean can replace beans that have @⁠Async methods
See gh-33742
2024-10-18 17:38:02 +02:00
Sam Brannen d5e334339a Verify @⁠MockitoBean can replace a scoped-proxy
See gh-33742
2024-10-18 17:14:59 +02:00
Sam Brannen c0ad9c0081 Verify @⁠MockitoBean & @⁠MockitoSpyBean can be used with @⁠ContextHierarchy
See gh-33742
2024-10-18 17:10:53 +02:00
Sam Brannen 2aa3f40257 Polishing 2024-10-18 16:55:40 +02:00
Sam Brannen 3842f12d09 Verify that the MockitoExtension and SpringExtension can be combined
See gh-33742
2024-10-18 16:51:52 +02:00
Brian Clozel 5f14703105 Merge branch '6.1.x' 2024-10-18 14:43:54 +02:00
Brian Clozel 67d78eb61c Avoid Servlet observations failures for invalid HTTP status
Prior to this commit, the `DefaultServerRequestObservationConvention`
for Servlet failed when the HTTP response status was invalid (for
example, set to "0").

This commit catches `IllegalArgumentException` thrown for such invalid
HTTP status and instead returns an unknown outcome for the observation.

Fixes gh-33725
2024-10-18 14:43:46 +02:00
Sébastien Deleuze e02f8ca492 Merge branch '6.1.x' 2024-10-18 12:37:00 +02:00
Johnny Lim 73fd9133e9 Fix Javadoc in ReactorNetty2ResourceFactory
See gh-33338
Closes gh-33735
2024-10-18 12:36:15 +02:00
Sébastien Deleuze 5abe5e1167 Merge branch '6.1.x' 2024-10-18 11:15:00 +02:00
Sébastien Deleuze 5e28a25a30 Add a WebFlux integration test
This commit adds a WebFlux integration test with a request
body and a delayed response in order to test a use case
where we found a regression with Undertow 2.3.18.Final.

For now, Undertow 2.3.17.Final is still used.

Closes gh-33739
2024-10-18 11:13:09 +02:00
Sébastien Deleuze 4c44b91cf9 Speedup WebFlux tests by reducing the interval period
In WebFlux, we have various tests using a period of 50 or 100ms.
We should use a smaller value like 1ms to speedup tests.

Closes gh-33738
2024-10-18 11:12:08 +02:00
Brian Clozel cee8b52de8 Merge branch '6.1.x' 2024-10-18 10:55:21 +02:00
Brian Clozel 912c067e23 Fix buffer leak in Jackson2 decoders
Prior to this commit, the Jackson2 decoders (JSON, Smile, CBOR) could
leak buffers in case the decoding operation times out or is cancelled
and some buffers are still in flight.

This commit ensures that buffers are released on cancel signals.

Fixes gh-33731
2024-10-18 10:51:38 +02:00
Brian Clozel 9a761579c0 Remove ServerResponse.AsyncBuilder interface
This new interface is not strictly necessary and introduces a binary
incompatibility. This commit merges back all the method definitions into
`SseBuilder` and `StreamBuilder` interfaces.

Closes gh-33736
2024-10-18 09:09:41 +02:00
Stéphane Nicoll 67c7b80c2b Merge branch '6.1.x' 2024-10-17 10:28:33 +02:00
Stéphane Nicoll a55701588e Next development version (v6.1.15-SNAPSHOT) 2024-10-17 10:28:22 +02:00
Stéphane Nicoll bdf76b2f8d Restore nested property resolution for non CharSequence types
Closes gh-33727

Co-authored-by: Andy Wilkinson <andy.wilkinson@broadcom.com>
2024-10-17 10:25:50 +02:00
Johnny Lim cbdfe815aa Add Javadoc since for headers() in Delete/Patch/Post/PutExchange
See gh-33309
Closes gh-33723
2024-10-16 18:11:29 +02:00
Sam Brannen ac458be845 Polish exception message 2024-10-16 17:49:57 +02:00
Sébastien Deleuze effe606b28 Refine record canonical constructor support in BeanUtils
This commit refines the contribution with the following changes:
 - Move the support to findPrimaryConstructor
 - Use a for loop instead of a Stream for more efficiency
 - Support other visibilities than public
 - Polishing

Closes gh-33707
2024-10-16 17:38:47 +02:00
evgenijnikiforov 514d6000d1 Support record canonical constructor in BeanUtils
See gh-33707
2024-10-16 17:38:47 +02:00
Sam Brannen 161d3995bf Introduce BeanOverrideHandler.createOverrideInstance() template method 2024-10-16 17:31:19 +02:00
Sam Brannen da856de100 Revise BeanOverrideRegistrar and rename it to BeanOverrideRegistry 2024-10-16 17:31:19 +02:00
Juergen Hoeller fa955934e7 Merge branch '6.1.x'
# Conflicts:
#	spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java
2024-10-16 17:19:30 +02:00
Juergen Hoeller fde7116ae4 Consistently skip processing of plain Java annotations
Closes gh-33580
2024-10-16 17:17:22 +02:00
rstoyanchev 92c9b0dc97 Reduce logging for unsent SUBSCRIBE messages
Closes gh-28252
2024-10-16 16:14:10 +01:00
Sam Brannen c0c78bd67e Rename OverrideMetadata for Bean Overrides
Prior to this commit, OverrideMetadata was the only public type in the
org.springframework.test.context.bean.override package whose name did
not start with BeanOverride. In addition, an OverrideMetadata component
plays multiple roles in addition to serving as a holder for metadata.

This commit therefore renames OverrideMetadata to BeanOverrideHandler.

In addition, this commit updates the affected documentation and renames
the following related methods in the Bean Override support.

- BeanOverrideHandler: createOverride() -> createOverrideInstance()
- BeanOverrideHandler: track() -> trackOverrideInstance()
- BeanOverrideProcessor: createMetadata() -> createHandler()
- BeanOverrideContextCustomizer: getMetadata() -> getBeanOverrideHandlers()
- BeanOverrideRegistrar: registerNameForMetadata() -> registerBeanOverrideHandler()
- BeanOverrideRegistrar: markWrapEarly() -> registerWrappingBeanOverrideHandler()

Closes gh-33702
2024-10-16 16:32:38 +02:00
Brian Clozel ab4fe5a29c Merge branch '6.1.x' 2024-10-16 16:26:12 +02:00
Brian Clozel 0a645916cd Add checkstyle rule for toLowerCase/toUpperCase
This commit adds a checkstyle rule that prevents the re-introduction of
such calls.

See gh-33708
2024-10-16 16:25:03 +02:00
Sébastien Deleuze beac903423 Merge branch '6.1.x' 2024-10-16 14:21:11 +02:00
Habin Song 5302e7aa25 Update fallback.adoc
Fix a typo.

Closes gh-33721
2024-10-16 14:20:56 +02:00
Sébastien Deleuze 0e70117d77 Merge branch '6.1.x' 2024-10-16 14:17:17 +02:00
github-actions[bot] cad02c1743 Update Antora Spring UI to v0.4.17 2024-10-16 14:15:55 +02:00
rstoyanchev ca820c914f Polishing contribution
Closes gh-33715
2024-10-16 13:06:22 +01:00
Yanming Zhou f35ed8d044 Improve check whether to lowercase scheme
See gh-33715

```
Map has no value for 'thescheme'
java.lang.IllegalArgumentException: Map has no value for 'thescheme'
	at org.springframework.web.util.UriComponents$MapTemplateVariables.getValue(UriComponents.java:348)
	at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:263)
	at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:436)
	at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:53)
	at org.springframework.web.util.UriComponents.expand(UriComponents.java:161)
	at org.springframework.web.util.UriComponentsBuilder.buildAndExpand(UriComponentsBuilder.java:364)
```
2024-10-16 12:54:33 +01:00
Juergen Hoeller e89218b39a Merge branch '6.1.x' 2024-10-16 13:46:22 +02:00
Juergen Hoeller c765d03a59 Use Locale.ROOT consistently for toLower/toUpperCase
Closes gh-33708
2024-10-16 13:44:59 +02:00
Juergen Hoeller 11d4272ff4 Use Locale.ROOT consistently for toLower/toUpperCase
Closes gh-33708
2024-10-16 13:36:23 +02:00
rstoyanchev bdcfbee7df Merge branch '6.1.x' 2024-10-16 12:11:23 +01:00
rstoyanchev 23656aebc6 Use Locale.ROOT consistently for toLower/toUpperCase
See gh-33708
2024-10-16 12:05:54 +01:00
Juergen Hoeller fb6a6892ef Merge branch '6.1.x' 2024-10-16 11:36:30 +02:00
Juergen Hoeller feb6a5f52d Polishing 2024-10-16 11:35:23 +02:00
Simon Baslé dbbc578676 Polishing
Inline `AbstractMockitoTestExecutionListener` since there's now only one
Mockito `TestExecutionListener`.
2024-10-16 10:22:38 +02:00
Simon Baslé 6f79c7e70f Remove support for Mockito annotations and MockitoSession
This change remove the support for Mockito annotations, `MockitoSession`
and opening/closing of mocks that was inherited from Boot's `@MockBean`
support, as well as the switch to `MockitoSession` made in 1c893e6.

Attempting to take responsability for things Mockito's own JUnit
Jupiter extension does better is not ideal, and we found it leads to
several corner cases which make `SpringExtension` and `MockitoExtension`
incompatible in the current approach.

Instead, this change refocuses our Mockito bean overriding support
exclusively on aspects specific to the Framework. `MockitoExtension`
will thus be usable in conjunction with `SpringExtension` if one needs
to use `@Captor`/`@InitMocks`/`@Mock`/`@Spy` or other Mockito utilities.

See gh-33318
Closes gh-33692
2024-10-16 09:40:57 +02:00
rstoyanchev c261ca3102 Ensure scheme not lowercased if URI variable
Closes gh-33699
2024-10-15 20:50:01 +01:00
rstoyanchev a63cf06496 Update Javadoc snippets for static resource locations
Switch to FileUrlResource, the same as what is used get with
the "file:" prefix in webmvc and webflux config.

See gh-33712
2024-10-15 19:23:07 +01:00
rstoyanchev 789d7effa9 Assert static resource location
Closes gh-33712
2024-10-15 19:23:07 +01:00
Brian Clozel f204f4962d Document XML parser usage against security false positives
Prior to this commit, our XML parser usage would be already haredened
against XXE (XML External Entities) attacks. Still, we recently received
several invalid security reports claiming that our setup should be
hardened.

This commit documents a few usages of XML parsers to add some more
context and hopefully prevent future invalid reports.

Closes gh-33713
2024-10-15 18:59:02 +02:00
Habin Song 166714c8f5 Update scheduling.adoc
Change quotation marks to backticks.

Closes gh-33709
2024-10-15 18:21:42 +02:00
Sam Brannen 67cb3c77ec Rename BeanOverrideStrategy enum constants
Closes gh-33701
2024-10-15 18:19:59 +02:00
Rossen Stoyanchev 7ea43bb252 Update SECURITY.md 2024-10-15 17:13:29 +01:00
Brian Clozel 88b684c981 Update security policy and issue template
Because Spring Framework already has a security policy, this shows up in
the issue template automatically. This commit removes the extra external
link and updates the original security policy.

See gh-33711
2024-10-15 17:57:04 +02:00
Brian Clozel 3bc2c91eff Revisit GitHub issue template
Prior to this commit, this repository had a single issue template
markdown file that listed all the information for creating a new issue
in this project. Because there was a lot, people missed warnings against
creating security reports publicly or asking questions in the issue
tracker.

This commit introduces an issue template configuration that provides
developers with a choice before creating the actual issue.

Closes gh-33711
2024-10-15 17:36:48 +02:00
Stéphane Nicoll 7f7de55b67 Merge branch '6.1.x' 2024-10-15 14:59:10 +02:00
Stéphane Nicoll 453849ab20 Upgrade to Reactor 2024.0.0-RC1
Closes gh-33636
2024-10-15 14:57:44 +02:00
Stéphane Nicoll a228eb8bd6 Upgrade to Reactor 2023.0.11
Closes gh-33637
2024-10-15 14:56:57 +02:00
Stéphane Nicoll f03f074581 Merge branch '6.1.x' 2024-10-15 09:13:35 +02:00
Stéphane Nicoll c79b575417 Upgrade to Micrometer 1.14.0-RC1
Closes gh-33648
2024-10-15 09:07:45 +02:00
Stéphane Nicoll c015814140 Upgrade to Micrometer 1.12.11
Closes gh-33647
2024-10-15 09:06:27 +02:00
rstoyanchev 5099657244 Merge branch '6.1.x' 2024-10-14 18:18:39 +01:00
rstoyanchev 7d3a3d35ce Update valid path checks for double encoding
See gh-33687
2024-10-14 18:14:01 +01:00
rstoyanchev fb7890d739 Update processPath for double encoding
See gh-33689
2024-10-14 18:13:55 +01:00
Sébastien Deleuze 20cdd192d9 Merge branch '6.1.x' 2024-10-14 19:01:43 +02:00
Habin Song 7c2c4d7c9a Update scheduling.adoc
Change 'OutOfMemoryErrors' to 'OutOfMemoryError'.

Closes gh-33703
2024-10-14 19:01:33 +02:00
Sébastien Deleuze 60978ff4c7 Polish WebRequest Javadoc
See gh-33698
2024-10-14 17:07:07 +02:00
rstoyanchev cff6db02b4 Merge branch '6.1.x' 2024-10-14 16:00:48 +01:00
rstoyanchev 1a0b577bfc Do not support relative static resource paths
Closes gh-33687
2024-10-14 15:54:59 +01:00
rstoyanchev 3bfbe30a78 Normalize static resource path early
Rather than leaving it to the Resource implementation, and
potentially normalizing twice, we apply it once as part of the
initial processPath checks.

Closes gh-33689
2024-10-14 15:52:15 +01:00
Tran Ngoc Nhan e191c34078 Polishing
Closes gh-33681
2024-10-14 16:44:42 +02:00
KimJuHyun 5bcce17fd9 Add tests for CollectionUtils
- findValueOfType
- findCommonElementType
- firstElement
- lastElement
- toArray
- compositeMap

Closes gh-33694
2024-10-14 16:10:05 +02:00
Brian Clozel 9be3d85a06 Merge branch '6.1.x' 2024-10-14 15:04:58 +02:00
Brian Clozel 32962894a0 Add runtime hints for JMS connection factories proxies
Prior to this commit, the JMS connection factories would proxy various
interfaces. This typically requires runtime hints for GraalVM native
applications and spring-jms is missing those.

This commit adds a new `ConnectionFactoriesRuntimeHints` that
contributes such hints with type conditions.

Fixes gh-33590
2024-10-14 14:54:24 +02:00
海子 Yang 3984266295 Remove unused method in UriComponentsBuilder
This commit removes HierarchicalUriComponents#checkSchemeAndHost
unused private method.

Closes gh-33684
2024-10-14 14:02:31 +02:00
Sébastien Deleuze a75f22e548 Merge branch '6.1.x' 2024-10-14 12:09:00 +02:00
Hosam Aly 97bce6d361 Fix link in testing/support-jdbc.adoc
Fix the link to "Testing Data Access Logic with an Embedded Database".

Closes gh-33686
2024-10-14 12:07:17 +02:00
Simon Baslé 12134e8619 Merge branch '6.1.x' 2024-10-14 11:57:39 +02:00
Simon Baslé 8da31e1db7 Reject CORS request with 403 if Origin header is malformed
When assessing if a request is a CORS request, both mvc and reactive
`DefaultCorsProcessor` now catch `IllegalArgumentException` and turn
this into a 403 rejection rather than letting the exception propagate
into a 500 response.

Closes gh-33688
2024-10-14 11:50:19 +02:00
Sangmin Park ae32227b50 Polish ServletWebRequest
Closes gh-33698
2024-10-14 11:38:24 +02:00
Sam Brannen b3cc9a219e Ensure that @⁠MockitoBeanSettings is inherited in @⁠Nested test class
Closes gh-33685
2024-10-11 17:20:53 +02:00
Juergen Hoeller 7ea0ac55cd Restore special instance supplier generation for inner classes
Closes gh-33683
2024-10-11 16:59:15 +02:00
Juergen Hoeller b748cb38c5 Rename to Mockito(Spy)BeanForFactoryBeanIntegrationTests 2024-10-11 16:58:18 +02:00
Sam Brannen eb4bf1c0a6 Support @⁠MockitoBean reset and MockitoSession management with @⁠Nested tests
Prior to this commit, the MockitoResetTestExecutionListener failed to
reset mocks created via @⁠MockitoBean if the @⁠MockitoBean field was
declared in an enclosing class for a @⁠Nested test class. In addition,
the MockitoSession was not properly managed by the
MockitoTestExecutionListener.

This commit addresses those issue as follows.

1) The hasMockitoAnnotations() utility method has been overhauled so
that it finds Mockito annotations not only on the current test class
and on fields of the current test class but also on interfaces,
superclasses, and enclosing classes for @⁠Nested test classes as well
as on fields of superclasses and enclosing classes.

That allows the MockitoResetTestExecutionListener to properly detect
that it needs to reset mocks for fields declared in enclosing classes
for @⁠Nested classes.

2) MockitoTestExecutionListener has been revised so that it only
initializes a MockitoSession before each test method and closes the
MockitoSession after each test method. In addition, it now only manages
the MockitoSession when hasMockitoAnnotations() returns true for the
current test class (which may be a @⁠Nested test class). Furthermore,
it no longer attempts to initialize a MockitoSession during the
prepareTestInstance() callback since that results in an
UnfinishedMockingSessionException for a @⁠Nested test class due to the
fact that a MockitoSession was already created for the current thread
for the enclosing test class.

Closes gh-33676
2024-10-11 16:14:42 +02:00
Sam Brannen 7fb6a2e4f7 Polish Javadoc for Bean Override TestExecutionListeners 2024-10-11 15:50:56 +02:00
Sam Brannen e2d981e809 Extract common logic into AbstractMockitoTestExecutionListener 2024-10-11 10:15:49 +02:00
Simon Baslé 0f25c75b9e Document TestExecutionListener implementations introduced in 6.2
Closes gh-33661
2024-10-10 16:32:38 +02:00
Sam Brannen 0e8316e704 Add value attribute alias to @⁠MockitoBean and @⁠MockitoSpyBean
This commit improves the user experience for common use cases by
introducing new `value` attributes in @⁠MockitoBean and
@⁠MockitoSpyBean that are aliases for the existing `name` attributes.

For example, this allows developers to declare
@⁠MockitoBean("userService") instead of @⁠MockitoBean(name =
"userService"), analogous to the existing name/value alias support in
@⁠TestBean.

Closes gh-33680
2024-10-10 13:05:39 +02:00
Sam Brannen 1b8f2c46c1 Update Javadoc for @⁠Mockito[Spy]Bean to reflect current semantics 2024-10-10 12:19:36 +02:00
Sam Brannen f7e32a9c78 Revise singleton destruction for Bean Overrides
See gh-33678
2024-10-10 12:13:44 +02:00
Sam Brannen 8d652e9c12 Reinstate Bean Override support for replacing a manually registered singleton
Closes gh-33678
2024-10-09 18:10:07 +02:00
Sam Brannen c70a6d3be1 Fix test method names 2024-10-09 17:17:57 +02:00
Sam Brannen 1afcb22205 Change enforceOverride flag to false in @⁠TestBean and @⁠MockitoBean
Based on feedback from the Spring Boot team, we have decided to change
the default values for the enforceOverride flags in @⁠TestBean and
@⁠MockitoBean from true to false.

Closes gh-33613
2024-10-09 17:08:58 +02:00
Sam Brannen 381b16fba2 Simplify Bean Override field injection logic
This commit simplifies the field injection logic for Bean Overrides in
order to align with the semantics of the core container and the Spring
TestContext Framework.

Closes gh-33677
2024-10-09 15:43:32 +02:00
Sam Brannen 4758424f6c Clean up warnings in Gradle build 2024-10-09 15:43:32 +02:00
Sam Brannen 7c3624318b Polish Mockito TestExecutionListeners 2024-10-09 15:43:32 +02:00
Sam Brannen 461f1724b7 Colocate nonexistent bean definition processing for Bean Overrides 2024-10-09 15:43:32 +02:00
Sam Brannen b5c82b8dcb Reject bean names with factory prefix for Bean Overrides
Closes gh-33674
2024-10-09 15:43:32 +02:00
Sam Brannen c864afd6fe Polishing 2024-10-09 15:43:32 +02:00
Stéphane Nicoll f54fabad8f Merge pull request #33669 from Seungpang
* pr/33669:
  Polish "Reject empty strings in DurationFormatterUtils"
  Reject empty strings in DurationFormatterUtils

Closes gh-33669
2024-10-09 15:27:59 +02:00
Stéphane Nicoll e2238c0211 Polish "Reject empty strings in DurationFormatterUtils"
See gh-33669
2024-10-09 15:26:09 +02:00
Seungrae 02c990ca82 Reject empty strings in DurationFormatterUtils
See gh-33669
2024-10-09 15:20:11 +02:00
Stéphane Nicoll 7f7f65cfcb Merge branch '6.1.x' 2024-10-09 14:44:38 +02:00
Stéphane Nicoll f991c19b30 Merge pull request #33617 from asibross
* pr/33617:
  Polish "Adapt Javadoc note about log level of BeanPostProcessorChecker"
  Adapt Javadoc note about log level of BeanPostProcessorChecker

Closes gh-33617
2024-10-09 14:44:32 +02:00
Stéphane Nicoll 3c80d4c978 Polish "Adapt Javadoc note about log level of BeanPostProcessorChecker"
See gh-33617
2024-10-09 14:42:36 +02:00
Asi Bross 6da32b4631 Adapt Javadoc note about log level of BeanPostProcessorChecker
See gh-33617
2024-10-09 14:40:49 +02:00
rstoyanchev 8520fa5e2a Reduce warnings in WhatWgUrlParser 2024-10-09 13:29:49 +01:00
rstoyanchev f4967f202e Revise URI template handling in WhatWgUrlParser
Closes gh-33673
2024-10-09 13:29:49 +01:00
rstoyanchev 1f4743af54 Lenient handling of malformed query in ServletServerHttpRequest
Closes gh-30489
2024-10-09 13:29:49 +01:00
Stéphane Nicoll af85d1997b Merge branch '6.1.x' 2024-10-09 14:25:26 +02:00
Stéphane Nicoll 6677d452e7 Start building against Micrometer 1.14.0-RC1 snapshots
See gh-33648
2024-10-09 14:19:35 +02:00
Stéphane Nicoll 91cadf7f24 Start building against Reactor 2023.0.11 snapshots
See gh-33637
2024-10-09 14:16:14 +02:00
Stéphane Nicoll 90637b6344 Start building against Micrometer 1.12.11 snapshots
See gh-33647
2024-10-09 14:15:22 +02:00
Simon Baslé ef77b4064f Keep DefaultServerHttpRequestBuilder-mutated headers case-insensitive
This change avoids the trap of creating a copy of `HttpHeaders` using a
case-sensitive `MultiValueMap` by mistake. Since mutability is always
desirable, we make a mutable copy by using `addAll` on an empty
`HttpHeaders`.

We can't simply rely on HttpHeaders' map-based constructor to detect
read-only header in this particular case, because the container's
original headers representation might in some cases be read-only.

Closes gh-33666
2024-10-09 11:39:33 +02:00
Sam Brannen 59ef5e140f Update warning for use of convention-based annotation attribute overrides
See gh-28761
2024-10-09 10:03:22 +02:00
Sam Brannen e1c450d253 Support Bean Overrides with AOT and native image
This set of commits introduces AOT and native image support for the new
Bean Override feature in the Spring TestContext Framework -- for
example, for using @⁠TestBean and @⁠MockitoBean in AOT mode on the JVM
as well as in a GraalVM native image.

Note, however, that @⁠MockitoBean has currently only been tested in a
native image when mocking interfaces and using Mockito's
ProxyMockMaker, along with a custom runtime hints.

Closes gh-32933
2024-10-08 17:57:21 +02:00
Sam Brannen 65d219131c Stop disabling MockitoResetTestExecutionListener within a native image
Instead, MockitoResetTestExecutionListener is now only enabled if the
current test class uses Mockito annotations or Mockito-related
annotations in spring-test.

See gh-32933
2024-10-08 17:41:30 +02:00
Sam Brannen 9a4be95dee Verify registration of runtime hints for Bean Overrides
See gh-32933
2024-10-08 17:41:30 +02:00
Sam Brannen 6a2e234a87 Register runtime hints for BeanOverrideProcessors
This commit introduces a BeanOverrideReflectiveProcessor which
registers runtime hints for any BeanOverrideProcessor configured
via @⁠BeanOverride.

See gh-32933
2024-10-08 17:41:17 +02:00
Sam Brannen 5ddeb06640 Skip pseudo bean definition registration during AOT processing
Prior to this commit, AOT processing failed for tests that made use of
the Bean Override feature to "override" a nonexistent bean. The reason
is that we register a "pseudo" bean definition as a placeholder for a
nonexistent bean, and our AOT support cannot automatically convert that
"pseudo" bean definition to a functional bean definition for use at AOT
runtime.

To address that, this commit skips registration of "pseudo" bean
definitions during AOT processing, and by doing so we enable the JVM
runtime and AOT runtime to operate with the same semantics.

See gh-32933
2024-10-08 17:41:11 +02:00
Sam Brannen ce8e06cf10 Register Bean Override infrastructure beans as manual singletons
Prior to this commit, AOT processing failed for tests that made use of
the Bean Override feature, since the Set<OverrideMetadata> constructor
argument configured in the bean definition for the
BeanOverrideBeanFactoryPostProcessor cannot be properly processed by
our AOT support. The reason is that each OverrideMetadata instance is
effectively an arbitrary object graph that cannot be automatically
converted to a functional bean definition for use at AOT runtime.

To address that, this commit registers Bean Override infrastructure
beans as manual singletons instead of via bean definitions with the
infrastructure role.

See gh-32933
2024-10-08 16:58:59 +02:00
Juergen Hoeller f590511112 Introspect pre-registered singletons in preDetermineBeanTypes as well
Closes gh-33668
2024-10-08 16:50:12 +02:00
rstoyanchev c4b6a02091 Polishing contribution
Closes gh-33594
2024-10-08 13:32:33 +01:00
Johnny Lim 1ec9a115a8 Replace RFC 7807 with RFC 9457 in documentation
See gh-33594
2024-10-08 13:32:33 +01:00
Brian Clozel 3303c98650 Fix link to code of conduct
Closes gh-33663
2024-10-08 14:03:54 +02:00
rstoyanchev 000b8a699c Auto-detect Reactor Netty client in RestClient
Closes gh-33635
2024-10-08 10:56:43 +01:00
rstoyanchev a84a41fa43 Polishing contribution
Closes gh-33638
2024-10-08 10:56:42 +01:00
Dariusz Jędrzejczyk a78385f8e5 Handle X-Forwarded-Prefix parsed by Reactor Netty
See gh-33638
2024-10-08 10:56:42 +01:00
Juergen Hoeller f9f025df43 Add note on autowireCandidate versus defaultCandidate
Closes gh-33392
2024-10-08 11:36:39 +02:00
Juergen Hoeller 1eee795143 Merge branch '6.1.x' 2024-10-08 11:34:27 +02:00
Juergen Hoeller 2622db1dbe Consistent references to annotation-based autowiring 2024-10-08 11:26:42 +02:00
rstoyanchev b13f86cf46 Fix failing tests in spring-test after recent changes
See gh-33639
2024-10-07 21:09:10 +01:00
rstoyanchev 2389748e25 Parameterize URI parsing tests
Closes gh-33639
2024-10-07 18:35:03 +01:00
rstoyanchev d6fcad9ad7 Add logging to RfcUriParser
See gh-33639
2024-10-07 18:35:03 +01:00
rstoyanchev ef0a21ec7a Update documentation for URI parsing types
See gh-33639
2024-10-07 18:35:03 +01:00
rstoyanchev 6c62965cbb Remove regular expressions from UriComponentsBuilder
See gh-33639
2024-10-07 18:35:03 +01:00
rstoyanchev bbb53d03c4 Pluggable URI parsing, use RFC parser by default
See gh-33639
2024-10-07 18:35:03 +01:00
rstoyanchev 52805da733 Add URI parser based on syntax in RFC 3986
See gh-33639
2024-10-07 18:35:03 +01:00
rstoyanchev 10f45223aa Rename UrlParser to WhatWgUrlParser
See gh-33639
2024-10-07 18:35:03 +01:00
rstoyanchev 6ba3bb54a0 Add efficient isUnreservedOrSubDelimiter method
isUnreserved and isSubDelimiter are usually checked together. It helps
to have a shortcut with an efficient lookup.

See gh-33639
2024-10-07 18:35:03 +01:00
rstoyanchev e04b115a7e Remove test for IPv4 compatible IPv6 address
An example of this can be found in RFC 2732, but it is obsoleted by
RFC 3986 whose syntax for IPv6address does not allow dots.

Also, Appendix D of RFC 3986:

As [RFC2732] defers to [RFC3513] for definition of an IPv6 literal
address, which, unfortunately, lacks an ABNF description of
IPv6address, we created a new ABNF rule for IPv6address that matches
the text representations defined by Section 2.2 of [RFC3513].

See gh-33639
2024-10-07 18:35:03 +01:00
rstoyanchev 92308ac83f Polishing in UrlParser 2024-10-07 18:35:02 +01:00
Sam Brannen 98bee41630 Polish BeanOverrideBeanFactoryPostProcessor 2024-10-07 14:22:53 +02:00
Juergen Hoeller c10a7f300c Merge branch '6.1.x' 2024-10-07 10:20:38 +02:00
Juergen Hoeller 3dac274d20 Avoid synchronization for delegate initialization
Closes gh-33656
2024-10-07 10:19:16 +02:00
Khyojun f86bc1cbe8 Polish CorsConfiguration
Closes gh-33650
2024-10-07 09:11:36 +02:00
KimJuHyun f1cbbd2aa8 Remove redundant array length check
Closes gh-33655
2024-10-07 08:24:37 +02:00
Stéphane Nicoll c73e76cf2e Merge branch '6.1.x' 2024-10-07 08:06:50 +02:00
Stéphane Nicoll 6b975592bf Harmonize GitHub Actions structure
See https://github.com/spring-projects/spring-boot/issues/42512
2024-10-07 07:57:16 +02:00
Sam Brannen ad4f0c99bf Polish StringUtilsTests 2024-10-06 15:36:16 +02:00
zinzo 2cd1ee8a24 Add unit tests for StringUtils.hasLength()
Closes gh-33658
2024-10-06 15:28:41 +02:00
Johnny Lim 1016743fc3 Remove Javadoc @⁠since tag from MapAccessor default constructor
See gh-33222
Closes gh-33659
2024-10-06 15:18:48 +02:00
Sam Brannen 28b9cf3b83 Simplify and document BeanOverrideTestExecutionListener
This commit simplifies the implementation of
BeanOverrideTestExecutionListener by introducing a static
injectFields() utility method and removing the use of BiConsumers,
records, and duplicated code.

This commit also introduces Javadoc for all methods in
BeanOverrideTestExecutionListener.

Closes gh-33660
2024-10-06 15:05:10 +02:00
Sam Brannen b0c7d15d9f Polishing 2024-10-05 13:57:24 +02:00
Park Sung Jun 32df079b05 Polish use of constants in StringUtils
The hardcoded '.' and '\\' literals have been replaced by the use of
EXTENSION_SEPARATOR and WINDOWS_FOLDER_SEPARATOR_CHAR.

Closes gh-33654
2024-10-05 13:57:24 +02:00
Sam Brannen d89983d633 Upgrade to Mockito 5.14.1 2024-10-04 17:24:55 +02:00
Sam Brannen d957d01d14 Polishing 2024-10-04 15:48:26 +02:00
Sam Brannen c4c005b82e Emulate AbstractAotProcessor.process() in AOT endToEndTests() 2024-10-04 15:46:23 +02:00
Sam Brannen 21d80dd849 Upgrade to JUnit 5.11.2 2024-10-04 15:39:00 +02:00
Sam Brannen b7f394c2a1 Merge branch '6.1.x' 2024-10-04 15:36:51 +02:00
Sam Brannen c44e43d791 Upgrade to JUnit 5.10.5 2024-10-04 15:33:25 +02:00
Sam Brannen 2569aa157e Make use of Executable abstraction in ProxyRuntimeHintsRegistrar 2024-10-04 15:05:37 +02:00
Sam Brannen 911d1b03cd Polishing 2024-10-04 15:05:37 +02:00
Sam Brannen fb5e4c0ef2 Remove obsolete method parameter 2024-10-04 11:16:49 +02:00
Stéphane Nicoll beca562ac2 Merge branch '6.1.x' 2024-10-04 10:20:28 +02:00
Stéphane Nicoll c41f8ea3c8 Merge pull request #33634 from junhyeongkim2
* pr/33634:
  Use HttpMethod.GET for better readability

Closes gh-33634
2024-10-04 10:20:20 +02:00
jun a668580f77 Use HttpMethod.GET for better readability
See gh-33634
2024-10-04 10:10:58 +02:00
SungbinYang 65ac17ee78 Refactor: Replace hardcoded path separator with PATH_SEPARATOR constant
Replaced the hardcoded '/' path separator with the `PATH_SEPARATOR` constant
to improve code readability and maintainability. This change ensures
consistency across the codebase when handling path separators.

Closes gh-33646
2024-10-04 09:19:16 +02:00
Sébastien Deleuze d65bdce0e8 Remove CglibMethodInvocation
This class does not add anything anymore and can be
replaced by a plain ReflectiveMethodInvocation.

Closes gh-33585
2024-10-03 19:53:49 +02:00
Sébastien Deleuze eebaa3538a Fix a regression in Cglib Kotlin proxies
The commit skips using UndeclaredThrowableStrategy for
Kotlin classes in CglibAopProxy in order to fix a
related regression caused by gh-32469.

See gh-33585
2024-10-03 19:49:59 +02:00
Sam Brannen 02094b258c Destroy singleton instead of removing and re-registering bean definition 2024-10-03 16:43:59 +02:00
Sam Brannen 39a27256a7 Reduce scope of BeanDefinitionRegistry usage in Bean Override BFPP 2024-10-03 16:39:43 +02:00
Sam Brannen f26a266c41 Optimize BeanOverrideRegistrar lookup in BeanOverrideTestExecutionListener 2024-10-03 16:39:43 +02:00
Sam Brannen d44701f828 Extract WrapEarlyBeanPostProcessor to top-level class 2024-10-03 16:39:43 +02:00
Sam Brannen 4c3bc3ba69 Emulate AbstractAotProcessor.process() in AotIntegrationTests 2024-10-03 16:39:43 +02:00
Simon Baslé 6c5e63e446 Merge branch '6.1.x' 2024-10-03 16:33:40 +02:00
Simon Baslé b54420f8aa Include argument name in MethodArgumentTypeMismatchException message
Closes gh-33573
2024-10-03 16:32:29 +02:00
Sam Brannen 32309e86ce Fix context caching for Bean Overrides w/ different annotation order
Prior to this commit, ApplicationContext caching support was broken if
two Bean Override fields declared the same annotations but in a
different order.

This commit fixes that by switching to Set semantics for the
annotations declared on a Bean Override field.

Closes gh-33633
2024-10-02 11:23:48 +02:00
Brian Clozel 8cd2c40860 Improve random source in SockJS server support
Prior to this commit, the SockJs server support would use
`java.util.Random` to send a random value to clients when they request
the `/info` endpoint. Per protocol, clients can use this value as a
source of entropy for generating a random session id.

In practice, this is not used by clients. For example, the SockJS
javascript client is using a cryptographically safe API to generate
session ids.

While this has no concrete effect on known clients, this commit improves
the random source in the server support by switching to
`java.security.SecureRandom`.

Closes gh-33632
2024-10-01 21:29:19 +02:00
Sam Brannen 309897497a Update copyright header 2024-10-01 12:35:01 +02:00
Hyunwoo Kim 893f5dcb9b Replace "null" with NULL_STRING constant in ObjectUtils.nullSafeConciseToString()
Closes gh-33625
2024-10-01 12:33:40 +02:00
Sam Brannen a21c557101 Do not replace existing Bean Override definition with pseudo-definition
Prior to this commit, BeanOverrideBeanFactoryPostProcessor replaced
existing bean definitions with "pseudo" bean definitions; however, that
is unnecessary. An existing BeanDefinition is suitable as-is and does
not need to be replaced with a pseudo/fake definition.

To address that, this commit reregisters an existing bean definition
and only registers a new bean definition when creating a bean
definition for a nonexistent bean.

As a side effect, we no longer need to copy primary and fallback flags.

Closes gh-33627
2024-10-01 12:20:27 +02:00
Sébastien Deleuze 56a0a33e5d Add a missing test case for ObjectUtils#unwrapOptional
Closes gh-33618
2024-10-01 09:42:58 +02:00
Tran Ngoc Nhan 4d87c77649 Add test cases for ObjectUtils#unwrapOptional
See gh-33618
2024-10-01 09:41:39 +02:00
SungbinYang fc8bd64f34 Simplify ObjectUtils#unwrapOptional
This commit replaces optional.isEmpty() and optional.get() with
optional.orElse(null) for better efficiency and readability.

Closes gh-33612
2024-09-30 18:32:43 +02:00
Sam Brannen 1c87e4795d Introduce enforceOverride flag in @⁠TestBean and @⁠MockitoBean
Prior to this commit, @⁠MockitoBean could be used to either create or
replace a bean definition, but @⁠TestBean could only be used to replace
a bean definition.

However, Bean Override implementations should require the presence of
an existing bean definition by default (i.e. literally "override" by
default), while giving the user the option to have a new bean
definition created if desired.

To address that, this commit introduces a new `enforceOverride`
attribute in @⁠TestBean and @⁠MockitoBean that defaults to true but
allows the user to decide if it's OK to create a bean for a nonexistent
bean definition.

Closes gh-33613
2024-09-30 14:32:53 +02:00
Juergen Hoeller 30dc86810e Upgrade to Jackson 2.18
Closes gh-33615
2024-09-30 13:53:22 +02:00
Sam Brannen 38c9af2385 Merge branch '6.1.x' 2024-09-30 12:42:17 +02:00
Sam Brannen 0b3b1391c1 Avoid usage of deprecated AssertJ feature 2024-09-30 12:41:35 +02:00
Johnny Lim 64daba34de Upgrade to Awaitility 4.2.2
See gh-33143
Closes gh-33604
2024-09-30 12:36:54 +02:00
Juergen Hoeller b59d0a396e Add equals/hashCode methods to ServerSentEvent
Closes gh-33606
2024-09-30 11:22:43 +02:00
Juergen Hoeller 8ab965c981 Merge branch '6.1.x'
# Conflicts:
#	spring-web/src/main/java/org/springframework/web/method/annotation/AbstractNamedValueMethodArgumentResolver.java
#	spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractNamedValueArgumentResolver.java
2024-09-30 11:17:55 +02:00
Juergen Hoeller 87157d3200 Polishing 2024-09-30 11:13:50 +02:00
Juergen Hoeller 95f181352f Defensively check MethodParameter.getMethod() in KotlinDelegate
Closes gh-33609
2024-09-30 11:13:26 +02:00
Simon Baslé 854f6ffd39 Merge branch '6.1.x' 2024-09-30 10:19:36 +02:00
Simon Baslé e32a2f339d Propagate method error in some cases of reactive findInCaches errors
In a Cacheable reactive method, if an exception is propagated from
both the method and the caching infrastructure, an NPE could previously
surface due to the `CacheAspectSupport` attempting to perform an
`onErrorResume` with a `null`. This change ensures that in such a case
the user-level exception from the method is propagated instead.

Closes gh-33492
2024-09-30 10:18:59 +02:00
Sam Brannen d79258ac73 Reject non-singletons in Test Bean Override support
Prior to this commit, a non-singleton FactoryBean was silently replaced
by a singleton bean. In addition, bean definitions for prototype-scoped
and custom-scoped beans were replaced by singleton bean definitions
that were incapable of creating the desired bean instance. For example,
if the bean type of the original bean definition was a concrete class,
an attempt was made to invoke the default constructor which either
succeeded with undesirable results or failed with an exception if the
bean type did not have a default constructor. If the bean type of the
original bean definition was an interface or a FactoryBean that claimed
to create a bean of a certain interface type, an attempt was made to
instantiate the interface which always failed with a
BeanCreationException.

To address the aforementioned issues, this commit reworks the logic in
BeanOverrideBeanFactoryPostProcessor so that an exception is thrown
whenever an attempt is made to override a non-singleton bean.

Closes gh-33602
2024-09-29 18:12:00 +02:00
Sam Brannen 4e9b503055 Polish OverrideMetadata 2024-09-29 18:02:09 +02:00
Sam Brannen ba1d01d9b7 Add missing final declaration to OverrideMetadata.getBeanName() 2024-09-29 16:31:20 +02:00
Sam Brannen 5c08f81d80 Polishing 2024-09-29 16:28:06 +02:00
Sam Brannen 625614a4d2 Stop "collecting" annotations in MockitoAnnotationDetector
There is no need to collect/track the actual annotations. Rather, we
only need to know if there is at least once such annotation present.
2024-09-29 15:34:40 +02:00
Sam Brannen 40ca83dfd4 Revise Bean Override internals and Javadoc 2024-09-28 17:13:24 +02:00
Juergen Hoeller 56f3a48879 Merge branch '6.1.x'
# Conflicts:
#	spring-context/src/main/java/org/springframework/context/aot/AbstractAotProcessor.java
2024-09-27 19:17:32 +02:00
Juergen Hoeller 9f4968ed05 Polishing 2024-09-27 19:16:12 +02:00
Juergen Hoeller b6cfa2db0b Refine warn log message with advisor and ROLE_INFRASTRUCTURE hints
Closes gh-33184
2024-09-27 19:16:05 +02:00
Sébastien Deleuze 8e3846991d Reuse NoTransactionInContextException instances
New NoTransactionInContextException instances are created frequently in
TransactionContextManager#currentContext() when there is no transaction,
we could reuse the same instance instead to reduce the GC pressure.

Closes gh-33601
2024-09-27 17:45:02 +02:00
Sam Brannen bed3025274 Restructure BeanOverrideBeanFactoryPostProcessor and improve documentation 2024-09-27 17:08:08 +02:00
Sam Brannen ea8b8ae910 Polishing 2024-09-27 17:03:49 +02:00
Sam Brannen 9c746905bc Test status quo for Bean Override singleton semantics
The tests introduced in this commit reveal the following issues in our
Bean Override support.

- If a FactoryBean signals it does not manage a singleton, the Bean
  Override support silently replaces it with a singleton.

- An attempt to override a prototype-scoped bean or a bean configured
  with a custom scope results in one of the following.

  - If the bean type of the original bean definition is a concrete
    class, an attempt will be made to invoke the default constructor
    which will either succeed with undesirable results or fail with an
    exception if the bean type does not have a default constructor.

  - If the bean type of the original bean definition is an interface or
    a FactoryBean that claims to create a bean of a certain interface
    type, an attempt will be made to instantiate the interface which
    will always fail with a BeanCreationException.
2024-09-27 15:42:12 +02:00
Sam Brannen c3ff6cf319 Reverse engineer documentation for Bean Override internals 2024-09-27 15:39:35 +02:00
Sam Brannen ded5c13e19 Reinstate BeanOverrideTestSuite 2024-09-27 13:48:56 +02:00
Juergen Hoeller 594ed95f3c Replace transaction isolation synchronization with ReentrantLock
Closes gh-33546
2024-09-27 11:36:21 +02:00
Juergen Hoeller 8680c43368 Check for advisor-introduced interfaces specifically
See gh-31304
2024-09-27 11:07:11 +02:00
Juergen Hoeller d3dd01e227 Adapt transactional test component declaration
See gh-33470
2024-09-27 11:06:30 +02:00
오영택 cc3948e14c feat: Implemented to throw a runtime error if a class has @Transactional 2024-09-27 10:59:52 +02:00
Tran Ngoc Nhan e3cf23d15a remove unused keyword 2024-09-26 21:49:22 +02:00
Juergen Hoeller 07d281c6d8 Expose public constant for spring.aot.processing system property
Closes gh-33388
2024-09-26 18:31:36 +02:00
Juergen Hoeller 5326640f79 Initialize application context with initializer-given ServletContext
Closes gh-22319
2024-09-26 18:31:02 +02:00
Juergen Hoeller 13b49d41c3 Merge branch '6.1.x' 2024-09-26 15:30:39 +02:00
Juergen Hoeller 26054d1ab0 Fix TargetSource setup for valid proxy interface specification
See gh-31304
2024-09-26 15:26:31 +02:00
Juergen Hoeller 552a5cde36 Create CGLIB proxy in case of no target interfaces (just introductions)
Closes gh-31304
2024-09-26 14:48:42 +02:00
Yanming Zhou 8941e2876e Replace 'e.g.' with 'for example' in documentation and comments
Closes gh-33515
2024-09-26 14:11:17 +02:00
Sam Brannen e55fe9077f Make DynamicPropertyRegistrarBeanInitializer public
In order to allow third parties (for example, Spring Boot) to ensure
that a DynamicPropertyRegistrarBeanInitializer has been registered in
an ApplicationContext which has not been customized by the
DynamicPropertiesContextCustomizer, this commit converts
DynamicPropertyRegistrarBeanInitializer to a public API for use in such
special use cases.

Closes gh-33593
2024-09-26 13:01:57 +02:00
Sam Brannen b4bfb8952c Polishing 2024-09-26 12:18:57 +02:00
Sam Brannen 8e85dd0673 Fix error message for XML qualifier 'attribute' tag 2024-09-26 12:11:27 +02:00
Sam Brannen b943bdeec2 Polishing 2024-09-25 17:28:47 +02:00
rstoyanchev dea4f71846 Update contribution
Closes gh-33090
2024-09-25 16:09:01 +01:00
cfredri4 883f123583 Use only one timeout in JdkClientHttpRequest
Previously, a timeout was set both on HttpRequest, and used on
httpClient.sendAsync().get(). This leads to inconsistent behaviour
depending on which timeout gets triggered first.

See gh-33090
2024-09-25 16:09:01 +01:00
Juergen Hoeller 073cfd405b Merge branch '6.1.x' 2024-09-25 14:24:35 +02:00
Juergen Hoeller f2b522211f Upgrade to Groovy 4.0.23 2024-09-25 14:23:23 +02:00
Juergen Hoeller 49da92b6a3 Avoid http URL String (making checkstyleNohttp happy)
See gh-33561
2024-09-25 13:53:34 +02:00
Juergen Hoeller 885f650911 Merge branch '6.1.x' 2024-09-25 12:46:37 +02:00
Juergen Hoeller daa109e2ec Preserve URLStreamHandler in toRelativeURL and convertClassLoaderURL
Closes gh-33561
See gh-33199
2024-09-25 12:45:34 +02:00
Juergen Hoeller ca0448260f Convert DateTimeException to expected IllegalArgumentException
Closes gh-33545
2024-09-25 12:45:20 +02:00
rstoyanchev 7051cddcf7 Align OutputStreamPublisher's
Align internal handling and contracts. The core copy could do without
those contracts, but it helps with alignment, and it's internal to
the implementation.

Closes gh-33592
2024-09-25 11:42:26 +01:00
rstoyanchev f6c31bb6c3 Align OutputStreamPublisher's
Update constructors to match and drop unnecessary factory methods.

See gh-33592
2024-09-25 11:42:26 +01:00
rstoyanchev 113b430fab Align OutputStreamPublisher's
Apply recent nullability changes, and formatting differences.

See gh-33592
2024-09-25 11:42:26 +01:00
Sébastien Deleuze a1613d1352 Merge branch '6.1.x' 2024-09-25 12:15:06 +02:00
Sébastien Deleuze 2ab0101b8a Add coroutine context tests for WebClientExtensions
Closes gh-33548
2024-09-25 12:14:50 +02:00
Illia Sorokoumov 478aa250a0 Preserve coroutine context in WebClientExtensions
See gh-33548
2024-09-25 11:46:30 +02:00
Sam Brannen 17f319b957 Upgrade to JUnit 5.11.1 2024-09-25 11:33:29 +02:00
Juergen Hoeller 8cfd6aed04 Separate internal ScheduledExecutorService for fixed-delay tasks
Closes gh-33408
2024-09-25 10:04:17 +02:00
Sébastien Deleuze 81a66a0334 Add an AbstractGenericHttpMessageConverter constructor
This commit adds a new
AbstractGenericHttpMessageConverter(Charset, MediaType...)
constructor, similar to the one present in
AbstractHttpMessageConverter.

Closes gh-33563
2024-09-24 19:40:15 +02:00
Juergen Hoeller 5f6b8d5582 Polishing 2024-09-24 18:59:17 +02:00
Juergen Hoeller d6e4bd7c90 Resolve AOT factory method target by bean name and reduce reflective method exposure
Includes consistent withShortcut naming and consistent bean definition flag exposure.
Removes support for inner classes in alignment with standard core container behavior.

Closes gh-32834
2024-09-24 18:59:08 +02:00
Sam Brannen aef5143642 Merge branch '6.1.x' 2024-09-24 16:50:12 +02:00
Sam Brannen 5cc4d0a2ca Do not invoke AotTestExecutionListener for @⁠DisabledInAotMode tests
Closes gh-33589
2024-09-24 16:47:48 +02:00
Sam Brannen 6da114054e Update comment 2024-09-24 15:49:35 +02:00
Sam Brannen 23528a5075 Merge branch '6.1.x' 2024-09-24 15:48:08 +02:00
Sam Brannen 602ac903ff Upgrade to JUnit 5.10.4 2024-09-24 15:39:53 +02:00
Sam Brannen dae871b5d3 Clean up warnings in Gradle build 2024-09-24 12:34:20 +02:00
Sam Brannen f6fcf15745 Merge branch '6.1.x' 2024-09-24 12:33:58 +02:00
Sam Brannen af3a26ab06 Clean up warnings in Gradle build 2024-09-24 12:33:35 +02:00
Sam Brannen 66a518abd5 Merge branch '6.1.x' 2024-09-24 12:23:47 +02:00
Sam Brannen 1cecf52883 Upgrade to Apache HttpCore Reactive 5.3
Closes gh-33588
2024-09-24 12:21:50 +02:00
Sam Brannen 88905ea20d Upgrade to Apache HttpClient 5.4
This commit also updates the external Javadoc link to avoid the following
warning in the build.

URL https://hc.apache.org/httpcomponents-client-5.2.x/current/httpclient5/apidocs/package-list was redirected to https://hc.apache.org/httpcomponents-client-5.4.x/current/httpclient5/apidocs/package-list

Closes gh-33587
2024-09-24 12:20:44 +02:00
Sam Brannen 6a9b5d21f4 Document that TestContextAnnotationUtils is required for @⁠Nested support
Closes gh-33586
2024-09-24 11:55:44 +02:00
Simon Baslé f7aa4409bb Merge branch '6.1.x' 2024-09-24 11:01:57 +02:00
Simon Baslé 7df9db3bb7 Polishing test
Assert that BlockHound doesn't trigger, rather than assertions on a
condition that makes the test flakky because concurrency is involved.
2024-09-24 11:01:37 +02:00
Sam Brannen 5bc2ff70b5 Merge branch '6.1.x' 2024-09-24 10:47:14 +02:00
Sam Brannen bd9c05a909 Upgrade to Gradle 8.10.2
Closes gh-33584
2024-09-24 10:46:58 +02:00
Sam Brannen 28dbcb2421 Improve FactoryBean Javadoc 2024-09-23 17:20:19 +02:00
Tran Ngoc Nhan c85050eb43 Consistently use CharSequence.isEmpty() for emptiness checks
Closes gh-33577
2024-09-23 17:10:21 +02:00
Sam Brannen f321ef9ec2 Improve toString() for AbstractBeanDefinition and BeanMetadataAttribute
Closes gh-33579
2024-09-23 16:45:56 +02:00
Sam Brannen 59eaed0b28 Ensure integration tests are suitable for AOT processing 2024-09-23 16:45:56 +02:00
Sam Brannen 7d99790c34 Polishing 2024-09-23 16:45:56 +02:00
rstoyanchev c6fa180602 Extract shared resource handling utility methods
Closes: gh-33574
2024-09-20 19:25:12 +01:00
Juergen Hoeller df5489b81a Introduce optionalValue() method on ResultQuerySpec
Closes gh-33560
2024-09-20 19:16:02 +02:00
Yanming Zhou 24a8f1b26d AnnotatedBeanDefinitionReader should respect @Fallback qualifier analogous to @Primary
Also add tests to cover qualifier classes.
2024-09-20 19:10:16 +02:00
Johnny Lim 159e23730c Fix Javadoc @⁠since tags in JettyCoreRequestUpgradeStrategy
See gh-32097
Closes gh-33569
2024-09-20 11:34:39 +02:00
Sam Brannen 8931b75b95 Polishing 2024-09-20 10:58:37 +02:00
Johnny Lim 3ba9d35e22 Polish
Closes gh-33566
2024-09-20 10:58:37 +02:00
rstoyanchev 6120076437 Merge branch '6.1.x' 2024-09-20 09:33:09 +01:00
Andrey Popov 94c04821ff Use correct method to check encoded resource path
Closes: gh-33568
2024-09-20 09:32:24 +01:00
rstoyanchev 4706ebc81e Minor refactoring in UrlHandlerFilter
See gh-33565
2024-09-19 11:55:53 +01:00
rstoyanchev 2090ece62a UrlHandlerFilter ignores trailing slash in contextPath
Closes gh-33565
2024-09-19 11:55:25 +01:00
Sam Brannen e587753b1d Introduce @⁠EasyMockBean bean override example
This commit introduces example support for a custom @⁠EasyMockBean
annotation that allows tests to use EasyMock as the mocking framework
for bean overrides in a test's ApplicationContext.

The point of this exercise is to ensure that it is possible for third
parties to introduce bean override support for mocking frameworks other
than Mockito, and that they can do so with the APIs currently in place.

Closes gh-33562
2024-09-18 17:10:06 +02:00
Sam Brannen 6c2cba5d8a Polish bean override internals 2024-09-18 14:22:15 +02:00
Simon Baslé c832d5f496 Polishing contribution
Fixes gh-33556
2024-09-18 11:44:29 +02:00
Carl Magnuson 453e7961a8 Add read timeout setter on HttpComponentsClientHttpRequestFactory
This commit adds support for HttpComponentsClientHttpRequestFactory to
set a read timeout, used on the underlying client as a RequestTimeout.

This brings the HttpComponentsClientHttpRequestFactory into alignment
with JDK, Jetty, OkHttp3, Reactor and SimpleClient
ClientHttpRequestFactory implementations.

See gh-33556
2024-09-18 11:44:29 +02:00
Brian Clozel 6f09c21f05 Merge branch '6.1.x' 2024-09-18 11:21:03 +02:00
Brian Clozel 776811bdb8 Defer ExchangeFilterFunction execution in WebClient
Prior to this commit, the `DefaultWebClient` would execute the configured
`ExchangeFilterFunction` as the reactive pipeline is assembled during
subscription. This means that if imperative code is executed in a filter
function, it won't be aware of the current observation through the local
scope.

For example, when automatic context propagation is enabled for Reactor
operators, the logger MDC will not know about the current
traceId/spanId.

This commit ensures that client filter functions execution is deferred
during the actual client exchange.

Fixes gh-33559
2024-09-18 11:18:17 +02:00
Simon Baslé 06d240b558 Merge branch '6.1.x' 2024-09-17 16:42:09 +02:00
Simon Baslé de4ff4b44b Polishing tests
This commit adds more test coverage of SpringCoreBlockHoundIntegration.

See gh-33450
2024-09-17 16:40:40 +02:00
Simon Baslé f6e96a24d4 Add BlockHound exception for ConcurrentReferenceHashMap$ReferenceManager
This commit adds a SpringCoreBlockHoundIntegration configuration to
allows `pollForPurge` method to block.

Closes gh-33450
2024-09-17 16:40:40 +02:00
Juergen Hoeller 20bc5ef68b Accept nested array type for upUntilUnresolvable check as well
Closes gh-33535
2024-09-17 16:20:54 +02:00
Sébastien Deleuze 383fa43ded Merge branch '6.1.x' 2024-09-16 16:59:31 +02:00
Antoine Rey daea92397f Reference the spring-framework-petclinic repository
Closes gh-33539
2024-09-16 16:58:34 +02:00
Sam Brannen 13e175ab46 Avoid use of static import in production code 2024-09-16 15:50:05 +02:00
Sam Brannen b60bb44256 Polish test @⁠Configuration classes 2024-09-16 15:45:32 +02:00
Sam Brannen 31a6e98eaf Introduce @⁠Disabled AOT tests for @⁠TestBean support
See gh-32933
2024-09-16 15:43:54 +02:00
Sébastien Deleuze d3755aba06 Add RestClient.Builder#messageConverters(List)
This commit also introduces the validation of the RestClient
message converters for both variants.

Closes gh-33536
2024-09-13 16:00:38 +02:00
Brian Clozel 0a001482c3 Merge branch '6.1.x' 2024-09-13 15:53:18 +02:00
Brian Clozel 5efb385e64 Read Expires cookie attribute in HttpComponents connector
Prior to this commit, the HttpComponents implementation for the
`WebClient` would only consider the max-age attribute of response
cookies when parsing the response. This is not aligned with other client
implementations that consider the max-age attribute first, and then the
expires if the former was not present. The expires date is then
translated into a max-age duration. This behavior is done naturally by
several implementations.

This commit updates the `HttpComponentsClientHttpResponse` to do the
same.

Fixes gh-33157
2024-09-13 15:49:06 +02:00
Sam Brannen 16d8df8c2f Merge branch '6.1.x' 2024-09-13 15:29:33 +02:00
Sam Brannen b388ff60dd Fix parameterized test display names and polishing 2024-09-13 15:26:56 +02:00
Sébastien Deleuze 52f0e8fb6d Refine null-safety for additional Assert methods
Closes gh-33530
2024-09-13 14:47:00 +02:00
Brian Clozel 598580020e Merge branch '6.1.x' 2024-09-13 10:21:43 +02:00
Brian Clozel 412f5f677b Fix NPEs in MimeMessageHelper when adding files without names
Prior to this commit, `MimeMessageHelper` would accept `Resource`
instances as inline attachments in multipart MIME messages. If the
provided `Resource` implementation returns `null` for `getFileName()`,
the `addInLine` method would fail with a `NullPointerException` as
Jakarta activation fails to detect the content type for a null filename.

This commit falls back on "application/octet-stream" when the filename
is not known for the given resource instead of failing with an
exception.

Fixes gh-33527
2024-09-13 10:17:58 +02:00
Brian Clozel 5838bf5888 Merge branch '6.1.x' 2024-09-13 09:33:10 +02:00
Brian Clozel 6a20987933 Add missing URI template variables in RedirectViews
Prior to this commit, the URL handler mapping would expose the matching
pattern, the path within mapping and matching URI variables as request
attributes. This was the case when the mapping would use the
`AntPathMatcher` as matching infrastructure, but not when using the
`PathPattern` variant. In this case, the map of URI variables would be
`null`. This could throw `IllegalArgumentException` when `RedirectView`
instances were relying on the presence of specific variables.

This commit ensures that URI variables are also extracted when the
`PathPatternParser` is used.

Fixes gh-33422
2024-09-13 09:28:45 +02:00
Stéphane Nicoll f6c6f7c02c Merge branch '6.1.x' 2024-09-12 14:11:13 +02:00
Stéphane Nicoll 2ae62dec8c Next development version (v6.1.14-SNAPSHOT) 2024-09-12 14:11:01 +02:00
Sam Brannen 29ffa4963c Restructure content in testing resources section 2024-09-12 13:37:58 +02:00
Sam Brannen 39e9e88932 Link to MockMvc AssertJ support from resources section 2024-09-12 13:31:13 +02:00
Sam Brannen a73b048b68 Update link to Mockito 2024-09-12 13:24:49 +02:00
Sam Brannen 129a486f52 Remove obsolete link to MockObjects.com 2024-09-12 13:23:44 +02:00
Sam Brannen d097eea3a8 Polish DynamicPropertyRegistrar documentation 2024-09-12 13:20:59 +02:00
rstoyanchev 398e5528a1 Merge branch '6.1.x' 2024-09-12 08:40:58 +01:00
rstoyanchev d86bf8b205 Align RouterFunctions resource handling
Closes: gh-33434
2024-09-12 08:33:37 +01:00
Sam Brannen 884105d469 Merge branch '6.1.x' 2024-09-11 18:08:30 +02:00
Sam Brannen c77de8a6fb Downgrade to Tomcat 10.1.28
Tomcat 10.1.29 was causing failures in spring-webflux when running a
full build.
2024-09-11 18:08:01 +02:00
Sam Brannen e7b52cf8b2 Introduce DynamicPropertyRegistrar to replace DynamicPropertyRegistry bean
Spring Boot's testing support registers a DynamicPropertyRegistry as a
bean in the ApplicationContext, which conflicts with the
DynamicPropertyRegistry registered as a bean by the Spring TestContext
Framework (TCF) since Spring Framework 6.2 M2.

To avoid that conflict and to improve the user experience for Spring's
testing support, this commit introduces a DynamicPropertyRegistrar API
to replace the DynamicPropertyRegistry bean support.

Specifically, the TCF no longer registers a DynamicPropertyRegistry as
a bean in the ApplicationContext.

Instead, users can now register custom implementations of
DynamicPropertyRegistrar as beans in the ApplicationContext, and the
DynamicPropertiesContextCustomizer now registers a
DynamicPropertyRegistrarBeanInitializer which eagerly initializes
DynamicPropertyRegistrar beans and invokes their accept() methods with
an appropriate DynamicPropertyRegistry.

In addition, a singleton DynamicValuesPropertySource is created and
registered with the Environment for use in
DynamicPropertiesContextCustomizer and
DynamicPropertyRegistrarBeanInitializer, which allows
@⁠DynamicPropertySource methods and DynamicPropertyRegistrar beans to
transparently populate the same DynamicValuesPropertySource.

Closes gh-33501
2024-09-11 17:42:04 +02:00
Juergen Hoeller 78028cde05 Upgrade to Mockito 5.13 (depends on JUnit 5.11)
See gh-33395
2024-09-11 17:20:01 +02:00
Juergen Hoeller e9f9a7ae8e Merge branch '6.1.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
2024-09-11 17:17:38 +02:00
Juergen Hoeller 4e49f67ec5 Upgrade to SLF4J 2.0.16, Tomcat 10.1.29, Jetty 12.0.13, Netty 4.1.113, Undertow 2.3.17, AssertJ 3.26.3, Checkstyle 10.18.1 2024-09-11 17:16:14 +02:00
Juergen Hoeller 54dbb9f52a Upgrade to Objenesis 3.4
Closes gh-33526
2024-09-11 17:15:37 +02:00
Juergen Hoeller 042346aa6a Harmonize Reactor client class names within the http.client package
Closes gh-33382
2024-09-11 16:27:56 +02:00
Juergen Hoeller e9e5fee149 Consistently resolve exceptions for resources and handler functions
Closes gh-33381
2024-09-11 15:51:01 +02:00
Juergen Hoeller a044357c31 Apply lenient locking fallback to singleton pre-instantiation phase only
Closes gh-33463
2024-09-11 14:09:57 +02:00
rstoyanchev 1ff2678147 Add UrlHandlerFilter for WebFlux
Closes gh-32830
2024-09-11 11:51:21 +01:00
rstoyanchev 5671744a94 Refactoring in UrlHandlerFilterTests 2024-09-11 11:51:21 +01:00
Patrick Strawderman 7827188e8e Avoid empty array allocations in AnnotationTypeMapping
Closes gh-33507
2024-09-11 09:49:39 +02:00
Brian Clozel 2b9b581024 Add streaming support to MVC functional endpoints
Prior to this commit, MVC function endpoints would allow Server Sent
Event responses through `ServerResponse.sse()`. While this covers a
common use case for streaming responses, other technologies would
benefit from a "low-level", unopinionated streaming support.

This commit introduces a new `BodyBuilder.stream()` methods that enables
such use cases. Developers are in charge of setting the relevant HTTP
response headers beforehand, and then can write to the response as raw
`String`, `byte[]` or using complex objects and the configured message
converters for serialization.

Because each streaming protocol has different message separator
semantics, it is also the developers' responsibility to flush buffered
content to the network once a message has been fully written.

Closes gh-32710
2024-09-10 15:41:21 +02:00
Stéphane Nicoll 6c8a859937 Merge branch '6.1.x' 2024-09-10 15:21:17 +02:00
Stéphane Nicoll 0fec2cf17a Upgrade to Reactor 2024.0.0-M6
Closes gh-33521
2024-09-10 15:10:59 +02:00
Stéphane Nicoll f1f69544b7 Upgrade to Micrometer 1.14.0-M3
Closes gh-33520
2024-09-10 15:10:12 +02:00
Stéphane Nicoll 34f649c3f5 Upgrade to Reactor 2023.0.10
Closes gh-33519
2024-09-10 15:05:08 +02:00
Stéphane Nicoll 5b01f31387 Upgrade to Micrometer 1.12.10
Closes gh-33518
2024-09-10 15:04:42 +02:00
rstoyanchev 88ff5e1dcc Remove unused imports 2024-09-10 13:36:16 +01:00
rstoyanchev ebef599146 Fix checkstyle violations 2024-09-10 13:05:57 +01:00
rstoyanchev 9d57c0ba89 Add compare method to ETag
Closes gh-33385
2024-09-10 12:29:33 +01:00
rstoyanchev 19700d07b1 Quote ETag if not quoted in HttpHeaders#setETag
This aligns HttpHeaders with other places like ServletWebRequest and
DefaultWebExchange where an ETag is accepted as input.

It also allows us to remove quoting from places that delegate to
HttpHeaders#setETag since it now does that internally.

Closes gh-33412
2024-09-10 09:17:56 +01:00
rstoyanchev 3dd4a8350a Update more places to use quoteETagIfNecessary
Closes gh-33412
2024-09-10 08:56:03 +01:00
rstoyanchev 1b26122e64 Polishing and minor refactoring
Update checks whether quoting is needed to be more complete
than what we've used so far, making sure the there is both
opening and closing quotes independent of each other.

See gh-33412
2024-09-10 08:56:01 +01:00
hyunmin0317 80b264ba82 Refactor eTag formatting into utility method
See gh-33412
2024-09-10 08:55:39 +01:00
Sébastien Deleuze cc3f4b87ff Update mime.types
This commit updates mime.types based on revision 1918129 of
https://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types.

Closes gh-33512
2024-09-09 19:23:57 +02:00
Sébastien Deleuze 413cbca2c0 Remove commented entries from mime.types
See gh-33512
2024-09-09 18:59:29 +02:00
Sébastien Deleuze b0b5fcea0e Merge branch '6.1.x' 2024-09-09 18:44:22 +02:00
Sébastien Deleuze 9150c81d92 Document fixed rate scheduling with CRaC
Closes gh-33490
2024-09-09 18:43:55 +02:00
Sam Brannen eff19ec972 Sync MockHttpServletRequest implementations 2024-09-09 15:42:21 +02:00
Sam Brannen d5f1e055d5 Merge branch '6.1.x' 2024-09-09 15:35:36 +02:00
Sam Brannen 4e1756d738 Polishing 2024-09-09 15:34:00 +02:00
Stéphane Nicoll e311d9848a Expose the uriTemplate used to build a MockHttpServletRequest
This commit exposes the unexpanded URI template used to build a
MockHttpServletRequest. This allows MockMvc users to retrieve that
information, in consistency with ExchangeResult in WebTestClient.

Closes gh-33509
2024-09-09 14:46:05 +02:00
rstoyanchev d2b25c0378 Merge branch '6.1.x' 2024-09-09 11:56:21 +01:00
rstoyanchev 5c1ab7ecd5 Polishing contribution
Closes gh-33498
2024-09-09 11:55:15 +01:00
yfoelsin 7655329463 Set status code on DefaultRenderingBuilder for RedirectView
See gh-33498
2024-09-09 11:54:50 +01:00
rstoyanchev 3d1bf28445 Refine how async request state lock is obtained
Rather than waiting indefinitely, keep checking if the state
changed from ASYNC (e.g. to ERROR).

Closes gh-33421
2024-09-09 11:54:38 +01:00
Sam Brannen 6518a56cee Revise introductory content for MockMvc 2024-09-08 17:59:15 +02:00
Sam Brannen 4fb70b671a Remove obsolete role attributes for tab groups in the reference manual
Since we now use asciidoctor-tabs instead of spring-asciidoctor-backends,
we no longer need the `role="primary"` and `role="secondary"` attributes
for tab groups.

Closes gh-33506
2024-09-08 17:20:10 +02:00
Brian Clozel 761fb8f6c9 Allow multiple listeners on ResponseBodyEmitter
Prior to this commit, `ResponseBodyEmitter` woud accept a single
`Runnable` callback on each of its `onTimeout`, `onError` or
`onCompletion` methods. This would limit the developers' ability to
register multiple sets of callbacks: one for managing the publication of
streaming values, another one for managing other concerns like
keep-alive signals to maintain the connection.

This commit now allows multiple calls to `onTimeout`, `onError` and
`onCompletion` and will register all callbacks accordingly.

Closes gh-33356
2024-09-06 15:30:18 +02:00
Patrick Strawderman 2b6639e587 Avoid storing duplicate empty array in MethodParameter field
Avoid storing duplicate empty arrays in the parameterAnnotations field of MethodParameter.

Closes gh-33496
2024-09-06 10:02:02 +02:00
Brian Clozel e9b0a19d3f Document TaskDecorator usage with TaskExecutors
Closes gh-33438
2024-09-05 21:04:22 +02:00
Sam Brannen d1920c0982 Merge branch '6.1.x' 2024-09-05 17:46:20 +02:00
Johnny Lim b7c7823315 Add @⁠since tag for CodeWarnings.detectDeprecation(ResolvableType)
See gh-32850
Closes gh-33493
2024-09-05 17:45:52 +02:00
Brian Clozel 046724b940 Document that WebFlux does not support forward redirects
Closes gh-33441
2024-09-05 16:02:42 +02:00
Sébastien Deleuze 5e3c5d466f Avoid collecting Flux elements in KotlinSerializationJsonEncoder
Closes gh-33428
2024-09-05 14:47:49 +02:00
Sam Brannen 907859f2f3 Merge branch '6.1.x' 2024-09-04 17:30:49 +02:00
Sam Brannen caaa86d6cf Make AspectJ pointcut in test more robust
The previous pointcut attempted to match against a local lambda type;
however, that pointcut was unreliable and failed sporadically.

This commit therefore changes the pointcut so that it specifically
targets the get() method of a subtype of Supplier, which seems to result
in reliable pointcut matching.
2024-09-04 17:30:16 +02:00
Sam Brannen 46655f367e Polishing 2024-09-04 17:27:01 +02:00
Sébastien Deleuze 2f56a59ba0 Merge branch '6.1.x' 2024-09-04 16:13:04 +02:00
Sébastien Deleuze 4b7292f431 Fix an off-by-one bug in ForwardedHeaderTransformer
Consistently with what is done in ForwardedHeaderFilter.

Closes gh-33465
2024-09-04 16:12:44 +02:00
Patrick Strawderman f88c314e83 Avoid empty array allocations in ResolvableType
Avoid allocating empty arrays in a few places in ResolvableType.

Closes gh-33473
2024-09-04 10:40:20 +02:00
Sébastien Deleuze daba9e55b6 Merge branch '6.1.x' 2024-09-03 20:22:12 +02:00
Sébastien Deleuze 83be0f2dac Improve documentation on reading form data
`@RequestParam` should be favored over `@RequestBody`
which can't always be used reliably due to how the Servlet
API behaves.

Closes gh-33409
2024-09-03 20:22:00 +02:00
Sam Brannen 717b972f88 Polish contribution
See gh-33452
2024-09-03 18:08:23 +02:00
Yanming Zhou 019c0b1d4e Expand acronyms FQN and FQCN
Closes gh-33452
2024-09-03 17:30:27 +02:00
Sam Brannen 529f311bd4 Polish and harmonize implementations of SpEL components in spring-context 2024-09-03 17:16:20 +02:00
Sébastien Deleuze ea8f8f77c5 Merge branch '6.1.x' 2024-09-03 15:35:03 +02:00
Sébastien Deleuze 3c2831030b Upgrade to Kotlin 1.9.25
Closes gh-33471
2024-09-03 15:34:53 +02:00
Sam Brannen 1af6480217 Revise reference documentation for Spring JMX annotations
This commit revises the reference documentation for Spring JMX
annotations for various reasons including, but not limited to, the
following.

- Type names such as ManagedResource are often ambiguous, especially
  when discussing an annotation like @⁠ManagedResource instead of
  org.springframework.jmx.export.metadata.ManagedResource which is a
  class.
- AnnotationTestBean implements IJmxTestBean, even though an annotated
  MBean is not required to implement any interfaces, and in fact the
  example is meant to demonstrate that an annotated POJO suffices.
- @⁠ManagedOperationParameter annotations are unnecessarily declared in
  the @⁠ManagedOperationParameters container.
- The documentation sometimes refers to JmxTestBean when it should
  instead refer to AnnotationTestBean.
- Inconsistent and confusing wording for annotation attributes,
  properties, managed attributes, etc.
- The tables refer to "source-level metadata types/parameters" when
  they should refer to Spring JMX annotations and their attributes.
- The annotation and attribute tables have inconsistent ordering and
  naming for column headers.
- @⁠ManagedNotification and @⁠ManagedMetric are not mentioned.
- The AutodetectCapableMBeanInfoAssembler example is broken since it
  uses the non-annotated JmxTestBean instead of the AnnotationTestBean.

As a side note, the JmxTestBean in our test suite still contains
XDoclet "annotations" which can be safely removed. 😉

Closes gh-33466
2024-09-02 18:18:10 +02:00
Johnny Lim 6e640f0800 Add Javadoc since for ReflectionHints.registerForInterfaces()
See gh-32824
Closed gh-33458
2024-09-02 16:21:35 +02:00
zhoukq aca264942d Update Content-Length if body changed by client interceptor
Prior to this commit, the HTTP interceptor model used for `RestTemplate`
and `RestClient` would not update the "Content-Length" request header,
even when the request body had been updated by a
`ClientHttpRequestInterceptor`.

Even though this is the `ClientHttpRequestInterceptor`'s responsibility
(along with the content type and encoding changes if needed), this
would result in invalid requests. This invalid situation can be detected
by `InterceptingClientHttpRequest`.

This commit ensures that such situations are detected and fixed
automatically by setting the Content-Length header to the actual body
size, right before executing the actual request, after all interceptors
are done.

Closes gh-33459
2024-09-02 16:19:26 +02:00
Brian Clozel be5d5fa52d UrlHandlerFilter should not strip slash for "/" request paths
This commit ensures that the `UrlHandlerFilter` does not handle "/"
paths in general, as they should not be altered and are meaningful for
web applications.

Closes gh-33444
2024-09-02 15:29:42 +02:00
Juergen Hoeller 69d5587f53 Merge branch '6.1.x'
# Conflicts:
#	spring-context/src/main/java/org/springframework/scheduling/annotation/Scheduled.java
2024-08-31 12:04:29 +02:00
Juergen Hoeller 1f6ab1a0c9 Polishing 2024-08-31 12:00:41 +02:00
Juergen Hoeller ce5869eeb0 Consistent test execution with Locale.UK 2024-08-31 12:00:34 +02:00
Juergen Hoeller 1db9faf248 Avoid shutdown timeout in case of exception on stop
Closes gh-33442
2024-08-31 12:00:26 +02:00
Juergen Hoeller 5d80d75051 Follow symlinks during root path traversal
Closes gh-33424
2024-08-31 12:00:14 +02:00
Brian Clozel 52c4ffa4d2 Merge branch '6.1.x' 2024-08-30 21:23:29 +02:00
Brian Clozel debba6545b Listen to multiple async operations in ServerHttpObservationFilter
Prior to this commit, the `ServerHttpObservationFilter` was fixed to
re-enable instrumentation for async dispatches. This fix involves using
an AsyncListener to be notified of exchange completion.

This change was incomplete, as this would not work in some cases.
If another filter starts the async mode and initiates an ASYNC dispatch,
before async handling at the controller level, the async listener is not
registered against subsequent async starts.

This commit not only ensures that the async listener registers
against new async starts, but also ensure that the initial creation and
registration only happens during the initial REQUEST dispatch.

Fixes gh-33451
2024-08-30 20:09:21 +02:00
Brian Clozel fab889009a Support multiple async starts in MockHttpServletRequest
Closes gh-33457
2024-08-30 20:08:36 +02:00
Sam Brannen 940eef0646 Merge branch '6.1.x' 2024-08-30 19:09:38 +02:00
Sam Brannen 5927b70dfe Update information in SpEL Evaluation chapter in reference manual
This commit updates the Evaluation chapter to reflect the following.

- SimpleEvaluationContext no longer has a create() method. Instead it
  has forPropertyAccessors(), forReadOnlyDataBinding(), and
  forReadWriteDataBinding() factory methods.

- SpEL cannot automatically create missing array elements or grow the
  size of an array like it can for a collection.

Closes gh-33456
2024-08-30 19:06:35 +02:00
Sam Brannen ba64d0fae6 Fix titles for Java tabs in Testing chapter of reference manual 2024-08-30 17:13:14 +02:00
Sam Brannen 72f912549d Revise AOP proxying section of the reference manual
This commit revises the AOP proxying section as follows.

- Documents all limitations of CGLIB-based proxies
- Documents self injection as alternative to AopContext.currentProxy()
- Avoids use of flippant language

See gh-33454
Closes gh-33455
2024-08-30 16:05:15 +02:00
Sam Brannen 5e1de19ba3 Consolidate self injection documentation in the reference manual
Closes gh-33454
2024-08-30 15:47:54 +02:00
Sam Brannen a19acc65b4 Merge branch '6.1.x' 2024-08-30 11:24:59 +02:00
Sam Brannen dca55236c4 Stop documenting use of -debug compiler flag in reference manual
Closes gh-33453
2024-08-30 11:24:39 +02:00
Sam Brannen 167cb5d494 Polishing 2024-08-29 17:02:08 +02:00
Sam Brannen 2ddf495802 Delete unused method and polish formatting 2024-08-29 16:53:49 +02:00
Sam Brannen a2b7b1c8af Merge branch '6.1.x' 2024-08-29 16:30:26 +02:00
Sam Brannen 61b5b1edd8 Fix example for @⁠ImportResource in the reference manual
Prior to this commit, the main() method attempted to retrieve a
TransferService bean from the context, but no such bean had been
configured in the context.

This commit addresses that by configuring a TransferService bean in the
context.

Closes gh-33446
2024-08-29 16:29:30 +02:00
Sam Brannen 22abcf9aef Update examples to use Environment#matchesProfiles() 2024-08-29 16:25:04 +02:00
Sam Brannen 4fa27197a7 Fix titles for code listings and improve wording 2024-08-29 16:06:52 +02:00
Sam Brannen 9b28e584af Merge branch '6.1.x' 2024-08-29 15:40:12 +02:00
Sam Brannen acf82e7c6d Use discrete headings instead of titled blocks in reference manual
This code switches from titled blocks to discrete headings in order to
properly format pseudo-section headers in the reference manual.

Closes gh-33447
2024-08-29 15:39:10 +02:00
Sam Brannen 29fdcf56eb Polishing 2024-08-29 15:15:26 +02:00
rstoyanchev 7aa25e083a Merge branch '6.1.x' 2024-08-28 18:59:47 +03:00
rstoyanchev 186deb777f Update deprecation notices on rawStatusCode
Mark for removal where not marked, and set to 7.0
consistently as the target for removal.

See gh-33440
2024-08-28 18:49:49 +03:00
rstoyanchev 57cb8c7abf Restore rawStatusCode methods
Revert methods removed in 7df2e2a8d2.

See gh-33440
2024-08-28 18:12:26 +03:00
Sam Brannen 5bcfcdd0be Polishing 2024-08-28 14:46:12 +02:00
Sam Brannen 38a56b3fda Unwrap CGLIB proxy when invoking non-proxied methods in ReflectionTestUtils
Prior to this commit, when ReflectionTestUtils was used to invoke a
method on a CGLIB proxy, the invocation was always performed directly
on the proxy. Consequently, if the method was not proxied/intercepted
by the CGLIB proxy -- for example, if the method was final or
effectively private -- the invoked method could not operate on the
state of the target object or interact with other private methods in
the target object.

With this commit, if the supplied target object is a CGLIB proxy which
does not intercept the method, the proxy will be unwrapped allowing the
method to be invoked directly on the ultimate target of the proxy.

Closes gh-33429
2024-08-28 14:31:24 +02:00
Sébastien Deleuze 6d1294ddad Merge branch '6.1.x' 2024-08-27 15:39:04 -07:00
Sébastien Deleuze 871539ab28 Fix a typo in the CDS documentation
Closes gh-33437
2024-08-27 15:38:56 -07:00
Sam Brannen ba774c6290 Restore behavior for ClassUtils.getInterfaceMethodIfPossible()
Commit 47f88e123f introduced support for invoking init/destroy/SpEL
methods via public types whenever possible. To achieve that,
getInterfaceMethodIfPossible() was modified so that it only returned
interface methods from public interfaces; however, we have learned that
third parties relied on the previous behavior which found any interface
method (even in non-public interfaces).

In light of the above, this commit partially reverts commit 47f88e123f
in order to reinstate getInterfaceMethodIfPossible() in non-deprecated
form with its previous behavior.

See gh-33216
2024-08-27 11:42:07 +02:00
Sam Brannen d2ea5b4448 Polish internal Javadoc 2024-08-23 11:24:22 +02:00
Sam Brannen 47f88e123f Invoke init/destroy/SpEL methods via public types whenever possible
Prior to this commit, when invoking init methods and destroy methods
for beans as well as methods within Spring Expression Language (SpEL)
expressions via reflection, we invoked them based on the "interface
method" returned from ClassUtils.getInterfaceMethodIfPossible(). That
works well for finding methods defined in an interface, but it does not
find public methods defined in a public superclass.

For example, in a SpEL expression it was previously impossible to
invoke toString() on a non-public type from a different module. This
could be seen when attempting to invoke toString() on an unmodifiable
list created by Collections.unmodifiableList(...). Doing so resulted in
an InaccessibleObjectException.

Although users can address that by adding an appropriate --add-opens
declaration, such as --add-opens java.base/java.util=ALL-UNNAMED, it is
better if applications do not have to add an --add-opens declaration
for such use cases in SpEL. The same applies to init methods and
destroy methods for beans.

This commit therefore introduces a new
getPubliclyAccessibleMethodIfPossible() method in ClassUtils which
serves as a replacement for getInterfaceMethodIfPossible().

This new method finds the first publicly accessible method in the
supplied method's type hierarchy that has a method signature equivalent
to the supplied method. If the supplied method is public and declared
in a public type, the supplied method will be returned. Otherwise, this
method recursively searches the class hierarchy and implemented
interfaces for an equivalent method that is public and declared in a
public type. If a publicly accessible equivalent method cannot be
found, the supplied method will be returned, indicating that no such
equivalent method exists.

All usage of getInterfaceMethodIfPossible() has been replaced with
getPubliclyAccessibleMethodIfPossible() in spring-beans and
spring-expression. In addition, getInterfaceMethodIfPossible() has been
marked as deprecated in favor of the new method.

As a bonus, the introduction of getPubliclyAccessibleMethodIfPossible()
allows us to delete a fair amount of obsolete code within the SpEL
infrastructure.

See gh-29857
Closes gh-33216
2024-08-22 14:35:21 +02:00
Sam Brannen cac623b3f4 Refer to the "Java Module System" instead of "Jigsaw" 2024-08-22 13:00:39 +02:00
Brian Clozel c5f51aab67 Merge branch '6.1.x' 2024-08-22 09:32:11 +02:00
alfredo-toledano aca5db817d Fix link to core container introduction in ref docs
Closes gh-33417
2024-08-22 09:30:47 +02:00
Sébastien Deleuze c71409821d Polishing
Closes gh-33402
2024-08-20 18:32:37 +02:00
dev-chpark a9cbb01a45 Rename test method to clarify its purpose
See gh-33402
2024-08-20 18:32:30 +02:00
Sam Brannen 4a099d213e Add missing @⁠TestMethodOrder declarations 2024-08-19 14:46:21 +02:00
Sam Brannen 9f0417fb33 Merge branch '6.1.x' 2024-08-19 13:58:31 +02:00
Sam Brannen b2c1f978a4 Stop logging result in WebAsyncManager
Closes gh-33406
2024-08-19 13:53:06 +02:00
Brian Clozel 96573ee5e1 Merge branch '6.1.x' 2024-08-19 11:48:36 +02:00
Brian Clozel 50be08480d Open observation scope in RestClient
Prior to this commit, the `RestClient` instrumentation would create and
close observations for HTTP requests, but would not open an observation
scope for the lifetime of the exchange.
This means that custom `ClientHttpRequestInterceptor` and
`ResponseErrorHandler` would not get access to the current observation
scope in case of tracing, possibly leading to missing trace ids in logs.

This commit ensures that an observation scope is managed for the
lifetime of the HTTP exchange.

Fixes gh-33397
2024-08-19 11:48:26 +02:00
Simon Baslé 107ae6159b Add tests for MockitoBean reset of mocks/spies from a FactoryBean
Closes gh-33405
2024-08-19 11:10:19 +02:00
Sébastien Deleuze 94d8fc7af8 Merge branch '6.1.x' 2024-08-19 10:46:54 +02:00
Sébastien Deleuze 0101945708 Prevent a leak in WebTestClient
This commit applies the same kind of processing for
Void.class element type in the ParameterizedTypeReference
variant of WebTestClient.ResponseSpec#returnResult than
in the Class variant.

Closes gh-33389
2024-08-19 10:46:47 +02:00
Sébastien Deleuze eb7a95cfdb Merge branch '6.1.x' 2024-08-19 09:47:08 +02:00
Sébastien Deleuze d41ca095ab Add native support for Kotlin default values in controllers
Closes gh-33384
2024-08-19 09:46:53 +02:00
Sam Brannen 346b6f740a Polish contribution
See gh-33401
2024-08-18 14:58:05 +02:00
tafjwr 4ffeddb099 Add tests for ControllerAdviceBean#resolveBean() and revise existing tests
Closes gh-33401
2024-08-18 14:52:05 +02:00
Sam Brannen 59c779d8fe Enforce order of Javadoc tags for records introduced in 6.2
See gh-33403
2024-08-18 13:12:47 +02:00
Sam Brannen 04271c3ead Merge branch '6.1.x' 2024-08-18 13:04:21 +02:00
Sam Brannen 143736e59b Enforce order of Javadoc tags for records
Closes gh-33403
2024-08-18 13:01:43 +02:00
Sam Brannen e50383e921 Improve Javadoc for SpEL's Expression API 2024-08-17 15:59:00 +02:00
Sébastien Deleuze f854800043 Merge branch '6.1.x' 2024-08-16 17:05:23 +02:00
Sébastien Deleuze e0cb7aa0a0 Build documentation branches only for 6.1 and later
To avoid a duplication error caused by a conflict between the
6.0.x branch and the v6.0.23 tag.

Closes gh-33398
2024-08-16 17:04:55 +02:00
Sam Brannen de33056c83 Use new features from JUnit Jupiter 5.11
This commit migrates additional parameterized tests (that were missed in
the previous commit) to the new argumentSet() feature.

See gh-33395
2024-08-16 15:48:47 +02:00
Sébastien Deleuze a9a1798012 Merge branch '6.1.x' 2024-08-16 14:37:56 +02:00
Sébastien Deleuze 46c29b9175 Support Boolean property in BindingReflectionHintsRegistrar
Closes gh-33380
2024-08-16 14:37:12 +02:00
Sam Brannen d749d2949d Use new features from JUnit Jupiter 5.11
This commit primarily migrates to the new argumentSet() feature but also
applies additional polishing to our use of parameterized tests.

See gh-33395
2024-08-16 13:48:19 +02:00
Sam Brannen 2eff5cb463 Upgrade to JUnit 5.11
Closes gh-33395
2024-08-15 18:15:15 +02:00
Stéphane Nicoll 6cc0561625 Merge branch '6.1.x' 2024-08-14 13:27:57 +02:00
Stéphane Nicoll 1634e63506 Next development version (v6.1.13-SNAPSHOT) 2024-08-14 13:27:42 +02:00
rstoyanchev 974dec262c Merge branch '6.1.x' 2024-08-14 07:33:15 +03:00
rstoyanchev bb17ad8314 Efficient ETag parsing 2024-08-14 07:19:59 +03:00
Juergen Hoeller e1cf203295 Merge branch '6.1.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
2024-08-13 19:05:20 +02:00
Juergen Hoeller 63486bf19c Upgrade to Tomcat 10.1.28, Jetty 12.0.12, Netty 4.1.112, Undertow 2.3.15 2024-08-13 18:52:15 +02:00
Juergen Hoeller d0bff584d7 Polishing 2024-08-13 18:51:02 +02:00
Juergen Hoeller 8be5010f5d LocaleEditor supports BCP 47 language tags as well
Closes gh-33348
2024-08-13 18:50:30 +02:00
Juergen Hoeller 552936627a Reject method name mismatch in case of bean name overloading
Closes gh-33330
2024-08-13 18:22:34 +02:00
Stéphane Nicoll 599fc8796b Upgrade to Reactor 2024.0.0-M5
Closes gh-33328
2024-08-13 18:07:31 +02:00
Stéphane Nicoll 57171143b9 Upgrade to Micrometer 1.14.0-M2
Closes gh-33327
2024-08-13 18:07:08 +02:00
Stéphane Nicoll 50c927b649 Merge branch '6.1.x' 2024-08-13 17:30:16 +02:00
Stéphane Nicoll 86761cd233 Upgrade to Reactor 2023.0.9
Closes gh-33326
2024-08-13 17:27:02 +02:00
Stéphane Nicoll 07cdef410e Upgrade to Micrometer 1.12.9
Closes gh-33325
2024-08-13 17:26:38 +02:00
Sam Brannen 1aea01687a Merge branch '6.1.x' 2024-08-13 17:40:13 +03:00
Sam Brannen e74406afd0 Introduce withAssignmentDisabled() option for SimpleEvaluationContext
To support additional use cases, this commit introduces a
withAssignmentDisabled() method in the Builder for
SimpleEvaluationContext.

Closes gh-33319
2024-08-13 17:26:34 +03:00
rstoyanchev 5fee796659 Merge branch '6.1.x' 2024-08-13 16:59:32 +03:00
rstoyanchev fe4fd00429 Polishing contribution
Closes gh-33374
2024-08-13 16:59:13 +03:00
Riley Park 1703b71563 Fix incorrect weak ETag assertion
See gh-33374
2024-08-13 16:31:14 +03:00
rstoyanchev cef1b7ea6d Polishing in HTTP interface argument resolvers 2024-08-12 21:01:03 +03:00
Olga Maciaszek-Sharma 51de84e148 Reject null for non-optional arguments
Closes gh-33339
2024-08-12 21:01:03 +03:00
Stéphane Nicoll 4ac4c1b868 Revert "Merge pull request #33366 from kashike"
This reverts commit a1ec7669f6, reversing
changes made to e27192e8ad.

See gh-33366
2024-08-12 17:47:35 +02:00
Sébastien Deleuze bb4a96f227 Merge branch '6.1.x' 2024-08-12 17:32:53 +02:00
Sébastien Deleuze 1911ca728d Support invoking bridged suspending functions in AopUtils
Closes gh-33045
2024-08-12 17:27:41 +02:00
Simon Baslé 4dcdd9a224 Polishing
See gh-21590
2024-08-12 15:20:37 +02:00
Simon Baslé 2eda5d7a2a Handle low-level errors for sync/flux/mono/future gets
This change adds 3 protected methods to `AbstractCacheInvoker` that wrap
additional `Cache#retrieve` and `Cache#get` calls with
`handleCacheGetError` in case the Cache call itself fails.

For example, if the cache is remote and a connection to it cannot be
established.

Closes gh-21590
2024-08-12 15:02:05 +02:00
Simon Baslé 5e72ee36e2 Merge branch '6.1.x' 2024-08-12 14:54:54 +02:00
Simon Baslé f4a73b79b8 Avoid CacheAspectSupport#findInCaches fall through to reactive handler
Prior to this commit if the return type is a CompletableFuture but a
cache get returns null, the execution falls through to the
reactiveCachingHandler.

This commit ensures that evaluation instead continues onto the next
cache (if any).

Closes gh-33371
2024-08-12 14:54:15 +02:00
Stéphane Nicoll b7ddf1b4f4 Fix typo 2024-08-12 12:18:44 +02:00
Stéphane Nicoll a1ec7669f6 Merge pull request #33366 from kashike
* pr/33366:
  Polish "Make CacheControl immutable"
  Make CacheControl immutable

Closes gh-33366
2024-08-12 11:51:10 +02:00
Stéphane Nicoll 9f22e0c2de Polish "Make CacheControl immutable"
See gh-33366
2024-08-12 11:44:17 +02:00
Riley Park c3ab9bba11 Make CacheControl immutable
See gh-33366
2024-08-12 11:28:47 +02:00
Stéphane Nicoll e27192e8ad Merge branch '6.1.x' 2024-08-12 11:02:07 +02:00
Stéphane Nicoll 289c35c829 Merge pull request #33368 from tafjwr
* pr/33368:
  Polish "Fix predicate setup in test"
  Fix predicate setup in test

Closes gh-33368
2024-08-12 11:02:02 +02:00
Stéphane Nicoll 749145be2a Polish "Fix predicate setup in test"
See gh-33368
2024-08-12 10:29:34 +02:00
tafjwr 28eece3da1 Fix predicate setup in test
See gh-33368
2024-08-12 10:29:23 +02:00
Sam Brannen 4f607b59a3 Improve document for SpEL Bean References 2024-08-10 16:44:17 +03:00
Sam Brannen eab96073da Document that SpEL expressions using bean references are not compilable
Closes gh-33363
2024-08-10 16:33:55 +03:00
Simon Baslé bf5e218b35 Add support for headers in @HttpExchange
On the client side, supports `name=value` pairs. Placeholders in values
are resolved by the `embeddedValueResolver`.
On the server side, additionally supports `name` and `!name` syntax.

Closes gh-33309
2024-08-09 18:02:16 +02:00
rstoyanchev b61eee7fb0 Support cross-parameter validation
Closes gh-33271
2024-08-09 18:53:30 +03:00
rstoyanchev 0d64c90a79 Move status/header handling into FragmentsRendering
Based on feedback from htmx-spring-boot. It's more generally useful
to process those from within DefaultFragmentsRendering rather than
in ModelAndViewMethodReturnValueHandler. That way a custom
return value handler can create a FragmentsRendering as well and
get the same result.

See gh-33194
2024-08-09 18:01:15 +03:00
Stéphane Nicoll ce5e247c3b Merge branch '6.1.x' 2024-08-09 15:52:35 +02:00
Stéphane Nicoll 2b8225f11c Polish "Sync GHA setup" 2024-08-09 15:52:27 +02:00
Stéphane Nicoll ae38c88f82 Merge branch '6.1.x' 2024-08-09 15:46:01 +02:00
Stéphane Nicoll 1e6767ac03 Sync GHA setup 2024-08-09 15:37:43 +02:00
Stéphane Nicoll ea2c441008 Merge branch '6.1.x' 2024-08-09 09:52:19 +02:00
Stéphane Nicoll 7a250aa8ea Polish
See gh-33354
2024-08-09 09:52:06 +02:00
Stéphane Nicoll bd61da12b2 Merge branch '6.1.x' 2024-08-09 09:05:12 +02:00
Stéphane Nicoll 21bc8726d6 Merge pull request #33354 from GoncaloPT
* pr/33354:
  Polish "Fix error codes in Customizing Validation Errors section"
  Fix error codes in Customizing Validation Errors section

Closes gh-33354
2024-08-09 09:04:34 +02:00
Stéphane Nicoll df7ac9b308 Polish "Fix error codes in Customizing Validation Errors section"
See gh-33354
2024-08-09 09:03:05 +02:00
Gonçalo Silva 43217bdf06 Fix error codes in Customizing Validation Errors section
See gh-33354
2024-08-09 09:02:53 +02:00
Sam Brannen f6110dda06 Polishing 2024-08-08 17:48:57 +03:00
Sam Brannen cd7c650941 Merge branch '6.1.x' 2024-08-08 17:16:19 +03:00
Robert Danczak a31945f8b6 Fix syntax error in RestClient documentation
Closes gh-33350
2024-08-08 17:15:27 +03:00
Simon Baslé d3e1e35d76 Merge branch '6.1.x' 2024-08-08 15:59:28 +02:00
Simon Baslé a0edf129eb Fix misleading statement in ReactorResourceFactory javadoc
Closes gh-33338
2024-08-08 15:26:10 +02:00
rstoyanchev e670c6b50a Documentation updates for fragment rendering
Closes gh-33195
2024-08-08 16:25:03 +03:00
rstoyanchev 0bac8d48a5 Polishing in view rendering documentation
See gh-33195
2024-08-08 16:25:03 +03:00
rstoyanchev 062c18a81d Add DataBuffer management in fragment rendering
See gh-33194
2024-08-08 16:25:03 +03:00
rstoyanchev 8e2b27e5d8 WebFlux support for SSE with multiline fragments
See gh-33194
2024-08-08 16:25:03 +03:00
rstoyanchev b734156f32 Update WebFlux fragment stream rendering
Thymeleaf has its own special handling for SSE that gets in the way
of fragment rendering. This is why we need to set the response
content-type before streaming, and then pass text/html to the
View for rendering each fragment.

See gh-33194
2024-08-08 16:25:02 +03:00
rstoyanchev f5ed1b8f6d Refactoring in ViewResolutionResultHandler
See gh-33194
2024-08-08 16:25:02 +03:00
Sam Brannen 3863b77536 Merge branch '6.1.x' 2024-08-08 14:20:56 +03:00
Sam Brannen bcffa15c7d Reinstate qualifier support for JSR-330 @⁠javax.inject.Named
This commit revises QualifierAnnotationAutowireCandidateResolver to
reinstate "qualifier" support for the legacy JSR-330
@⁠javax.inject.Named annotation.

See gh-31090
Closes gh-33345
2024-08-08 14:20:06 +03:00
Sam Brannen f9d2641fd5 Update field name to reflect switch to Jakarta 2024-08-08 13:22:00 +03:00
Sam Brannen 3b506e11a1 Polishing 2024-08-08 13:22:00 +03:00
Stéphane Nicoll 4ceefa7501 Merge branch '6.1.x' 2024-08-08 11:41:53 +02:00
Stéphane Nicoll ddee309e11 Merge pull request #33341 from pcvolkmer
* pr/33341:
  Add missing Kotlin example for expectAll()

Closes gh-33341
2024-08-08 11:41:48 +02:00
Paul-Christian Volkmer 7e4884fcfa Add missing Kotlin example for expectAll()
See gh-33341
2024-08-08 11:35:12 +02:00
Stéphane Nicoll 7d72a03427 Start building against Micrometer 1.14.0-M2 snapshots
See gh-33327
2024-08-08 10:55:14 +02:00
Stéphane Nicoll 27aa341ab0 Merge branch '6.1.x' 2024-08-08 10:47:43 +02:00
Jonatan Ivanov 38a3d18256 Start Observation before scope open for Scheduled operation
When ScheduledAnnotationReactiveSupport adds the Observation to the
context, Reactor opens a scope through the Context Propagation API.
This happens before TrackingSubscriber would start the Observation and
opening a scope without starting an Observation is invalid.

This change moves the Observation start before the scope opening.

Closes gh-33349
2024-08-08 10:46:19 +02:00
Stéphane Nicoll dbb3a9ab08 Merge branch '6.1.x' 2024-08-08 09:33:40 +02:00
Jonatan Ivanov 6c74fee5e8 Remove unnecessary error signal from DefaultRestClient
Before UnknownContentTypeException is thrown, it is added to the current
Observation but since UnknownContentTypeException is a
RestClientException, the exception is added again in one of the
catch blocks later on.

Closes gh-33347
2024-08-08 09:30:22 +02:00
Stéphane Nicoll 873c9fe0d8 Merge branch '6.1.x' 2024-08-08 09:14:30 +02:00
Jonatan Ivanov 36e84a5209 Fix RestClient instrumentation
ClientHttpResponse implements Closeable and the close method of
DefaultConvertibleClientHttpResponse also stops the current Observation.

Before this change exiting the try-with-resource block stopped the
Observation since it called close on ClientHttpResponse.
After this, there were multiple error and stop calls on the Observation
in the catch blocks after the Observation was already stopped
which is invalid.

This change reorders the flow by stopping the Observation in the
finally block (closing ClientHttpResponse) and not stopping
the Observation in any of the catch blocks.

Closes gh-33346
2024-08-08 09:11:57 +02:00
Stéphane Nicoll 67838f3ff9 Provide all counters in BatchUpdateException
This commit updates JbcTemplate#batchUpdate to provide additional
information when one batch fails. Previously, the raw
BatchUpdateException was thrown with no way to know what had completed
thus far.

This commit creates an AggregatedBatchUpdateException that wraps the
original BatchUpdateException, yet providing the counters of the batches
that ran prior to the exception. In essence, this represents the same
state as the return value of the method if no batch fails.

AggregateBatchUpdateException exposes the original BatchUpdateException
in advanced case, such as checking for a sub-class that may contain
additional information.

Closes gh-23867
2024-08-08 08:35:06 +02:00
Sam Brannen a55207e88f Add tests for read-only IndexAccessors in 6.2 2024-08-07 19:23:06 +03:00
Sam Brannen b0999641dd Merge branch '6.1.x' 2024-08-07 18:26:13 +03:00
Sam Brannen 1e97b2137b Disable class data sharing (CDS) for tests
Prior to this commit, the Gradle build output the following warning
multiple times.

OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended

Since we don't need CDS enabled for our tests, I've added `-Xshare:off`
as a JVM argument for our tests to disable CDS.

(cherry picked from commit 27985b1439)
2024-08-07 18:08:03 +03:00
Sam Brannen 5e4e530c59 Remove Java 21 classpath entries in Eclipse projects
Since the me.champeau.mrjar stores Java 21 main and test sources in
non-standard locations, and since we can only use a single JDK within
Eclipse, this commit updates `ide.gradle` to remove `java21` classpath
entries in Eclipse projects.
2024-08-07 18:02:43 +03:00
Simon Baslé 70e5af7d16 Polishing: remove unnecessary code 2024-08-07 16:57:52 +02:00
Simon Baslé 52bc3cf5aa Polishing 2024-08-07 16:43:09 +02:00
Stéphane Nicoll 25b57d4808 Merge branch '6.1.x' 2024-08-07 16:32:20 +02:00
Stéphane Nicoll 76b2d13b2c Add support for changing context path in ServletRequestPath
This commit implements modifyContextPath in ServletRequestPath and
apply the same logic of concatenating the servlet path with the
context path.

Closes gh-33251
2024-08-07 16:28:17 +02:00
Simon Baslé 71927b3487 Merge branch '6.1.x'
# Conflicts:
#	spring-context/src/main/java/org/springframework/scheduling/concurrent/SimpleAsyncTaskScheduler.java
2024-08-07 16:07:00 +02:00
Aleksey Genus 9b85a246d8 SimpleAsyncTaskScheduler stops accepting new tasks when isShutdown
This changes the criteria for simplified task rejection logging from
to be that the executor is in the shutdown phase, not fully terminated.

See gh-33334
Closes gh-33336
2024-08-07 15:58:27 +02:00
Stéphane Nicoll 313b063aef Polish 2024-08-07 15:28:52 +02:00
Simon Baslé 7052af97a6 Polish test to focus on the FactoryBean results being mocked 2024-08-07 14:57:15 +02:00
Simon Baslé 1c893e6354 Add @MockitoBeanSettings, use MockitoSession with strict stubs default
This commit changes the way the `MockitoTestExecutionListener` sets up
mockito, now using the `MockitoSession` feature. Additionally, stubbing
now defaults to a STRICT mode which can be overruled with a newly
introduced annotation: `@MockitoBeanSettings`.

Closes gh-33318
2024-08-07 14:57:15 +02:00
Stéphane Nicoll bc05474271 Merge branch '6.1.x' 2024-08-07 10:26:07 +02:00
Stéphane Nicoll 88a408474d Start building against Reactor 2024.0.0-M5 snapshots
See gh-33328
2024-08-07 10:22:53 +02:00
Stéphane Nicoll 5a99407847 Start building against Reactor 2023.0.9 snapshots
See gh-33326
2024-08-07 10:02:20 +02:00
Stéphane Nicoll 05bd246cab Start building against Micrometer 1.12.9 snapshots
See gh-33325
2024-08-07 10:01:54 +02:00
Sam Brannen a698f66c3a Merge branch '6.1.x'
# Conflicts:
#	spring-expression/src/main/java/org/springframework/expression/spel/support/SimpleEvaluationContext.java
2024-08-06 13:56:57 +03:00
Sam Brannen 0127de5a7a Enforce read-only semantics in SpEL's SimpleEvaluationContext
SimpleEvaluationContext.forReadOnlyDataBinding() documents that it
creates a SimpleEvaluationContext for read-only access to public
properties; however, prior to this commit write access was not disabled
for indexed structures when using the assignment operator, the
increment operator, or the decrement operator.

In order to better align with the documented contract for
forReadOnlyDataBinding(), this commit makes it possible to disable
assignment in general in order to enforce read-only semantics for
SpEL's SimpleEvaluationContext when created via the
forReadOnlyDataBinding() factory method. Specifically:

- This commit introduces a new isAssignmentEnabled() "default" method
  in the EvaluationContext API, which returns true by default.

- SimpleEvaluationContext overrides isAssignmentEnabled(), returning
  false if the context was created via the forReadOnlyDataBinding()
  factory method.

- The Assign, OpDec, and OpInc AST nodes -- representing the assignment
  (=), increment (++), and decrement (--) operators, respectively --
  now throw a SpelEvaluationException if assignment is disabled for the
  current EvaluationContext.

Closes gh-33319
2024-08-06 13:54:11 +03:00
Juergen Hoeller 28668d774b Enforce non-null value in requiredSingleResult/requiredUniqueResult
Closes gh-33300
2024-08-05 15:53:17 +02:00
Sam Brannen 1e804d8d4f Merge branch '6.1.x' 2024-08-05 16:37:57 +03:00
Sam Brannen fcc99a67b6 Support lists for varargs invocations in SpEL
The changes made in conjunction with gh-33013 resulted in a regression
for varargs support in SpEL expressions. Specifically, before gh-33013
one could supply a list -- for example, an "inline list" -- as the
varargs array when invoking a varargs constructor, method, or function
within a SpEL expression. However, after gh-33013 an inline list (or
collection in general) is no longer converted to an array for varargs
invocations. Instead, the list is supplied as a single argument of the
resulting varargs array which breaks applications that depend on the
previous behavior.

Although it was never intended that one could supply a collection as
the set of varargs, we concede that this is a regression in existing
behavior, and this commit therefore restores support for supplying a
java.util.List as the varargs "array".

In addition, this commit introduces the same "list to array" conversion
support for MethodHandle-based functions that accept varargs.

Note, however, that this commit does not restore support for converting
arbitrary single objects to an array for varargs invocations if the
single object is already an instance of the varargs array's component
type.

See gh-33013
Closes gh-33315
2024-08-05 16:28:11 +03:00
Sam Brannen 8afff3359b Polishing 2024-08-05 15:01:41 +03:00
rstoyanchev 622c1b9e8c WebMvc support for SSE Fragment stream
Closes gh-33194
2024-08-05 14:38:23 +03:00
rstoyanchev 184bb7c23c Polishing in ResponseBodyEmitterReturnValueHandler
See gh-33194
2024-08-05 14:38:23 +03:00
Sam Brannen f3ab3905b8 Merge branch '6.1.x' 2024-08-05 14:21:27 +03:00
Sam Brannen c57c2272a1 Throw exception for failure to set property as index in SpEL
Prior to this commit, the Indexer in the Spring Expression Language
(SpEL) silently ignored a failure to set a property via the indexed
property syntax (['<property name>'] = <new value>) – for example, if
property write access was disabled in the EvaluationContext.

This commit addresses this issue by properly throwing a
SpelEvaluationException in PropertyIndexingValueRef.setValue(Object) if
the property could not be set.

Closes gh-33310
2024-08-05 14:15:55 +03:00
Sam Brannen 8ec23a0fcc Polishing 2024-08-05 14:15:39 +03:00
Sam Brannen 74b0bb105e Merge branch '6.1.x' 2024-08-05 11:58:49 +03:00
Sam Brannen 8badae9d72 Convert primitive array to Object[] when invoking varargs method in SpEL
Prior to this commit, SpEL incorrectly wrapped a primitive array in an
Object[] array when invoking Object[] varargs methods and constructors.

This commit addresses this by updating the convertArguments(...) method
in ReflectionHelper as follows when the user supplies the varargs
already packaged in a primitive array.

- When deciding whether to convert a single element passed as varargs,
  we now check if the argument is an array that is assignable to the
  varargs array type.

- When converting an array supplied as the varargs, we convert that
  array to the varargs array type.

Closes gh-33317
2024-08-05 11:56:48 +03:00
Sam Brannen 46a4ad4a75 Merge branch '6.1.x' 2024-08-05 11:07:47 +03:00
Stéphane Nicoll 5c3f1b1741 Merge pull request #33316 from zinzoddari
* pr/33316:
  Polishing Javadoc and comment

Closes gh-33316
2024-08-05 10:06:33 +02:00
Sam Brannen 444e7eeb74 Enable test for primitive array to Object[] conversion in SpEL
See gh-33212
2024-08-05 11:05:53 +03:00
zinzo edbaf68707 Polishing Javadoc and comment
See gh-33316
2024-08-05 10:05:00 +02:00
Stéphane Nicoll 6bcffe3b4a Shorten PR jobs to 60 minutes
See gh-33302
2024-08-05 10:03:25 +02:00
Sam Brannen f4604cfab3 Merge branch '6.1.x' 2024-08-04 17:14:10 +03:00
Sam Brannen cb6a5baac5 Support conversion from primitive array to Object[] in ConversionService
Prior to this commit, the ConversionService failed to convert a primitive
array (such as int[]) to an Object[] due to an error in the logic in
ArrayToArrayConverter.

This commit addresses this by augmenting the "can bypass conversion"
check in ArrayToArrayConverter to ensure that the supplied source object
is an instance of the target type (i.e., that the source array can be
cast to the target type array without conversion).

Closes gh-33212
2024-08-04 17:13:56 +03:00
Stéphane Nicoll 776a1d45f8 Merge branch '6.1.x' 2024-08-04 09:34:38 +02:00
Stéphane Nicoll 3b2a818f1e Upgrade to Java 17.0.12 2024-08-04 09:34:13 +02:00
Stéphane Nicoll 499cf5e84c Merge pull request #33308 from benelog
* pr/33308:
  Remove duplicated "the" in Javadoc

Closes gh-33308
2024-08-03 09:54:39 +02:00
Sanghyuk Jung ca377e4854 Remove duplicated "the" in Javadoc
See gh-33308
2024-08-03 09:52:23 +02:00
Stéphane Nicoll 0a2611b22f Harmonize NoUniqueBeanDefinitionException message
This commit makes sure that the programmatic exception that is thrown
by the cache abstraction uses the same message structure as a default
message produced by NoUniqueBeanDefinitionException.

Closes gh-33305
2024-08-02 16:24:43 +02:00
Stéphane Nicoll 29dce74fcd Merge branch '6.1.x' 2024-08-02 10:57:57 +02:00
Stéphane Nicoll 84d1122190 Shorten CI and deploy snapshot jobs to 60 minutes
Closes gh-33302
2024-08-02 10:56:25 +02:00
Stéphane Nicoll 3aec39973c Polish 2024-08-02 09:16:15 +02:00
Simon Baslé 25f62c8765 Merge branch '6.1.x' 2024-08-01 16:29:52 +02:00
Simon Baslé 722dcae1b1 Fix buffer leak in MultipartParser
This change fixes a buffer leak when the MultipartParser is encountering
a body DataBuffer that only contains a boundary.

Closes gh-33094
2024-08-01 16:28:50 +02:00
Stéphane Nicoll 47780747ba Merge pull request #33298 from zinzoddari
* pr/33298:
  Polish "Improve test coverage of StringUtils"
  Improve test coverage of StringUtils

Closes gh-33298
2024-08-01 07:35:01 +02:00
Stéphane Nicoll ec9d29ea8f Polish "Improve test coverage of StringUtils"
See gh-33298
2024-08-01 07:32:41 +02:00
zinzo a2cae4c8f4 Improve test coverage of StringUtils
This commit adds tests for `trimArrayElements()` and
`delimitedListToStringArray()` in StringUtils.

See gh-33298
2024-08-01 07:23:28 +02:00
Stéphane Nicoll f63fc01d22 Merge branch '6.1.x' 2024-07-31 16:56:22 +02:00
Stéphane Nicoll 850a0de1b0 Suppress deprecated warnings for autowiring
This commit extends our handling of deprecated with AOT to autowiring.

Closes gh-33295
2024-07-31 16:51:06 +02:00
rstoyanchev 31a3119784 Add FilterRegistration's defensively
Follow-up to d2225c, which broke Boot tests because the ServletContext can
be the one of the embedded Servlet container if initializing a live server
and as well as MockMvc (e.g. via `@AutoConfigureMockMvc`).

See gh-33252
2024-07-31 14:50:08 +03:00
Simon Baslé f1a99cd968 Allow setting filename for inline elements in MimeMessageHelper
This change adds several overloads of `MimeMessageHelper#addInline`
which allow users to specify a file name for inline elements added from
an `InputStreamResource` or a `jakarta.activation.DataSource`.

Closes gh-33230
2024-07-31 11:39:16 +02:00
Stéphane Nicoll c71f98acba Merge branch '6.1.x' 2024-07-30 17:21:28 +02:00
Stéphane Nicoll 321e8a58ae Document that NoOpResponseErrorHandler is not a good fit with RestClient
Closes gh-33276
2024-07-30 17:17:39 +02:00
Simon Baslé 6174d95ba2 Add multi-unit DurationFormat.Style for duration parsing/printing
This adds the COMPOSITE style, which allows multiple segments each
similar to the SIMPLE style.

See gh-30396
Closes gh-33262
2024-07-30 16:58:42 +02:00
rstoyanchev f967f6f9f0 Update contribution
Closes gh-33220
2024-07-30 13:15:21 +03:00
Seokjae Lee 5e9308e0cb Flexible collection handling in RequestParamArgumentResolver
See gh-33220
2024-07-30 11:42:44 +03:00
rstoyanchev dbc69284c8 ResponseEntityExceptionHandler handles AsyncRequestNotUsableException
Closes gh-33225
2024-07-30 11:33:47 +03:00
rstoyanchev 5ac7e74bf2 Replace test FilterRegistration with the one in testFixtures
See gh-33252
2024-07-30 11:33:47 +03:00
rstoyanchev 24ab6f61de Add FilterRegistration to spring-web textFixtures
See gh-33252
2024-07-30 11:33:47 +03:00
rstoyanchev d2225c2140 MockMvc supports FilterRegistration filter init
Closes gh-33252
2024-07-30 11:33:47 +03:00
Brian Clozel 38453910cd Add DatabaseClient bind variant for list of parameters
Prior to this commit, the `DatabaseClient` interface would allow batch
operations for binding parameters by their names and values. Positional
parameters did not have such equivalent.

This commit adds a new `bindValues(List<?>)` method variant for adding
multiple positional arguments in a single call and avoiding allocation
overhead when the parameters count is large.

Closes gh-33274
2024-07-29 14:07:15 +02:00
Stéphane Nicoll 1f2c6c33ac Merge branch '6.1.x' 2024-07-29 11:34:12 +02:00
Stéphane Nicoll 46ba13b645 Review Caching infrastructure documentation
Closes gh-33288
2024-07-29 11:29:35 +02:00
Juergen Hoeller 7c13d55906 Merge branch '6.1.x' 2024-07-29 10:48:11 +02:00
Juergen Hoeller 9d9e621efe Defensive singleton check for non-registered bean
Closes gh-33286
2024-07-29 10:47:08 +02:00
Stéphane Nicoll 70f3b0eb91 Only register DynamicPropertySourceBeanInitializer if necessary
This commit makes sure to check first if
DynamicPropertySourceBeanInitializer has been registered before trying
to register it.

When running with AOT optimizations, the bean definition has been
contributed so there is no need to register it again when the context
customizer runs.

Closes gh-33272
2024-07-29 09:30:27 +02:00
Stéphane Nicoll 2596e29013 Refine "Add AOT/Native support"
This commit review the support for AOT by only ignoring beans that are
using an instance supplier. The Kotlin DSL has a way to register a
bean by type where all inferences should happen as usual and that was
previously ignored.

This commit no longer ignores those beans so AOT can optimize them, and
makes sure that they are not registered again when running with AOT
optimizations. This change makes it so that the order in which beans are
registered is now different when running with AOT optimizations, and
we'll have to find a solution for that.

See gh-29555
2024-07-29 09:01:57 +02:00
Brian Clozel b888f362e5 Document ControllerAdviceBean as internal usage
This commit documents `ControllerAdviceBean` as internal usage, as it is
not meant for application to manually create controller advice bean
instances.

This also refactors the existing partial implementation of the support
for creating controller advice beans "programmatically".

Closes gh-32776
2024-07-26 17:52:20 +02:00
Sam Brannen 94e2bef9a3 Merge branch '6.1.x' 2024-07-26 16:41:13 +03:00
Sam Brannen 5aa38833dd Fix XJC configuration to re-enable Eclipse IDE support
Our recent switch from the `org.unbroken-dome.xjc` plugin to the
`com.github.bjornvester.xjc` plugin resulted in errors when trying to
import Spring Framework projects into the Eclipse IDE.

This commit fixes those issues as follows.

- @wilkinsona revised the XJC configuration in `spring-oxm.gradle` to
  avoid the ConcurrentModificationException encountered when running
  `./gradlew eclipse`.

- I added a workaround in `ide.gradle` to manually remove lingering
  "main" classpath entries for sources generated by XJC.

Co-authored-by: Andy Wilkinson <andy.wilkinson@broadcom.com>

Closes gh-33264
2024-07-26 16:39:40 +03:00
Stéphane Nicoll de2335bee3 Merge branch '6.1.x' 2024-07-26 10:05:06 +02:00
Stéphane Nicoll 9aac24c18a Merge pull request #33277 from sheip9
* pr/33277:
  Polish "Fix reference to configurePathMatching in code sample"
  Fix reference to configurePathMatching in code sample

Closes gh-33277
2024-07-26 10:02:50 +02:00
Stéphane Nicoll ea665d776d Polish "Fix reference to configurePathMatching in code sample"
See gh-33277
2024-07-26 10:01:39 +02:00
sheip9 7a2fc2ff09 Fix reference to configurePathMatching in code sample
See gh-33277
2024-07-26 10:01:21 +02:00
Stéphane Nicoll fc28926c15 Merge branch '6.1.x' 2024-07-25 16:29:07 +02:00
Stéphane Nicoll 52849819de Detect deprecation on enclosing classes as well
This commit improves CodeWarnings so that it detects if an enclosing
class is deprecated. Previously, it would only consider the annotated
element itself and the enclosing element is important for a class as
it is required to refer to it.

Closes gh-33273
2024-07-25 16:28:40 +02:00
Stéphane Nicoll 65faca8236 Consistently using credentials for creating the JMSContext
This commit updates UserCredentialsConnectionFactoryAdapter to apply
the same handling of credentials for creating the JMSContext.

Closes gh-33270
2024-07-25 09:41:43 +02:00
rstoyanchev 6e55e78b22 WebFlux support for SSE Fragment stream
See gh-33194
2024-07-24 15:34:13 +01:00
rstoyanchev aa6b47bfce Polishing in FragmentsRendering
See gh-33194
2024-07-24 15:34:13 +01:00
Stéphane Nicoll 7c9bb24296 Polish 2024-07-24 13:59:06 +02:00
Stéphane Nicoll b8f9913aa1 Add AOT/Native support
This commit adds AOT/Native support for beans that are contributed by
the Kotlin DSL.

Since they use an instance supplier, such beans are now configured to
be ignored by AOT generation. They are part of the bean factory still
so any hint generation works.

This commit removes a previous attempt at fixing this issue when we
were not checking for instance suppliers. Rather than skipping the
initializr at runtime, it runs again as intended since their state
can't be stored in AOT-generated code.

Closes gh-29555
2024-07-24 13:58:36 +02:00
Stéphane Nicoll e741d6edbb Exclude bean definition from AOT processing using an attribute
This commits allows a particular bean definition to be excluded from
AOT processing using an attribute.

If BeanRegistrationAotProcessor#IGNORE_REGISTRATION_ATTRIBUTE is set
to `true`, then the bean definition is excluded. This complement the
existing BeanRegistrationExcludeFilter capability.

Closes gh-33243
2024-07-24 12:42:45 +02:00
Stéphane Nicoll bbfc3364e1 Merge branch '6.1.x' 2024-07-24 11:45:49 +02:00
Stéphane Nicoll bcdc991838 Switch to Shadow plugin fork
This commit fixes to a fork of the shadow plugin that fixes support
with recent Gradle releases.

See https://github.com/johnrengelman/shadow/pull/876
2024-07-24 11:42:54 +02:00
Stéphane Nicoll 589f17f48b Polish "Upgrade XJC processing to com.github.bjornvester.xjc"
See gh-33264
2024-07-24 11:42:25 +02:00
Sam Brannen e547313fa6 Sync MapAccessor implementations 2024-07-23 18:27:52 +03:00
Sam Brannen 4fa9781549 Ensure MapAccessor#canWrite only returns true for a Map target
Closes gh-33265
2024-07-23 18:26:53 +03:00
Sam Brannen 4684a17f00 Polishing 2024-07-23 18:21:12 +03:00
Brian Clozel f3123d88f3 Merge branch '6.1.x' 2024-07-23 17:10:08 +02:00
Brian Clozel 9366308285 Fix Gradle warning in RuntimeHintsAgentPlugin
Fixing the following warning in the runtime hints plugin configuration:
https://docs.gradle.org/8.9/userguide/upgrading_version_8.html#test_task_default_classpath
2024-07-23 17:09:13 +02:00
Stéphane Nicoll de002ec12a Merge branch '6.1.x' 2024-07-23 16:21:04 +02:00
Stéphane Nicoll 12b996b07d Upgrade XJC processing to com.github.bjornvester.xjc
This commit upgrades our build to use a different plugin for XJC
processing, so that Gradle doesn't output a compatibility warning
anymore.

Unfortunately, com.github.bjornvester.xjc only works against main
sources and our schema is only used for test purposes. This commit
therefore reconfigure the task to remove the xjc main source set and
apply it to the test source set instead.

Closes gh-33264
2024-07-23 16:19:30 +02:00
Stéphane Nicoll 7c558a3d6d Merge branch '6.1.x' 2024-07-23 15:07:21 +02:00
Stéphane Nicoll 656d08f075 Fix warning in doc generation 2024-07-23 15:06:59 +02:00
Simon Baslé c92e043bbc Support multiple style of parsing/printing Durations
This commit introduces a notion of different styles for the formatting
of Duration.
The `@DurationFormat` annotation is added to ease selection of a style,
which are represented as DurationFormat.Style enum, as well as a
supported time unit represented as DurationFormat.Unit enum.

DurationFormatter has been retroffited to take such a Style,
optionally, at construction. The default is still the JDK style a.k.a.
ISO-8601.

This introduces the new SIMPLE style which uses a single number + a
short human-readable suffix. For instance "-3ms" or "2h".

This has the same semantics as the DurationStyle in Spring Boot and
is intended as a replacement for that feature, providing access to the
feature to projects that only depend on Spring Framework.

Finally, the `@Scheduled` annotation is improved by adding detection
of the style and parsing for the String versions of initial delay, fixed
delay and fixed rate.

See gh-22013
See gh-22474

Closes gh-30396
2024-07-23 11:56:48 +02:00
Stéphane Nicoll d219362eb1 Keep fallback flag in AOT-generated code
Closes gh-33261
2024-07-23 11:30:37 +02:00
Stéphane Nicoll eda21c4d22 Merge branch '6.1.x' 2024-07-23 10:51:56 +02:00
Stéphane Nicoll 6e9a19212f Consistently check for Content-Length value
This commit makes sure to consistently check that the content length
is not set above 2GB. Previously it was only checked in
setContentLength.

Closes gh-33256
2024-07-23 10:43:48 +02:00
Stéphane Nicoll 92385418ae Polish assertion 2024-07-23 10:16:04 +02:00
Brian Clozel ccc0a54c1c Merge branch '6.1.x' 2024-07-23 09:22:15 +02:00
Dawid Olbiński 83ff8e4e98 Support JAXBElement subtypes in Jaxb2XmlEncoder
Closes gh-33258
2024-07-23 09:19:11 +02:00
Stéphane Nicoll 00301440cd Merge pull request #32876 from quaff
* pr/32876:
  Polish "Resolved nested placeholder for CharSequence"

Closes gh-32876
2024-07-22 15:04:06 +02:00
Stéphane Nicoll b6fbbeccdc Polish "Resolved nested placeholder for CharSequence"
See gh-32876
2024-07-22 14:59:58 +02:00
Stéphane Nicoll 5331499393 Do not further process imports of Object.class
This commit filters out source classes that didn't pass a predicate
filter so that they are no longer considered.

Closes gh-27080
2024-07-22 12:31:02 +02:00
Stéphane Nicoll e011d4f798 Merge branch '6.1.x' 2024-07-21 13:06:10 +02:00
Stéphane Nicoll cbdaafd409 Order dependencies 2024-07-21 13:02:15 +02:00
Stéphane Nicoll 2190c6ec79 Merge branch '6.1.x' 2024-07-21 11:42:39 +02:00
Stéphane Nicoll e5c505b71a Merge pull request #33248 from ngocnhan-tran1996
* pr/33248:
  Polish "Stop referring to STRUCT and ARRAY as they are deprecated"
  Stop referring to STRUCT and ARRAY as they are deprecated

Closes gh-33248
2024-07-21 11:40:11 +02:00
Stéphane Nicoll af8dc44469 Polish "Stop referring to STRUCT and ARRAY as they are deprecated"
See gh-33248
2024-07-21 11:39:16 +02:00
Tran Ngoc Nhan 955602bdbd Stop referring to STRUCT and ARRAY as they are deprecated
See gh-33248
2024-07-21 11:18:12 +02:00
Stéphane Nicoll 28b044cdb4 Merge pull request #33247 from izeye
* pr/33247:
  Polish "Add missing Javadoc since in AbstractUrlHandlerMapping"
  Add missing Javadoc since in AbstractUrlHandlerMapping

Closes gh-33247
2024-07-21 09:34:06 +02:00
Stéphane Nicoll d5abc071f1 Polish "Add missing Javadoc since in AbstractUrlHandlerMapping"
See gh-33247
2024-07-21 09:30:06 +02:00
Johnny Lim edc356d5a0 Add missing Javadoc since in AbstractUrlHandlerMapping
See gh-33247
2024-07-21 09:29:53 +02:00
Stéphane Nicoll 97411ddd55 Merge branch '6.1.x' 2024-07-20 11:53:31 +02:00
Stéphane Nicoll b62662296e Merge pull request #33245 from ngocnhan-tran1996
* pr/33245:
  Polish "Update links in reference manual"
  Update links in reference manual

Closes gh-33245
2024-07-20 11:52:59 +02:00
Stéphane Nicoll a3b737ed00 Polish "Update links in reference manual"
See gh-33245
2024-07-20 11:51:49 +02:00
Tran Ngoc Nhan 61d1fde797 Update links in reference manual
See gh-33245
2024-07-20 11:32:35 +02:00
Brian Clozel b701b26b07 Merge branch '6.1.x' 2024-07-19 17:23:14 +02:00
Brian Clozel 0bb309f433 Instrument @JmsListener session for response messages
Prior to this commit, the observation instrumentation for `@JmsListener`
annotated methods (implemented in `AbstractMessageListenerContainer`
would not instrument the JMS session using the Micrometer JMS support.
This means that response messages returned from the listener method
would be sent but no observation would be recorded. As a result, tracing
message properties would be also missing.

This commit ensures that the session provided to the listener method is
instrumented beforehand, if Micrometer is on the classpath and an
observation registry has been configured.

Fixes gh-33221
2024-07-19 17:17:18 +02:00
rstoyanchev dcabddddc2 Expose HttpExchange metadata to argument resolvers
See gh-33220
2024-07-19 11:00:43 +01:00
Stéphane Nicoll 0bfc8e27cc Merge branch '6.1.x' 2024-07-19 11:33:54 +02:00
Stéphane Nicoll e8630f3409 Remove useless permissions on build-and-deploy-snapshot workflow
Closes gh-33238
2024-07-19 11:17:50 +02:00
Stéphane Nicoll 7b5e4b014b Merge pull request #33233 from deblockt
* pr/33233:
  Polish "Support JAXBElement in Jaxb2RootElementHttpMessageConverter"
  Support JAXBElement in Jaxb2RootElementHttpMessageConverter

Closes gh-33233
2024-07-19 10:22:45 +02:00
Stéphane Nicoll f4b2886775 Polish "Support JAXBElement in Jaxb2RootElementHttpMessageConverter"
See gh-33233
2024-07-19 10:20:06 +02:00
Thomas Deblock a5e2557738 Support JAXBElement in Jaxb2RootElementHttpMessageConverter
See gh-33233
2024-07-19 10:12:53 +02:00
Stéphane Nicoll e4edd3246a Restore Freemarker support now it supports Jakarta
Closes gh-30186
2024-07-18 17:55:52 +02:00
rstoyanchev ade8128060 Remove deprecated methods
Closes gh-33123
2024-07-18 11:37:20 +01:00
rstoyanchev 9409543dac Update deprecation notices
See gh-33123
2024-07-18 11:37:20 +01:00
Stéphane Nicoll 89453905cb Copy tests for multipart request builder
See gh-33229
2024-07-18 12:11:59 +02:00
Stéphane Nicoll 6590ab6bf9 Consistently set content type of the request with multipart
Closes gh-33232
2024-07-18 12:01:47 +02:00
Stéphane Nicoll 265299c790 Restore source and binary compatibility in MockMvc
Previous to this commit, MockHttpServletRequestBuilder was not binary
compatible as its methods had moved to a parent class with a generic
argument on the return type. MockMultipartHttpServletRequestBuilder
was also not source compatible as it no longed extended from
MockHttpServletRequestBuilder.

Both these changes were introduced to allow the AssertJ support to
expose builders that implement an extra AssertJ interface, without
copying the features the builders provide.

This commit restore compatibility. For MockHttpServletRequestBuilder
we simply override all methods that returns the generic type into
the resolved type.

MockMultipartHttpServletRequestBuilder is more involved. Because we
need to extend from MockHttpServletRequestBuilder, we have no other
choice than duplicating the code. For now, the abstract builder for
multipart is only used by the AssertJ support, but we can revisit this
again in a major release.

Closes gh-33229
2024-07-18 11:21:35 +02:00
Stéphane Nicoll 5715b2a783 Fix javadoc references 2024-07-17 16:54:59 +02:00
rstoyanchev b9509d3c85 Initialize RequestPath on demand
Closes gh-33227
2024-07-17 15:15:31 +01:00
Stéphane Nicoll 30a64d6a0b Avoid code too large with AOT processing
This commit adapts code generation to "slice" the registration of bean
definitions in separate bean methods rather than a unique method for
all of them.

If the bean factory has more than a thousand bean, a method is created
for each slice of 1000 bean definitions.

Closes gh-33126
2024-07-17 16:04:32 +02:00
Stéphane Nicoll 48dead4017 Harmonize milestone release workflow 2024-07-17 11:50:56 +02:00
Stéphane Nicoll 9b34400504 Merge pull request #33222 from quaff
* pr/33222:
  Polish "Add support for making MapAccessor read-only"
  Add support for making MapAccessor read-only

Closes gh-33222
2024-07-17 11:39:29 +02:00
Stéphane Nicoll 821109bd06 Polish "Add support for making MapAccessor read-only"
See gh-33222
2024-07-17 11:34:47 +02:00
Yanming Zhou a0e43b1f46 Add support for making MapAccessor read-only
See gh-33222
2024-07-17 11:32:21 +02:00
Stéphane Nicoll ec383f69f2 Merge branch '6.1.x' 2024-07-16 09:59:56 +02:00
Stéphane Nicoll c250817284 Update GHA actions 2024-07-16 09:59:14 +02:00
rstoyanchev b2decb4e5d Merge branch '6.1.x' 2024-07-15 15:21:39 +01:00
rstoyanchev 77bdbf7e37 Polishing contribution
Closes gh-33181
2024-07-15 15:21:19 +01:00
kevin.kep 2fe7ab1f92 Trim last allowed origin in comma-delimited list
See gh-33181
2024-07-15 15:17:03 +01:00
rstoyanchev 39c040005e Lazy use of Reactor Scheduler in DefaultPartHttpMessageReader
Closes gh-33218
2024-07-15 15:10:30 +01:00
Simon Baslé 50906e7fcb Merge branch '6.1.x' 2024-07-15 11:49:47 +02:00
Simon Baslé 6becfe2508 Fix AOP for Kotlin suspending function with aspect + @Cacheable
This change simplifies the CacheInterceptor way of dealing with cached
coroutines, thanks to the fact that lower level support for AOP has been
introduced in c8169e5c. This fix is similar to the one applied for
`@Transactional` in gh-33095.

Closes gh-33210
2024-07-15 11:47:12 +02:00
Stéphane Nicoll 681cfce730 Merge branch '6.1.x' 2024-07-14 11:22:14 +02:00
Stéphane Nicoll dfcd8374c7 Upgrade to Gradle 8.9
Closes gh-33214
2024-07-14 11:21:52 +02:00
Sam Brannen aa2829455b Expand test coverage for gh-14200 2024-07-13 17:26:26 +02:00
Sam Brannen 6ca8fbc2da Merge ArgumentsMatchInfo into ArgumentsMatchKind in SpEL
The internal ArgumentsMatchInfo type seems to have once had additional
methods beyond the functionality provided by the ArgumentsMatchKind
enum; however, that is no longer the case. Consequently, there is no
need to maintain both types.

This commit therefore merges the convenience methods from
ArgumentsMatchInfo into the ArgumentsMatchKind enum and removes the
unnecessary ArgumentsMatchInfo type.
2024-07-13 14:34:24 +02:00
rstoyanchev 007a347ade Refine executor description in WebSocketMessageBrokerStats
Closes gh-33104
2024-07-12 17:35:35 +01:00
rstoyanchev bd31e8dacc Provide access to underlying ConstraintViolation
Closes gh-33025
2024-07-12 17:35:35 +01:00
Sam Brannen 3e48498663 Change MIME mapping for .js from application/javascript to text/javascript
This application/javascript MIME type is deprecated.

This commit therefore changes the MIME type mapping for *.js files from
application/javascript to text/javascript in order to align with
industry standards.

Closes gh-33197
2024-07-12 18:22:18 +02:00
Sam Brannen 59b9404956 Specify nullability @⁠Contract for TypeDescriptor.array() 2024-07-12 18:02:26 +02:00
Sam Brannen 09d8e4458c Merge branch '6.1.x' 2024-07-12 17:37:51 +02:00
Sam Brannen ae5dd54115 Add @⁠Disabled tests for primitive varargs array to Object[] conversion 2024-07-12 17:36:54 +02:00
Sam Brannen e088892fc1 Support MethodHandle invocation with primitive varargs array in SpEL
Prior to this commit, the Spring Expression Language (SpEL) could not
invoke a varargs MethodHandle function with a primitive array
containing the variable arguments, although that is supported for a
varargs Method function. Attempting to do so resulted in the first
element of the primitive array being supplied as a single argument to
the MethodHandle, effectively ignoring any variable arguments after the
first one.

This commit addresses this by updating the
convertAllMethodHandleArguments(...) method in ReflectionHelper as
follows when the user supplies the varargs already packaged in a
primitive array.

- Regarding conversion, use the wrapper type for a primitive varargs
  array, since we eventually need an Object array in order to invoke
  the MethodHandle in FunctionReference#executeFunctionViaMethodHandle().

- When deciding whether to convert a single element passed as varargs,
  we now check if the argument is an array that is assignable to the
  varargs array type.

- When converting an array supplied as the varargs, we now convert that
  array to the varargs array type instead of the varargs component type.

Note, however, that a SpEL expression cannot provide a primitive array
for an Object[] varargs target. This is due to the fact that the
ArrayToArrayConverter used by Spring's ConversionService does not
support conversion from a primitive array to Object[] -- for example,
from int[] to Object[].

See gh-33191
Closes gh-33198
2024-07-12 17:36:54 +02:00
Simon Baslé fbe781b172 Merge branch '6.1.x' 2024-07-12 12:52:40 +02:00
Simon Baslé 152914a752 Fix multipart async servlet request temporary files deletion
This change tracks the multipart nature of the async request
within the `DispatcherServlet`, in the `WebAsyncManager`.

This allows for the second ASYNC dispatch to recognize the
multipart aspect and clean up the associated resources.

Closes gh-33161
2024-07-12 12:50:59 +02:00
Stéphane Nicoll 348764620d Merge branch '6.1.x' 2024-07-12 12:02:45 +02:00
Stéphane Nicoll 0f3f979d16 Align classloader used to create the JAXBContext
This commit makes sure that JAXBContext.newInstance consistently use
the target class classloader to detect the necessary resources.

Previously, the current thread's context classloader was used, which
could lead to not finding the required JAXB components.

Closes gh-33158
2024-07-12 12:00:07 +02:00
Stéphane Nicoll bac8a86419 Merge branch '6.1.x' 2024-07-12 08:37:47 +02:00
Stéphane Nicoll f8875ea970 Add missing artifact properties for staging
This commit makes sure that docs artifacts have their attributes set
for staging as well. Previously they were not and deployment of Javadoc
did not occur.

Closes gh-33204
2024-07-12 08:37:36 +02:00
Stéphane Nicoll c9375167fd Harmonize properties of deploy action 2024-07-12 08:37:36 +02:00
Sam Brannen c93598835c Merge branch '6.1.x' 2024-07-11 18:31:37 +02:00
Sam Brannen 48a6bd6ce7 Polishing 2024-07-11 18:30:52 +02:00
Stéphane Nicoll a421fc4fb3 Merge branch '6.1.x' 2024-07-11 17:01:01 +02:00
Stéphane Nicoll e15f123486 Remove concourse configuration now that CI is using GitHub Actions 2024-07-11 17:00:29 +02:00
Juergen Hoeller d1f9e35b35 Merge branch '6.1.x' 2024-07-11 16:16:31 +02:00
Juergen Hoeller 2bfff7fc37 Retain original URL instance in case of custom URLStreamHandler
Closes gh-33199
2024-07-11 16:15:42 +02:00
Stéphane Nicoll 022b91980e Publish release notes as a pre-release for milestones
This commit updates the "create-github-release" action to allow an
additional input that specifies whether this is a pre-release. If that
is the case, then the `--prerelease` flag is set.

Closes gh-33200
2024-07-11 16:11:47 +02:00
Stéphane Nicoll 1a21977965 Only promote a milestone when verify has completed
See gh-gh-33179
2024-07-11 10:47:10 +02:00
Stéphane Nicoll c038f551fc Merge branch '6.1.x' 2024-07-11 10:14:21 +02:00
Stéphane Nicoll 1880e109c3 Next development version (v6.1.12-SNAPSHOT) 2024-07-11 10:14:04 +02:00
rstoyanchev 93d5be621b Merge branch '6.1.x' 2024-07-10 17:55:48 +01:00
rstoyanchev 611d3e5551 Correct type names in docs on Validation in WebFlux
Closes gh-33061
2024-07-10 17:55:19 +01:00
Sébastien Deleuze 7617a01f60 Unwrap Kotlin inline value classes return values
The result returned by Kotlin reflective invocation of a function
returning an inline value class is wrapped, which makes sense
from Kotlin POV but from a JVM perspective the associated value
and type should be unwrapped to be consistent with what
would happen with a reflective invocation done by Java.

This commit unwraps such result.

Closes gh-33026
2024-07-10 18:38:37 +02:00
Sébastien Deleuze 82c5aa4a48 Refactor InvocableHandlerMethodKotlinTests
See gh-33026
2024-07-10 18:32:10 +02:00
rstoyanchev b93b7e013a Add FragmentsRendering to documentation for return values
Closes gh-33162
2024-07-10 16:50:12 +01:00
rstoyanchev 65296c6aad Add status/headers to WebMVC FragmentsRendering
See gh-33162
2024-07-10 16:40:40 +01:00
rstoyanchev 14c1faa5ee Updates to WebMVC fragment rendering API
See gh-33162
2024-07-10 16:40:40 +01:00
rstoyanchev 6ee8786385 Updates to WebFlux fragment rendering API
See gh-33162
2024-07-10 16:40:40 +01:00
rstoyanchev 54e76c8105 Support List and Publisher<Fragment> return values
See gh-33162
2024-07-10 16:40:40 +01:00
Stéphane Nicoll f2028d2339 Add workflow for releases to the milestone repository
See gh-33179
2024-07-10 16:58:34 +02:00
Sam Brannen f7d4742ab8 Merge branch '6.1.x' 2024-07-10 16:52:08 +02:00
Sam Brannen fa2a58b9db Ensure varargs component type for MethodHandle is not null in SpEL
This commit ensures that the varargs component type for a MethodHandle
cannot be null in ReflectionHelper's
convertAllMethodHandleArguments(...) method in SpEL.

Closes gh-33193
2024-07-10 16:46:47 +02:00
Sam Brannen 4de2aadf72 Merge branch '6.1.x' 2024-07-10 16:22:17 +02:00
Sam Brannen 83ca2c0cff Support MethodHandle function invocation with varargs array in SpEL
Prior to this commit, the Spring Expression Language (SpEL) could not
invoke a varargs MethodHandle function with an array containing the
variable arguments, although that is supported for a varargs Method
function. Attempting to do so resulted in the array being supplied as a
single argument to the MethodHandle.

This commit addresses this by updating the
executeFunctionViaMethodHandle(...) method in FunctionReference as
follows when the user supplies the varargs already packaged in an array.

- Creates a new array large enough to hold the non-varargs arguments
  and the unpackaged varargs arguments.

- Adds the non-varargs arguments to the beginning of that array and
  adds the unpackaged varargs arguments to the end of that array.

- Invokes the MethodHandle with the new arguments array.

Closes gh-33191
2024-07-10 16:16:41 +02:00
Sam Brannen dc16f3cffb Polish SpEL function invocation support 2024-07-10 16:16:41 +02:00
Juergen Hoeller 8cfdaaaabc Merge branch '6.1.x' 2024-07-10 15:57:24 +02:00
Juergen Hoeller f2b3263fff Polishing 2024-07-10 15:56:56 +02:00
Stéphane Nicoll 6de624d537 Provide a template method to expose the currently invoked factory method
This commit improves SimpleInstantiationStrategy by providing a common
template method before the regular runtime and AOT. As a result, the
method to set the currently invoked factory method is deprecated as it
should no longer be used.

Closes gh-33192
2024-07-10 15:38:17 +02:00
Simon Baslé 0c319a89d7 Merge branch '6.1.x' 2024-07-10 15:36:03 +02:00
Simon Baslé 1d890a8952 Make coroutines with custom AOP aspects work with @Transactional
Previous to this change, the transactional aspect would supersed the
user-defined AspectJ aspect, shortcircuiting to calling the original
Kotlin suspending function.

This change simplifies the TransactionAspectSupport way of dealing with
transactional coroutines, thanks to the fact that lower level support
for AOP has been introduced in c8169e5c.

Closes gh-33095
2024-07-10 15:35:43 +02:00
Juergen Hoeller a9efe10428 Merge branch '6.1.x'
# Conflicts:
#	spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java
2024-07-10 15:16:40 +02:00
Juergen Hoeller 3ccaefe38f Polishing 2024-07-10 15:15:32 +02:00
Juergen Hoeller 300f4585be Update spring.jdbc.getParameterType.ignore note for 6.1.2
See gh-25679
2024-07-10 15:15:26 +02:00
Sam Brannen bb64e22266 Merge branch '6.1.x' 2024-07-10 13:51:44 +02:00
Sam Brannen a0f5c16627 Support MethodHandle function invocation with zero varargs in SpEL
Prior to this commit, the Spring Expression Language (SpEL) could not
invoke a varargs MethodHandle function with zero variable arguments,
even though the variable arguments are not required. Attempting to do
so resulted in a SpelEvaluationException with an
INCORRECT_NUMBER_OF_ARGUMENTS_TO_FUNCTION message.

This commit addresses this by updating the
executeFunctionViaMethodHandle(...) method in FunctionReference so that
it properly checks the required number of arguments for both varargs
and non-varargs MethodHandle invocations.

This commit also improves the error message for varargs invocations
with too few arguments. For example, if the MethodHandle requires at
least 1 argument plus a variable number of additional arguments and 0
arguments were supplied, the error message now states:

"Incorrect number of arguments for function 'myFunc': 0 supplied but function takes 1 or more"

Instead of:

"Incorrect number of arguments for function 'myFunc': 0 supplied but function takes 2"

Closes gh-33190
2024-07-10 13:39:48 +02:00
Stéphane Nicoll c6b20c04c2 Merge branch '6.1.x' 2024-07-10 12:39:05 +02:00
Stéphane Nicoll b5a86dec92 Retain previous factory method in case of nested invocation with AOT
This commit harmonizes the invocation of a bean supplier with what
SimpleInstantiationStrategy does. Previously, the current factory method
was set to `null` once the invocation completes. This did not take
into account recursive scenarios where an instance supplier triggers
another instance supplier.

For consistency, the thread local is removed now if we attempt to set
the current method to null. SimpleInstantiationStrategy itself uses
the shortcut to align the code as much as possible.

Closes gh-33180
2024-07-10 12:38:56 +02:00
Sam Brannen ee6402eeca Merge branch '6.1.x' 2024-07-10 12:04:26 +02:00
Sam Brannen c55c64427c Support single String argument for varargs invocations in SpEL
Prior to this commit, the Spring Expression Language (SpEL) incorrectly
split single String arguments by comma for Object... varargs method and
constructor invocations.

This commit addresses this by checking if the single argument type is
already "assignable" to the varargs component type instead of "equal"
to the varargs component type.

Closes gh-33013
2024-07-10 11:51:55 +02:00
Sam Brannen a4fcd301f2 Polish SpEL's ReflectionHelper 2024-07-10 11:19:36 +02:00
Stéphane Nicoll 555e11b6b9 Merge branch '6.1.x' 2024-07-10 10:23:51 +02:00
Stéphane Nicoll ec4558dc14 Polish 2024-07-10 10:19:50 +02:00
Stéphane Nicoll 074348e047 Merge branch '6.1.x' 2024-07-10 10:13:42 +02:00
Stéphane Nicoll d6c623be40 Release from GHA
This commit adds a workflow to release the Spring Framework from GitHub
Actions.

Closes gh-33179
2024-07-10 10:11:32 +02:00
Stéphane Nicoll 9e34edad3d Merge branch '6.1.x' 2024-07-09 16:10:53 +02:00
Stéphane Nicoll 16b6d42adf Upgrade to Reactor 2024.0.0-M4
Closes gh-33171
2024-07-09 15:52:43 +02:00
Stéphane Nicoll 86da45ba15 Upgrade to Reactor 2023.0.8
Closes gh-33169
2024-07-09 15:52:09 +02:00
Stéphane Nicoll 8ac55e1463 Merge branch '6.1.x' 2024-07-09 14:39:37 +02:00
Stéphane Nicoll b2ba61155a Upgrade to Micrometer 1.14.0-M1
Closes gh-33170
2024-07-09 14:39:28 +02:00
Stéphane Nicoll 6a60298024 Upgrade to Micrometer 1.12.8
Closes gh-33168
2024-07-09 14:39:10 +02:00
Sébastien Deleuze 4ad5c59dea Upgrade to Kotlin Coroutines 1.8.1
Closes gh-33176
2024-07-09 14:35:15 +02:00
Sébastien Deleuze ea2895f7c7 Merge branch '6.1.x' 2024-07-09 14:34:47 +02:00
Sébastien Deleuze f8b448e949 Upgrade to Kotlin Serialization 1.6.3
Closes gh-33175
2024-07-09 14:31:56 +02:00
Sébastien Deleuze 52a0e6f900 Upgrade to Kotlin 1.9.24
Closes gh-33177
2024-07-09 14:31:47 +02:00
Stéphane Nicoll 0f66192e80 Merge branch '6.1.x' 2024-07-09 14:24:04 +02:00
Stéphane Nicoll 3d2fb3af3d Add verification tests
In preparation for releasing Spring Framework from GitHub actions, this
commit adds a `verify` workflow that validates that the released bits
are correct by running sample projects against them.

Closes gh-33178
2024-07-09 14:23:44 +02:00
Sam Brannen 028ff9b548 Unwrap InvocationTargetException in SpEL's FunctionReference
FunctionReference in the Spring Expression Language (SpEL) currently
does not unwrap an InvocationTargetException; however,
ConstructorReference and MethodReference do.

For example, currently one may encounter an exception like the
following, where the 'null' comes from the fact that an
InvocationTargetException doesn't always have a message.

SpelEvaluationException: EL1023E: A problem occurred whilst attempting
  to invoke the function 'formatObjectVarargs': 'null'

To address that, and to align with the behavior of ConstructorReference
and MethodReference, this commit modifies FunctionReference so that it
unwraps the InvocationTargetException to use its cause for the
exception message, resulting in an exception message like the following.

SpelEvaluationException: EL1023E: A problem occurred whilst attempting
  to invoke the function 'formatObjectVarargs': 'Format specifier '%s''

Closes gh-33174
2024-07-09 13:32:06 +02:00
Sébastien Deleuze e2ce811407 Merge branch '6.1.x' 2024-07-09 12:06:29 +02:00
Sébastien Deleuze 4f38079042 Throw proper DecodingException in Kotlin Serialization decoders
Closes gh-33138
2024-07-09 12:05:24 +02:00
rstoyanchev 9d45a8d512 Merge branch '6.1.x' 2024-07-09 06:54:56 +01:00
rstoyanchev 3008d97f93 Polishing contribution
Closes gh-33150
2024-07-09 06:53:14 +01:00
Sébastien NUSSBAUMER f0c758498b Allow validation of Set method parameters
See gh-33150
2024-07-09 06:53:14 +01:00
Juergen Hoeller f91f7916ac Merge branch '6.1.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
2024-07-08 22:57:14 +02:00
Juergen Hoeller bc2deef951 Upgrade to JRuby 9.4.8, Rhino 1.7.15, Moneta 1.4.4, JSONassert 1.5.3 2024-07-08 22:55:54 +02:00
Juergen Hoeller c6347025d6 Merge branch '6.1.x'
# Conflicts:
#	spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolutionIntegrationTests.java
2024-07-08 19:54:07 +02:00
Juergen Hoeller 7322a0d3c5 Upgrade to Groovy 4.0.22, Tomcat 10.1.25, Jetty 12.0.11, Undertow 2.3.14 2024-07-08 19:43:19 +02:00
Juergen Hoeller 7227c30917 Allow tests to pass on Windows JVM (non-UTF-8 default encoding)
See gh-33071
2024-07-08 19:42:28 +02:00
Simon Baslé 8918a772bf Polishing
See gh-32097
2024-07-08 18:36:46 +02:00
gregw 0a60c622cc Implement Eclipse Jetty core HTTP handler adapter
This provides an implementation of an HTTP Handler Adapter that is coded
directly to the Eclipse Jetty core API, bypassing any servlet
implementation.

This includes a Jetty implementation of the spring `WebSocketClient`
interface, `JettyWebSocketClient`, using an explicit dependency to the
jetty-websocket-api.

Closes gh-32097

Co-authored-by: Lachlan Roberts <lachlan@webtide.com>
Co-authored-by: Arjen Poutsma <arjen.poutsma@broadcom.com>
2024-07-08 18:36:46 +02:00
Stéphane Nicoll b7ec028149 Merge branch '6.1.x' 2024-07-08 16:52:01 +02:00
Stéphane Nicoll 7e7f55cb23 Merge pull request #33166 from hunhee98
* pr/33166:
  Polish contribution
  Harmonize phrasing in URI Encoding section

Closes gh-33166
2024-07-08 16:51:51 +02:00
Stéphane Nicoll 84f20cd0a7 Polish contribution
See gh-33166
2024-07-08 16:51:23 +02:00
Hunhee Lee 3d8f1fb00f Harmonize phrasing in URI Encoding section
See gh-33166
2024-07-08 16:51:09 +02:00
rstoyanchev ef6a3768ee Support multi-view rendering
See gh-33162
2024-07-08 12:47:10 +01:00
rstoyanchev 545228d693 Remove unused tiles config files 2024-07-08 12:47:10 +01:00
Stéphane Nicoll 078dfd47dc Add MessageHeaderAccessor to be created with existing headers
This commit mirrors toMap/toMessageHeaders with from factory methods
that allow to create an instance without having to create an
intermediate message if all they have is the headers.

Closes gh-33153
2024-07-08 13:40:38 +02:00
Stéphane Nicoll d89cb34c29 Merge branch '6.1.x' 2024-07-08 13:16:29 +02:00
Stéphane Nicoll e06115c06f Merge pull request #33156 from
* pr/33156:
  Polish "Implement DefaultErrorResponseBuilder#headers(Consumer)"
  Implement DefaultErrorResponseBuilder#headers(Consumer)

Closes gh-33156
2024-07-08 13:15:29 +02:00
Stéphane Nicoll 69850cad27 Polish "Implement DefaultErrorResponseBuilder#headers(Consumer)"
See gh-33156
2024-07-08 13:11:31 +02:00
Harry Yang bbbc95f773 Implement DefaultErrorResponseBuilder#headers(Consumer)
See gh-33156
2024-07-08 13:09:26 +02:00
Stéphane Nicoll 93587da394 Introduce ReflectiveScan
This commit allows `@Reflective` to be used on arbitrary types, not
only Spring beans. This makes the feature much more powerful as
components can be tagged directly.

Scanning happens during AOT processing (typically at build-time) when
`@ReflectiveScan` is used. Types do not need to have a particular
annotation, and types that can't be loaded are ignored.

This commit also exposes the infrastructure that does the scanning so
that custom code can do the scanning in an AOT contribution if they
don't want to rely on the annotation.

Closes gh-33132
2024-07-08 11:11:48 +02:00
Stéphane Nicoll f1658079a5 Polish documentation for RegisterReflection
See gh-29194
2024-07-06 09:31:12 +02:00
Sam Brannen c1f7d15c09 Merge branch '6.1.x' 2024-07-05 19:01:21 +02:00
Sam Brannen 83f7996c79 Polishing 2024-07-05 19:00:39 +02:00
rstoyanchev 194b4cedfb Use parsed path for checks in UrlHandlerFilter
See gh-32830
2024-07-05 09:35:57 +01:00
rstoyanchev 4054dc7088 Revise handler hierarchy in UrlHandlerFilter
See gh-32830
2024-07-05 09:35:57 +01:00
rstoyanchev 6ad8d6e5e3 Optimize path matching in UrlHandlerFilter
See gh-32830
2024-07-05 09:35:57 +01:00
rstoyanchev 80d1d50478 Polishing and minor refactoring in UrlHandlerFilter
See gh-32830
2024-07-05 09:35:57 +01:00
Stéphane Nicoll fd3bf5b352 Harmonize CI configuration
This commit is a continuation of eacfd77d but for workflows specific
to the main branch.
2024-07-05 10:26:43 +02:00
Stéphane Nicoll 3dba68fc5f Merge branch '6.1.x' 2024-07-05 10:00:37 +02:00
Stéphane Nicoll 0544dfe090 Enable building against Java 23-ea
This commit updates the CI workflow to build against Java 23-ea as
well, using the temurin distribution. For consistency, we're also
building against Java 22.

Closes gh-32090
2024-07-05 10:00:17 +02:00
Stéphane Nicoll 00738c17fa Merge branch '6.1.x' 2024-07-05 09:51:02 +02:00
Stéphane Nicoll eacfd77d6a Harmonize CI configuration
This commit harmonizes our CI configuration with Spring Boot, in
particular the clever use of reusable custom actions that simplify
the workflow definition quite a bit.

One main difference compared to Spring Boot is that we can now
specify a different distribution for a Java version to test, in
preparation for the support of building against 23-ea

See gh-32090
2024-07-05 09:46:45 +02:00
Stéphane Nicoll db1e6e1e26 Polish 2024-07-05 08:26:27 +02:00
Stéphane Nicoll f4607da45f Introduce RegisterReflection
This commit introduces a declarative way of registering reflection
information for arbitrary types. Types can be specified as a class,
a class name, or by annotating the type itself.

This existing RegisterReflectionForBinding becomes a specialized
version of the new annotation, registering the necessary hints for
data binding.

Closes gh-29194
2024-07-04 17:49:41 +02:00
Stéphane Nicoll b0807d847e Fix broken Javadoc reference
See gh-33102
2024-07-04 17:13:04 +02:00
Sam Brannen 8eb204b8dd Merge branch '6.1.x'
# Conflicts:
#	buildSrc/src/main/java/org/springframework/build/TestConventions.java
2024-07-04 17:05:38 +02:00
Sam Brannen 89338c91a9 Stop using using legacy locale data for Date/Time formatting tests
Commit 84714fbae9 introduced usage of the
-Djava.locale.providers=COMPAT command-line argument for javac in order
to allow our JDK 20 builds to pass by using legacy locale data.

That was done to ensure that Date/Time formats using AM/PM produced a
standard space (" ") before the "AM" or "PM" instead of a narrow
non-breaking space (NNBSP "\u202F"), which was introduced in Java 20
due to adoption of Unicode Common Locale Data Repository (CLDR-14032).

This commit removes usage of the -Djava.locale.providers=COMPAT
command-line argument and updates all affected tests to:

- Use an NNBSP before "AM" or "PM" in input text when running on Java 20
  or higher.

- Leniently match against any Unicode space character in formatted
  values containing "AM" or "PM".

See https://jdk.java.net/20/release-notes#JDK-8284840
See https://unicode-org.atlassian.net/browse/CLDR-14032
See gh-30185
Closes gh-33144
2024-07-04 17:03:15 +02:00
Stéphane Nicoll 6fa340760d Merge branch '6.1.x' 2024-07-04 16:52:48 +02:00
Stéphane Nicoll 51641ece72 Polish
See gh-33127
2024-07-04 16:51:10 +02:00
Stéphane Nicoll ca8bd7b06b Simplify tests 2024-07-04 16:34:33 +02:00
Simon Baslé 5cb9469a29 Merge branch '6.1.x' 2024-07-04 16:19:10 +02:00
Simon Baslé 06d267f04e Improve WebClientResponseException message in case of 1xx/2xx/3xx status
When a response fails to be completely emitted by the remote (connection
termination during the transmission of the response for example), a
WebClientResponseException can be propagated with a confusing message
which mainly reflects the status code and reason phrase, leading to
messages like "200 OK" in such an exception.

This change improves the situation by appending a hint at the underlying
cause whenever getMessage() is called on a WebClientResponseException
which was created with a non-error status code.

Closes gh-33127
2024-07-04 15:20:46 +02:00
Stéphane Nicoll 4bdb772d39 Introduce HttpMessageContentConverter
This commit introduces an abstraction that allows to convert HTTP
inputs to a data type based on a set of HttpMessageConverter.

Previously, the AssertJ integration was finding the first converter
that is able to convert JSON to a Map (and vice-versa) and used that
in its API. With the introduction of SmartHttpMessageConverter, exposing
a specific converter is fragile.

The added abstraction allows for converting other kind of input than
JSON if we need to do that in the future.

Closes gh-33148
2024-07-04 14:06:00 +02:00
Stéphane Nicoll 206d81ee08 Merge branch '6.1.x' 2024-07-04 10:26:46 +02:00
Stéphane Nicoll dfa6b4bd42 Upgrade to Gradle 8.8
Closes gh-33146
2024-07-04 10:23:15 +02:00
Stéphane Nicoll 6cccbeda5b Merge branch '6.1.x' 2024-07-04 04:26:46 +02:00
Stéphane Nicoll 099a97740e Downgrade Awaitility to 4.2.0
This is required to build against ea builds

Closes gh-33143
2024-07-04 04:20:43 +02:00
Sam Brannen abcad5dbcf Support property placeholders in @⁠Sql script paths
Prior to this commit, paths configured via the scripts attribute in
@⁠Sql were required to be final paths without dynamic placeholders;
however, being able to make script paths dependent on the current
environment can be useful in certain testing scenarios.

This commit introduces support for property placeholders (${...}) in
@⁠Sql script paths which will be replaced by properties available in
the Environment of the test's ApplicationContext.

Closes gh-33114
2024-07-03 17:16:53 +02:00
Juergen Hoeller 384d0e4fd5 Merge branch '6.1.x' 2024-07-03 16:37:36 +02:00
Juergen Hoeller daea3f0eae Apply fallback resolution for non-hierarchical URIs such as "file:."
Includes meaningful exception message for file system resolution.

Closes gh-33124
2024-07-03 16:36:18 +02:00
Stéphane Nicoll 1ea4eb147a Polish 2024-07-03 10:04:51 +02:00
Stéphane Nicoll 99e8978a91 Restore binary backward compatibility for GeneratedFiles
See gh-31331
2024-07-03 09:57:22 +02:00
Simon Baslé 78d594c012 Merge branch '6.1.x' 2024-07-02 11:40:39 +02:00
zizare 8974da2a5a Use error handler for reactive cache aspect
This change ensures that the cache error handler is used in case of
future-based or publisher-based asynchronous caching completing with an
exception.

Closes gh-33073
2024-07-02 11:29:53 +02:00
Sam Brannen a8e8897a00 Stop referring to old Spring versions in the reference manual 2024-07-01 18:37:46 +02:00
Sam Brannen e02cddd155 Delete obsolete documentation for JNDI mock support 2024-07-01 18:32:28 +02:00
Sam Brannen 932ce04541 Stop referring to old Spring versions in Javadoc 2024-07-01 17:50:52 +02:00
Sam Brannen e427ac2683 Document parallel execution regarding @⁠MockitoBean & @⁠MockitoSpyBean 2024-07-01 17:08:09 +02:00
Sam Brannen 56fe857f1e Don't reference "Spring Framework 5.0" in parallel test execution section 2024-07-01 17:03:43 +02:00
Arjen Poutsma bd4823e3de Remove deprecated methods scheduled for removal in 6.2
See gh-33123
2024-07-01 16:26:49 +02:00
Arjen Poutsma 5864f57198 Resolve URI to baseUrl in RestClient
Closes gh-32679
2024-07-01 15:10:30 +02:00
Sébastien Deleuze 98e89d8fba Leverage KType in Kotlin Serialization WebFlux support
In order to take in account properly Kotlin null-safety with the
annotation programming model.

Closes gh-33016
2024-07-01 15:06:08 +02:00
Sébastien Deleuze 23dccc5977 Leverage KType in Kotlin Serialization WebMVC support
In order to take in account properly Kotlin null-safety with the
annotation programming model.

See gh-33016
2024-07-01 15:06:08 +02:00
Sébastien Deleuze 4555384528 Introduce SmartHttpMessageConverter
SmartHttpMessageConverter is similar to GenericHttpMessageConverter,
but more consistent with WebFlux Encoder and Decoder contracts, with
the following differences:
 - A ResolvableType parameter is used instead of the Type one
 - The MethodParameter can be retrieved via the ResolvableType source
 - No contextClass parameter
 - `@Nullable Map<String, Object> hints` additional parameter for write
   and read methods

This commit also refines RestTemplate#canReadResponse in order to use
the most specific converter contract when possible.

Closes gh-33118
2024-07-01 15:05:57 +02:00
Brian Clozel 0717748f58 Merge branch '6.1.x' 2024-07-01 11:49:13 +02:00
Brian Clozel ab236c7741 Re-enable async dispatches in Observation Filter
Prior to this commit, the fix for gh-32730 disabled the involvment of
the osbervation filter for async dispatches. Instead of relying on ASYNC
dispatches to close the observation for async requests, this is now
using an async listener instead: async dispatches are not guaranteed to
happen once the async request is handled.

This change caused another side-effect: because async dispatches are not
considered anymore by this filter, the observation scope is not
reinstated for async dispatches. For example, `ResponseBodyAdvice`
implementations do not have the observation scope opened during their
execution.

This commit re-enables async dispatches for this filter, but ensures
that observations are not closed during such dispatches as this will be
done by the async listener.

Fixes gh-33091
2024-07-01 11:42:48 +02:00
Sam Brannen cc002875c4 Support fully-qualified factory method names in @⁠TestBean
Prior to this commit, @⁠TestBean factory methods had to be defined in
the test class, one of its superclasses, or in an implemented
interface. However, users may wish to define common factory methods in
external classes that can be shared easily across multiple test classes
simply by referencing an external method via a fully-qualified method
name.

To address that, this commit introduces support for referencing a
@⁠TestBean factory method via its fully-qualified method name following
the syntax <fully-qualified class name>#<method name>.

Closes gh-33125
2024-06-30 21:16:04 +02:00
Sam Brannen c2f8d4803f Update Javadoc for @⁠TestBean 2024-06-30 21:15:56 +02:00
Sam Brannen b105fdc87a Polishing 2024-06-30 14:41:43 +02:00
Sam Brannen b64edb2d2a Update Content-Type based on encoding in MVC FreeMarkerView
Closes gh-33119
2024-06-29 17:12:48 +02:00
Sam Brannen ce53443cf0 Polishing 2024-06-29 17:12:47 +02:00
Juergen Hoeller 775a23b39d Merge branch '6.1.x' 2024-06-28 18:10:53 +02:00
Juergen Hoeller 61adf2dd25 Formal null safety for exception message through String.valueOf
See gh-33117
2024-06-28 18:09:39 +02:00
Juergen Hoeller 61894af0bd Expose FactoryBean attribute exception as BeanDefinitionStoreException
Closes gh-33117
2024-06-28 17:55:45 +02:00
rstoyanchev acb427d460 Merge branch '6.1.x' 2024-06-28 15:35:13 +01:00
rstoyanchev c74666a883 Polishing contribution
Closes gh-33105
2024-06-28 15:32:43 +01:00
vatsal 976b4f3533 Fix return value validation
Fix argument in call to applyReturnValueValidation()
method in MethodValidationInterceptor.java. Method
argument was passed instead of the return value of the
method that was being validated.

See gh-33105
2024-06-28 15:00:11 +01:00
Juergen Hoeller c681614bc2 Merge branch '6.1.x' 2024-06-28 11:36:53 +02:00
Juergen Hoeller 100da83913 Detect ajc markers in superclasses as well (for weaving check)
Closes gh-33113
2024-06-28 11:36:17 +02:00
Sam Brannen 3715df11de Merge branch '6.1.x' 2024-06-27 17:02:16 +02:00
Sam Brannen e881c70a93 Upgrade to JUnit 5.10.3 2024-06-27 17:00:43 +02:00
Sam Brannen d902bd7696 Reject ModelMap argument types in WebFlux
Prior to this commit, if ModelMap was used as an argument type in a
WebFlux controller method, the user encountered an exception similar to
the following.

java.lang.IllegalStateException: argument type mismatch
  Controller [example.SampleController]
  Method [java.lang.String example.SampleController.index(org.springframework.ui.ModelMap)] with argument values:
  [0] [type=org.springframework.validation.support.BindingAwareConcurrentModel] [value={}]

However, the above error message is a bit cryptic since the error
occurs while attempting to invoke the controller method with an
instance of BindingAwareConcurrentModel which is not compatible with
ModelMap. More importantly, this error message does not explicitly
convey to the user that a ModelMap is not supported.

This commit improve the diagnostics for the user in such scenarios by
rejecting the use of ModelMap upfront in WebFlux.

Consequently, for the same use case as above, the user now encounters
an exception similar to the following.

java.lang.IllegalStateException:
  Could not resolve parameter [0] in
  java.lang.String example.SampleController.index(org.springframework.ui.ModelMap):
  No suitable resolver

Closes gh-33109
2024-06-27 16:16:48 +02:00
Juergen Hoeller 053af5f75b Merge branch '6.1.x' 2024-06-27 12:04:59 +02:00
Juergen Hoeller fea237c065 Lazily start and retain HttpClient once resource factory is running
Closes gh-33093
2024-06-27 12:03:10 +02:00
Sam Brannen e1567b93c2 Merge branch '6.1.x' 2024-06-27 11:40:16 +02:00
Sam Brannen 8b11ee9ee2 Document that ModelMap is not a supported argument type in WebFlux
Prior to this commit, the "Method Arguments" documentation for WebFlux
in the reference manual stated that WebFlux controller methods can
accept arguments of type Map, Model, or ModelMap to access the model.
However, ModelMap is actually not supported and results in exception
due to a type mismatch.

This commit updates the documentation to reflect this.

In addition, this commit updates related Javadoc and tests to avoid
mentioning or using ModelMap in WebFlux.

Closes gh-33107
2024-06-27 11:33:50 +02:00
Sam Brannen 1cf5264163 Polishing 2024-06-27 10:46:00 +02:00
Sam Brannen 8b95697c8d Set output_encoding in FreeMarkerView implementations
According to the official FreeMarker documentation, Spring's
FreeMarkerView implementations should be configuring the
output_encoding for template rendering.

To address that, this commit modifies the FreeMarkerView
implementations in Web MVC and WebFlux to explicitly set the
output_encoding for template rendering.

See https://freemarker.apache.org/docs/pgui_misc_charset.html#autoid_53
See gh-33071
Closes gh-33106
2024-06-27 10:07:47 +02:00
Sam Brannen 95887c81b9 Polish naming for Charset setters in FreeMarker support
See gh-33102
2024-06-26 17:51:11 +02:00
Sam Brannen 08112963a2 Merge branch '6.1.x' 2024-06-26 16:45:34 +02:00
Sam Brannen c68c6faa03 Fix comment in Method Injection example in reference manual
Prior to this commit, the comment in the XML configuration example in
the Method Injection section of the reference manual referred to the
wrong bean names.

Closes gh-33096
2024-06-26 16:45:06 +02:00
Sam Brannen 73c0783df1 Allow encoding to be set with a Charset in FreeMarker support
Closes gh-33102
2024-06-26 16:18:09 +02:00
rstoyanchev 4e13a69948 Fix spring-websocket test failure after 6c2f60
See gh-32813
2024-06-26 09:31:08 +01:00
Brian Clozel 7f9e541f58 Merge branch '6.1.x' 2024-06-25 21:19:27 +02:00
Brian Clozel 6dd5c85ed0 Support byte array payloads in ProtobufMessageConverter
Prior to this commit, the `ProtobufMessageConverter` used in messaging
would try and serialize the message payload by calling "toString()" on
it in order to pass it to the Protobuf JSON encoder.
While this works for `String` payloads, this fails for `byte[]` types.

This commit ensures that such `byte[]` are first converted to `String`
instances using the given charset first.

Fixes gh-27408
2024-06-25 21:16:50 +02:00
Sam Brannen 7183a19dbe Merge branch '6.1.x' 2024-06-25 16:58:45 +02:00
Sam Brannen d133ab60ee Improve documentation regarding encoding in FreeMarker support
This commit also introduces integration tests to test the status quo
regarding encoding.

Closes gh-33071
2024-06-25 16:56:48 +02:00
Sam Brannen 5d6e143ff4 Remove invalid configuration in RequestMappingViewResolutionIntegrationTests
Prior to this commit, RequestMappingViewResolutionIntegrationTests
invoked the following:

configurer.setTemplateLoaderPath(
	"classpath*:org/springframework/web/reactive/view/freemarker/");

However, that configuration is invalid since `classpath*:` is not
supported for a `templateLoaderPath`.

Despite that, the tests still passed since FreeMarkerConfigurer already
registers a new ClassTemplateLoader(FreeMarkerConfigurer.class, ""),
which automatically finds template files in the same package as
FreeMarkerConfigurer (for the "spring.ftl" macro library support) and
coincidentally RequestMappingViewResolutionIntegrationTests as well
(which resides in the same package).

This commit therefore removes the invalid configuration and adds a
comment to explain what's going on.
2024-06-25 16:56:21 +02:00
rstoyanchev 6c2f602369 Propagate context to send for SSE Flux
Closes gh-32813
2024-06-25 15:39:43 +01:00
rstoyanchev c1250b1898 Replace use of deprecated ContextSnapshot methods
See gh-32813
2024-06-25 15:39:43 +01:00
Stephane Nicoll 0ea7af7465 Polish
See gh-31331
2024-06-24 18:07:59 +02:00
Sébastien Deleuze 8ef74dfdad Prevent compilation warnings with @Nullable
This commit replaces `@Nonnull(when = When.MAYBE)` meta-annotation in
org.springframework.lang.Nullable by `@CheckForNull` in order to
prevent "unknown enum constant When.MAYBE" compilation warnings.

IntelliJ IDEA 2024.1.2+ is required to interpret correctly the related
annotations.

Closes gh-27183
2024-06-24 14:56:07 +02:00
Juergen Hoeller 0a0f4c7460 Accept file separator difference in exception message (for Windows compatibility) 2024-06-24 12:28:43 +02:00
Juergen Hoeller d9a2e0b731 Merge branch '6.1.x' 2024-06-24 12:27:23 +02:00
rstoyanchev 6e82bf05b6 Document list/map/array constructor data binding
Closes gh-32426
2024-06-24 11:25:22 +01:00
Juergen Hoeller 4e2fb308f6 Document contentLength() behavior for InputStreamResource and custom subclasses
Closes gh-33089
2024-06-24 12:10:35 +02:00
rstoyanchev e48cbc5ba8 Support list/map/array constructor data binding
See gh-32426
2024-06-24 10:44:32 +01:00
Brian Clozel f9af5d400d Use custom path separator for pattern comparisons
As pointed out in gh-33085, the `AntPatternComparator` hardcodes the "/"
separator when checking for "catch all" patterns like "/**".
This commit ensures that the custom path separator is used for those
checks, in order to guarantee consistent comparator results.

See gh-33085
2024-06-24 11:37:24 +02:00
Brian Clozel 6d1f117103 Polishing contribution
Closes gh-33085
2024-06-24 11:37:16 +02:00
tafjwr 83fcdfba64 Fix AntPathMatcher URI template variable extractor
See gh-33085
2024-06-24 11:37:09 +02:00
Sam Brannen 9b58e1ff71 Merge branch '6.1.x' 2024-06-23 17:44:47 +02:00
Sam Brannen 5f765fc8ce Polishing 2024-06-23 13:22:08 +02:00
Stephane Nicoll 2650da2b53 Provide more control over registration of GeneratedFiles
This commit provides an advanced handling of generated files that
provides more control over files registration. The callback provides
a FileHandler that can determine if the file already exists and its
content. The caller can then chose to override the content or leave it
as it is.

Closes gh-31331
2024-06-22 18:52:33 +02:00
Sam Brannen 6b456b6157 Upgrade to FreeMarker 2.3.33 2024-06-22 16:55:56 +02:00
Sam Brannen e6b77d301d Merge branch '6.1.x' 2024-06-22 16:52:42 +02:00
Sam Brannen 000b563e83 Use consistent formatting for view name in AbstractView 2024-06-22 16:51:37 +02:00
Sam Brannen c571ee1f95 Fix typo in comment 2024-06-22 16:51:28 +02:00
Stéphane Nicoll b134f253b5 Move the testing section after data and web
Closes gh-33083
2024-06-21 14:35:33 +02:00
Stéphane Nicoll 043b93d255 Upgrade to HtmlUnit 4.2.0
Closes gh-33081
2024-06-21 14:30:02 +02:00
Stéphane Nicoll 6e87aba100 Merge branch '6.1.x' 2024-06-21 14:14:26 +02:00
Stéphane Nicoll 899f6308d9 Fix name of GitHub actions bot
See gh-gh-33076
2024-06-21 14:14:05 +02:00
Stéphane Nicoll d43dba63a1 Document AssertJ support for MockMvc
This commit restructures the section on MockMvc so that the anchors
are easier to read. The standard integration has moved to a
Hamcrest Integration section  at the same level as HtmlUnit Integration,
and a new AssertJ Integration section has been created.

Closes gh-32454
2024-06-21 12:51:35 +02:00
Juergen Hoeller 7d236e29bb Merge branch '6.1.x'
# Conflicts:
#	spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
2024-06-21 11:23:37 +02:00
Juergen Hoeller a580d6d6fc Leniently ignore type mismatch for LoadTimeWeaverAware beans
Closes gh-33082
2024-06-21 11:22:48 +02:00
Juergen Hoeller 7fc2814a34 Merge branch '6.1.x' 2024-06-20 18:57:49 +02:00
Juergen Hoeller 66eddf99af Include original exception if cause is null
Closes gh-33080
See gh-32952
2024-06-20 18:56:43 +02:00
Sam Brannen eeb9959cb9 Polishing 2024-06-20 17:13:48 +02:00
Stéphane Nicoll e5993d92c4 Merge branch '6.1.x' 2024-06-20 14:16:13 +02:00
Stéphane Nicoll e94ec80df4 Exclude GitHub Actions bot from changelog
Closes gh-33076
2024-06-20 14:15:54 +02:00
Juergen Hoeller 52e1f30bfe Merge branch '6.1.x' 2024-06-20 13:48:55 +02:00
Juergen Hoeller 2861e570fd Catch and log LinkageError in getTypeForFactoryMethod
Closes gh-33075
2024-06-20 13:47:43 +02:00
Brian Clozel e3048bce11 Merge branch '6.1.x' 2024-06-19 18:15:55 +02:00
Stéphane Nicoll 5cf8978d22 Restore proper code generation for types with nested generics
This commit aligns code generation to recent improvement in the core
container regarding type detection. Now that nested types are properly
resolved, our code generation that uses hasResolvableGenerics() is
taking the wrong decision if only a nested type has an unresolved
generics. Previously, this was hidden by the fact that the core
container would not resolve them recursively.

A new hasResolvableGenerics() method allows to verify that at least
one direct generic type is resolved. This restore our intent of checking
at the first level only and let recursive invocations figure out if they
have to write the raw type or the type with generics.

Closes gh-33069
2024-06-19 17:48:39 +02:00
Spring Builds ee7a1e8b7e Next development version (v6.1.11-SNAPSHOT) 2024-06-19 15:37:10 +00:00
Juergen Hoeller 1047e1f722 Declare complete set of default methods on ObjectProvider
Closes gh-33070
2024-06-19 16:53:10 +02:00
Brian Clozel 4cbaaa3b1d Move Servlet HTTP Message Conversion to its own section
Closes gh-33063
2024-06-19 15:45:16 +02:00
Arjen Poutsma e62255512a Encode based on response character encoding
Before this commit, characters were always encoded with the default
encoding (i.e. ISO-8859-1). Now, the character encoding of the response
is used.

Closes gh-files
2024-06-19 14:26:38 +02:00
Brian Clozel c72e31bcf5 Merge branch '6.1.x' 2024-06-19 12:51:23 +02:00
Brian Clozel f7307c9e07 Avoid recording RestClient observations twice
Prior to this commit, the fix for gh-32575 introduced cases where the
client observation would be stopped twice.

This commit ensures that `RestClient` observations are stopped only once
when the response is closed, or before throwing an unhanlded exception.

Fixes gh-33068
2024-06-19 12:46:21 +02:00
Sam Brannen ce49354400 Sync MockHttpServletResponse implementations
See gh-33019
2024-06-19 12:31:17 +02:00
Sébastien Deleuze 1d363e5a41 Use UTF-8 with JSON in MockHttpServletResponse
This commit makes MockHttpServletResponse consistent with the other
parts of the framework where the body of a response is read as an UTF-8
String when the content type is application/json or similar, overriding
the ISO-8859-1 default Servlet encoding.

Closes gh-33019
2024-06-19 09:33:43 +02:00
Brian Clozel 2116d71d81 Merge branch '6.1.x' 2024-06-18 19:28:05 +02:00
Brian Clozel 098c4b1dd7 Use Sonatype S01 token in release pipeline 2024-06-18 19:25:20 +02:00
Juergen Hoeller 82af8e62c1 Merge branch '6.1.x' 2024-06-18 18:32:29 +02:00
Juergen Hoeller 65dbfd09b4 Defensive PersistenceExceptionTranslator bean retrieval on shutdown
Closes gh-33067
2024-06-18 18:31:15 +02:00
Sam Brannen d7668eec00 Merge branch '6.1.x' 2024-06-18 16:45:28 +02:00
Sam Brannen 203fa75196 Support all "connection reset" phrases in DisconnectedClientHelper
Prior to this commit, the isClientDisconnectedException() method in
DisconnectedClientHelper checked whether the message of the ultimate
exception in an exception chain contained one of the phrases "broken
pipe" or "connection reset by peer". However, that failed to match if
the exception message contained "Connection reset", which is the case
for the SocketException thrown by throwConnectionReset() in
sun.nio.ch.SocketChannelImpl.

This commit therefore replaces the "connection reset by peer" phrase
with "connection reset" in order to support all exception messages
containing "connection reset".

Closes gh-33064
2024-06-18 16:43:06 +02:00
Stéphane Nicoll 1eaa9cd2f4 Polish 2024-06-18 16:04:19 +02:00
Brian Clozel 17abb4d25d Add codecs for JSON support with Protobuf
Prior to this commit, WebFlux had Protobuf codecs for managing the
`Message`/`"application/x-protobuf"` encoding and decoding.
The `com.google.protobuf:protobuf-java-util` library has additional
support for JSON (de)serialization, but this is not supported by
existing codecs.

This commit adds the new `ProtobufJsonEncode` and `ProtobufJsonDecoder`
classes that support this use case. Note, the `ProtobufJsonDecoder` has
a significant limitation: it cannot decode JSON arrays as
`Flux<Message>` because there is no available non-blocking parser able
to tokenize JSON arrays into streams of `Databuffer`. Instead,
applications should decode to `Mono<List<Message>>` which causes
additional buffering but is properly supported.

Closes gh-25457
2024-06-18 15:48:46 +02:00
Stéphane Nicoll 24bbc6d80d Improve support of async request in MockMvcTester
This commit improves the handling of asynchronous requests by offering
a way to opt-in for the raw async result. This provides first class
support for asserting a request that might still be in process as well
as the asyncResult, if necessary.

See gh-33040
2024-06-18 15:19:47 +02:00
Stéphane Nicoll a7503e7200 Add explicit support for asynchronous requests in MockMvcTester
This commit makes asynchronous requests first class by providing a
MvcTestResult that represents the final, completed, state of a request
by default. Previously, the result was an intermediate step that may
require an ASYNC dispatch to be fully usable. Now it is de facto
immutable.

To make things a bit more explicit, an `.exchange(Duration)` method has
been added to provide a dedicated time to wait. The default applies a
default timeout that is consistent with what MVcResult#getAsyncResult
does.

Given that we apply the ASYNC dispatch automatically, the intermediate
response is no longer available by default. As a result, the asyncResult
is not available for assertions.

As always, it is possible to use plain MockMvc by using the `perform`
method that takes the regular RequestBuilder as an input. When this
method is invoked, no asynchronous handling is done.

Closes gh-33040
2024-06-18 13:03:09 +02:00
Stéphane Nicoll a1b0099795 Add missing debug(Writer) alternative
See gh-33059
2024-06-18 12:40:29 +02:00
Arjen Poutsma 54c37ffd6f Check response code in SimpleClientHttpResponse::getBody
The error stream can be null with an empty body, so check the response
code instead.

Closes gh-33020
2024-06-18 12:33:56 +02:00
Stéphane Nicoll acf73404c1 Simplify Mock[Multipart]HttpServletRequestBuilder
This commit simplifies the package private constructors on those two
builders now that the URI can be specified by dedicated builder methods.

Closes gh-33062
2024-06-18 10:10:07 +02:00
Stéphane Nicoll d76f37c90b Add multipart support for MockMvcTester
File uploads with MockMvc require a separate
MockHttpServletRequestBuilder implementation. This commit applies the
same change to support AssertJ on this builder, but for the multipart
version.

Any request builder can now use `multipart()` to "down cast" to a
dedicated multipart request builder that contains the settings
configured thus far.

Closes gh-33027
2024-06-18 09:43:08 +02:00
Stéphane Nicoll f2137c99e5 Add debug support for MvcResult
This commit adds a debug() shortcut to print the detail of a MvcResult
to ease debugging when a request did not work as expected.

Closes gh-33059
2024-06-18 06:43:26 +02:00
Stéphane Nicoll 84bcb65dd1 Streamline assertions on exceptions
This commit simplifies assertions on MockMvc requests that have failed
to process. A now general hasFailed/doesNotHaveFailed/failure provides
the necessary to assert the exception.

Any attempt to access anything from the result with an unresolved
exception still fails as before.

Closes gh-33060
2024-06-18 06:23:13 +02:00
Juergen Hoeller 6561490fd9 Expose isClosed() method on AbstractApplicationContext
Closes gh-33058
2024-06-17 21:08:28 +02:00
Juergen Hoeller 5c68f3f4ef Reject @Bean method with method-level @Autowired declaration
Closes gh-33051
2024-06-17 21:08:21 +02:00
Juergen Hoeller a58e27eded Use CollectionFactory#newLinkedHashSet for method arguments
See gh-32291
2024-06-17 18:50:31 +02:00
Juergen Hoeller 6d5c312027 Merge branch '6.1.x' 2024-06-17 18:44:50 +02:00
Juergen Hoeller 9a56a8877f Polishing 2024-06-17 18:42:37 +02:00
Juergen Hoeller e79a9a5bff Correct and consistent event class names in constructor javadoc
Closes gh-33032
2024-06-17 18:42:30 +02:00
Juergen Hoeller 2c3c3831c1 Consistently ignore bridge method on generated subclass for visibility purposes
Closes gh-33030
2024-06-17 18:42:20 +02:00
Stéphane Nicoll 1582f5f7d1 Handle URI as candidate for a merge from a parent builder
Closes gh-33057
2024-06-17 17:06:10 +02:00
Stéphane Nicoll b8790077b9 Polish 2024-06-17 16:47:37 +02:00
Arjen Poutsma b65b3350be Merge branch '6.1.x' 2024-06-17 14:20:05 +02:00
Arjen Poutsma c38e9896c7 Remove use of ServletException in ModelFactory
This commit changes the use of HttpSessionRequiredException in
ModelFactory::initModel to an IllegalStateException, because the former
extends ServletException and cannot be used in WebFlux.

Closes gh-33043
2024-06-17 14:19:19 +02:00
Stéphane Nicoll e4c881be73 Merge branch '6.1.x' 2024-06-17 13:43:23 +02:00
Stéphane Nicoll 3e0849a566 Fix typo
Closes gh-33050
2024-06-17 13:39:18 +02:00
Brian Clozel 7658a8064d Merge branch '6.1.x'
Closes gh-33049
2024-06-17 12:55:31 +02:00
github-actions[bot] f3a605b92c Update Antora Spring UI to v0.4.16 2024-06-17 10:06:47 +00:00
Stéphane Nicoll 5edb4cb2c9 Merge branch '6.1.x' 2024-06-16 16:51:15 +02:00
Stéphane Nicoll 6fdff201e9 Fix property name in Container Extension Points section
Closes gh-33037
2024-06-16 16:47:36 +02:00
Stéphane Nicoll e9d5d68628 Merge branch '6.1.x' 2024-06-16 09:59:21 +02:00
Stéphane Nicoll c42778a05b Merge pull request #33036 from tafjwr
* pr/33036:
  Polish "Fix typo in comment"
  Fix typo in comment

Closes gh-33036
2024-06-16 09:59:15 +02:00
Stéphane Nicoll f140df881d Polish "Fix typo in comment"
See gh-33036
2024-06-16 09:57:24 +02:00
tafjwr 12cf654c98 Fix typo in comment
See gh-33036
2024-06-16 09:56:58 +02:00
Juergen Hoeller 4b58626fa4 Merge branch '6.1.x' 2024-06-14 22:09:31 +02:00
Juergen Hoeller 089e4e69f1 Do not attempt to load pre-enhanced class for reloadable classes
Closes gh-33024
2024-06-14 22:07:46 +02:00
Stéphane Nicoll 9db24d23ae Merge branch '6.1.x' 2024-06-14 19:56:08 +02:00
Stéphane Nicoll 77755ff2fa Remove repo-specific code of conduct
This will allow us to inherit the org's CoC instead.

Closes gh-33031
2024-06-14 18:58:49 +02:00
Stéphane Nicoll 4fac6a91c7 Merge branch '6.1.x' 2024-06-13 14:10:53 +02:00
Stéphane Nicoll d0aa7ad524 Fix invalid character in Javadoc of BeanFactory 2024-06-13 14:06:19 +02:00
Spring Builds 072fc80cdb Next development version (v6.1.10-SNAPSHOT) 2024-06-13 10:27:57 +00:00
Arjen Poutsma df01b013fa Merge branch '6.1.x' 2024-06-13 11:11:13 +02:00
Arjen Poutsma 6f32ff489a Use null stream in ReactorNettyClientResponse if no body is available
Closes gh-32805
2024-06-13 11:10:50 +02:00
Stéphane Nicoll 69c44dee99 Add support for conversion of the whole JSON document
Closes gh-33018
2024-06-13 00:12:33 +02:00
Johnny Lim f3d390a95f Fix package description for org.springframework.validation.annotation
See gh-32532
2024-06-12 17:45:32 +02:00
Juergen Hoeller b196167f19 Merge branch '6.1.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
2024-06-12 14:28:53 +02:00
Juergen Hoeller 24c8dfea1f Remove duplicated javadoc paragraph 2024-06-12 14:23:26 +02:00
Juergen Hoeller cdfe5816c8 Upgrade to Netty 4.1.111 and Awaitility 4.2.1 2024-06-12 14:23:14 +02:00
Juergen Hoeller 8b8604db73 Align after merge from 6.1.x 2024-06-12 13:34:53 +02:00
Juergen Hoeller 4bb755e2d2 Merge branch '6.1.x' 2024-06-12 13:31:38 +02:00
Juergen Hoeller 0ff200b2f1 Trigger cancellation on context close for non-managed objects only
Specifically for prototype/scoped beans and FactoryBean-exposed objects.

Closes gh-33009
2024-06-12 13:31:00 +02:00
Juergen Hoeller 7a7f34f4ad Defensive access to volatile ScheduledFuture field
Includes defensive test arrangement for isInThePast() with at least 1 ms having passed.

See gh-24560
2024-06-12 13:01:58 +02:00
Arjen Poutsma 099d016857 Handle trailing semicolon in Accept-Language
Closes gh-32259
2024-06-12 12:28:26 +02:00
Stéphane Nicoll 1d0af7e5d3 Move TestBeanFactory to example package 2024-06-12 11:05:22 +02:00
Stéphane Nicoll 3f2d9c372d Migrate "Failing" test cases to regular tests
This commit replaces the use of EngineTestKit to test scenarios where
bean override could not process the test class. There is no need to
run an actual test for this as:

1. Regular integration tests are already validating that adding the
annotation triggers the processing as part of executing the test.
2. The entry point is a ContextCustomizer that can easily be invoked
in a regular test.

As part of harmonizing this, AbstractTestBeanIntegrationTestCase can
be nested, and BeanOverrideTestSuite serve no purpose. The tests can
be executed in an IDE without any special setup.
2024-06-12 11:03:14 +02:00
Stéphane Nicoll 1318f65223 Harmonize test class names
This commit harmonizes the class names of the bean override support by
using a consistent prefix for integration test, inspire from the one
that was used in Spring Boot
2024-06-12 08:54:24 +02:00
Stéphane Nicoll 2d48371c6d Revert polish on Bean Override support
This commit revers the removal of the `private` keyword in the examples
of the reference documentation and the tests for consistency. While the
default visibility makes the example more concise, it could imply to the
reader that the field (or the factory method) cannot be private.

Also, there is no need to multiply anything returned from `Objects.hash`
as its very distinct on its own already.
2024-06-12 08:11:18 +02:00
Brian Clozel dc2c8d6094 Add execution metadata to tasks and scheduled tasks
This commit adds new information about the execution and scheduling of
tasks.

The `Task` type now exposes the `TaskExecutionOutcome` of the latest
execution; this includes the instant the execution started, the
execution outcome and any thrown exception.

The `ScheduledTask` contract can now provide the time when the next
execution is scheduled.

Closes gh-24560
2024-06-11 19:34:41 +02:00
Sam Brannen 46dccd8f97 Polishing 2024-06-11 16:39:24 +02:00
Sam Brannen a4912dd5b1 Remove obsolete field
See gh-32992
2024-06-11 16:35:13 +02:00
Sam Brannen f35c39fe1e Clean up warnings in Gradle build 2024-06-11 16:32:14 +02:00
Sam Brannen f481a4b60b Polish reference documentation 2024-06-11 16:31:56 +02:00
Arjen Poutsma 60b5bbe334 Introduce request attributes in RestClient
This commit introduces request attributes in the RestClient and
underlying infrastructure (i.e. HttpRequest).

Closes gh-32027
2024-06-11 15:51:29 +02:00
Stéphane Nicoll c36e270481 Upgrade to Reactor 2024.0.0-M3
Closes gh-33006
2024-06-11 14:47:40 +02:00
Stéphane Nicoll a5432a82e9 Merge branch '6.1.x' 2024-06-11 14:46:32 +02:00
Stéphane Nicoll 261dac87cc Upgrade to Reactor 2023.0.7
Closes gh-33007
2024-06-11 14:42:08 +02:00
Stéphane Nicoll 89e894205a Improve exception message to include affected configuration class
Closes gh-32998
2024-06-11 14:24:28 +02:00
Brian Clozel a6fb7e99a0 Support for Protobuf 4.x
This commit compiles our Protobuf against 4.27, effectively raising our
baseline to 3.9+.

This commit also re-generates all the Java messages from the .proto spec
using the latest protoc binary.

Closes gh-33011
2024-06-11 14:12:55 +02:00
Stéphane Nicoll 2a680934ee Harmonize equals/hashCode of OverrideMetadata to use class identity
This commit harmonizes the equals/hashCode behavior of OverrideMetadata
to always take the implementation class as a factor for its identity.

This is important as two OverrideMetadata implementations could use
the same strategy and other settings while creating the override value
in a totally different way. This commit makes sure they are identified
as different.

Closes gh-33005
2024-06-11 12:03:31 +02:00
Stéphane Nicoll 1be92f82af Polish 2024-06-11 11:58:19 +02:00
Stéphane Nicoll 28f62abda4 Use the field name as a fallback qualifier for Bean Overriding
This commit harmonizes how a candidate bean definition is determined
for overriding using `@TestBean`, `@MockitoBean`, and `@MockitoSpyBean`.

Previously, a qualifier was necessary even if the name of the annotated
field matches the name of a candidate. After this commit, such candidate
will be picked up transparently, the same it is done for regular
autowiring.

This commit also reviews the documentation of the feature as considering
the field means that its name is taken into account to compute a cache
key if by-type lookup is requested.

Closes gh-32939
2024-06-11 11:30:01 +02:00
Sébastien Deleuze 4c7374797e Polishing
Closes gh-32931
2024-06-11 10:20:14 +02:00
Sébastien Deleuze 611367e4bb Add coroutine variant of WebExceptionHandler
See gh-32931
2024-06-11 10:09:17 +02:00
Juergen Hoeller 3d8488a7d8 Upgrade to Micrometer 1.13.1
Closes gh-33000
2024-06-11 09:13:42 +02:00
Juergen Hoeller e43e659983 Merge branch '6.1.x'
# Conflicts:
#	framework-docs/modules/ROOT/pages/core/beans/definition.adoc
#	framework-platform/framework-platform.gradle
#	spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java
2024-06-11 09:11:42 +02:00
Juergen Hoeller fce2f49e46 Polishing (aligned with main) 2024-06-11 09:07:09 +02:00
Juergen Hoeller eca2b9657e Documentation notes for @Bean overriding and bean name matching
Closes gh-32825
2024-06-11 09:06:33 +02:00
Juergen Hoeller e48f37d956 Upgrade to Micrometer 1.12.7
Closes gh-33001
2024-06-11 09:05:48 +02:00
Juergen Hoeller ddc397dd05 Upgrade to spring-javaformat-checkstyle 0.0.42 2024-06-11 09:04:30 +02:00
Stéphane Nicoll 720b7c1dac Merge branch '6.1.x' 2024-06-11 06:53:22 +02:00
Stéphane Nicoll 6b7f0bd4b6 Fix typo 2024-06-11 06:47:42 +02:00
Sébastien Deleuze 68e6b152ef Merge branch '6.1.x' 2024-06-10 22:46:03 +02:00
Sébastien Deleuze c97a895f09 Add support for double backslashes to StringUtils#cleanPath
Closes gh-32962
2024-06-10 22:25:31 +02:00
Juergen Hoeller 42c17eb787 Documentation notes for @Bean overriding and bean name matching
See gh-31052
See gh-28122
2024-06-10 16:43:05 +02:00
Stéphane Nicoll b9a6ba1242 Fix package tangle in bean override tests
This commit fixes a package tangle between the root bean override
package and its sub-packages. This was vastly improved with the
introduction of `@DummyBean` but we still had a few tests that were
at the wrong place.
2024-06-10 15:23:36 +02:00
Stéphane Nicoll 96302a7102 Stop using a conventional suffix for TestBean factory methods
This commit changes how factory method for `@TestBean` usage is
discovered. Previously the field name or bean name suffixed with
'TestOverride' was used. It sounds more natural to just use the
field name or bean name, leaving cases where a suffix is required
to explicitly providing the method name.

As part of this change, the exception messages have been revisited as
it's less since the method name candidates have the exact same name
as the field or bean name. A `()` is added to make it more clear the
name is for a method.

Closes gh-32940
2024-06-10 12:52:21 +02:00
rstoyanchev 5787bc569d Merge branch '6.1.x' 2024-06-10 10:48:49 +01:00
rstoyanchev 3b13f2ed38 Update code-of-conduct email 2024-06-10 10:48:06 +01:00
Stéphane Nicoll 45e9f04b57 Remove TestOverrideMetadata and use dummy implementation
TestOverrideMetadata was doing byName lookup by default, even without
a bean name. This makes writing tests that need to do by type lookup
way more complicated that it should.

This commit introduces DummyBean, that merely replaces two types with
hardcoded values. It also exposes the raw attribute of OverrideMetadata
and doesn't override anything from it to make sure the behavior is not
altered.

Closes gh-32982
2024-06-10 11:27:27 +02:00
Juergen Hoeller 457bf9416c Configure individual timeouts for specific shutdown phases
Closes gh-32985
2024-06-10 11:00:47 +02:00
Stéphane Nicoll b7e4fa06c3 Merge branch '6.1.x' 2024-06-10 10:02:41 +02:00
Stéphane Nicoll a0eebca0cf Merge pull request #32993 from hlmg
* pr/32993:
  Fix typo

Closes gh-32993
2024-06-10 10:02:36 +02:00
hlmg c6c64e6fe7 Fix typo
See gh-32993
2024-06-10 10:00:37 +02:00
Stéphane Nicoll 536de9ac80 Allow MockitoBean to create a mock for a bean that does not exist
This commit aligns the by-type lookup for bean overrides with what was
done when a bean name is present. It now correctly generate a bean
name rather than failing because no bean of that type exists.

Closes gh-32990
2024-06-10 09:57:27 +02:00
Brian Clozel bc98410acf Merge branch '6.1.x' 2024-06-10 09:47:57 +02:00
Brian Clozel 0ca393c0dc Restrict memory allocation in ContentCachingRequestWrapper
Prior to this commit, the `ContentCachingRequestWrapper` could allocate
a `FastByteArrayOutputStream` block that was larger than the content
cache limit given as a consturctor argument. This was due to an
optimization applied in gh-31834 for allocating the right content cache
size when the request size is known.

Fixes gh-32987
2024-06-10 09:46:01 +02:00
Carlos Corbacho e95e4423bb Do not swallow exceptions on failing to release a savepoint
By swallowing the exception on failing to release a savepoint, we are hiding
client code from database errors that they may need to be aware of or handle.

e.g. if the connection is now dead when trying to release the savepoint, by
swallowing the exception here, client code has no way of knowing this now until
the next operation on the database, which will yield a confusing message about
the problem and obscures where the failure occurred as it will be in a different
part of their code that throws any exception.

Swallowing the exception here is also inconsistent with all the other database
calls in the Transaction Object, where we always raise an exception up and let
client code decide how to handle the error.
2024-06-09 13:08:57 +02:00
Brian Clozel 24997b3356 Merge branch '6.1.x' 2024-06-07 19:02:53 +02:00
Brian Clozel 6681394886 Stop observations for async requests in Servlet filter
Prior to this commit, the `ServerHttpObservationFilter` would support
async dispatches and would do the following:

1. start the observation
2. call the filter chain
3. if async has started, do nothing
4. if not in async mode, stop the observation

This behavior would effectively rely on Async implementations to
complete and dispatch the request back to the container for an async
dispatch. This is what Spring web frameworks do and guarantee.

Some implementations complete the async request but do not dispatch
back; as a result, observations could leak as they are never stopped.

This commit changes the support of async requests. The filter now
opts-out of async dispatches - the filter will not be called for those
anymore. Instead, if the application started async mode during the
initial container dispatch, the filter will register an AsyncListener to
be notified of the outcome of the async handling.

Fixes gh-32730
2024-06-07 19:01:57 +02:00
Sébastien Deleuze c39ce10619 Merge branch '6.1.x' 2024-06-07 18:42:10 +02:00
Sébastien Deleuze 172987c874 Ignore checkpointOnRefresh after restore
Closes gh-32978
2024-06-07 18:41:37 +02:00
Stéphane Nicoll 373cf30b75 Polish 2024-06-07 17:11:38 +02:00
Stéphane Nicoll 55a7a49863 Merge pull request #32941 from m4tt30c91
* pr/32941:
  Polish contribution
  Add support for specifying a read timeout for the reactive jdk client

Closes gh-32941
2024-06-07 17:08:49 +02:00
Stéphane Nicoll 329b53309a Polish contribution
See gh-32941
2024-06-07 17:06:28 +02:00
Matteo Cristoforo 916ed5c0a9 Add support for specifying a read timeout for the reactive jdk client
See gh-32941
2024-06-07 17:01:23 +02:00
Stéphane Nicoll 7916f74942 Review TCF cache support for bean override
This commit reviews how bean override support can influence the key of
an application context cached by the TCF. OverrideMetadata and its
subclasses now implement a proper equals/hashCode pair that is tested
in various scenarios.

Due to how the TCF operates, OverrideMetadata has to be computed in
two locations:

1. In a ContextCustomizerFactory, using the metadata in the enclosing
class if any. This determines whether a customizer is needed in the
first place. The computed set of unique metadata identifies the
customizer and participates in the application context cache's key.
2. In the TestExecutionListener so that it knows the override points
it has to process.

Parsing of the metadata based on a test class has been greatly
simplified and moved to OverrideMetadata proper as we don't need several
flavors. 1 and 2 are using the same algorithm with the former wrapping
that in a Set to compute a proper key.

BeanOverrideContextCustomizerEqualityTests provides a framework for
testing edge cases as we only care about whether the created
ContextCustomizer behaves correctly against the identity of another.

Closes gh-32884
2024-06-07 16:44:57 +02:00
Stéphane Nicoll 02517e5011 Polish
This commit reviews the structure of several classes to comply with
our guidelines. Also, rather than exposing a static method to configure
the context in a test, we call the high-level API directly.
2024-06-07 16:44:57 +02:00
Stéphane Nicoll 0165529d97 Align OverrideMetadata arguments and harmonize bean name
Rather than having to override the getBeanName method when there is one,
this commit moves it as a @Nullable argument. This makes sure that
equals and hashCode consistently use the bean name. getBeanName cannot
be final just yet as the test infrastructure overrides it.

Also, arguments are now ordered consistently, which improves code
readability and type signature.
2024-06-07 16:44:57 +02:00
Stéphane Nicoll 8b66eca932 Harmonize OverrideMetadata implementations
This commit makes sure that each OverrideMetadata implementation is
a top level class with a consistent name.
2024-06-07 16:44:57 +02:00
Brian Clozel e8c122c00a Fix MockCookie Partitioned support
See gh-31454
2024-06-07 14:49:15 +02:00
Sam Brannen 9cfd455dde Merge branch '6.1.x' 2024-06-07 14:19:38 +02:00
Thomas Deblock 47a5ebfde6 Support canEncode() for JAXBElement in Jaxb2XmlEncoder
Commit d7970e4ab8 introduced support for JAXBElement in
Jaxb2XmlEncoder's encodeValue() method; however, canEncode() still
returned false for a JAXBElement element type.

This commit revises canEncode() so that it returns true for an element
type that is assignable from JAXBElement.

See gh-30552
See gh-32972
Closes gh-32977
2024-06-07 14:13:59 +02:00
Sébastien Deleuze 20d23584f6 Merge branch '6.1.x' 2024-06-07 13:45:19 +02:00
Sébastien Deleuze 43a113f067 Polishing
See gh-32983
2024-06-07 13:45:09 +02:00
Sébastien Deleuze 8073f32ca6 Merge branch '6.1.x' 2024-06-07 13:36:39 +02:00
Sébastien Deleuze dc250e1cc1 Remove outdated copyright from index.adoc
Closes gh-32983
2024-06-07 13:35:21 +02:00
Sébastien Deleuze b442e0d3d5 Merge branch '6.1.x' 2024-06-07 11:44:36 +02:00
Sébastien Deleuze fe74fcfded Exclude node_modules from NoHttp checks
Closes gh-32980
2024-06-07 11:43:45 +02:00
Arjen Poutsma 35e8f1c423 Support queries in opaque URLs
Closes gh-32920
2024-06-07 11:11:43 +02:00
Brian Clozel 7fc4937199 Add Partitioned cookie attribute support for servers
This commit adds support for the "Partitioned" cookie attribute in
WebFlux servers and the related testing infrastructure.
Note, Undertow does not support this feature at the moment.

Closes gh-31454
2024-06-07 10:03:52 +02:00
Juergen Hoeller 2aabe238c6 Merge branch '6.1.x'
# Conflicts:
#	spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java
2024-06-06 20:47:02 +02:00
Juergen Hoeller 2451bd62b0 Polishing 2024-06-06 20:43:31 +02:00
Juergen Hoeller 624d6dd167 Expose actual result value for @CacheEvict condition
Closes gh-32960
2024-06-06 20:43:04 +02:00
Juergen Hoeller 0ea96b4806 Skip ajc-compiled aspects for ajc-compiled target classes
Includes defensive ignoring of incompatible aspect types.

Closes gh-32970
2024-06-06 20:42:07 +02:00
Sébastien Deleuze 7b9cbd7876 Add support for Kotlin BeanPostProcessor beans
This commit adds support for Kotlin BeanPostProcessor beans which should
be defined in a companion object and annotated with `@JvmStatic`.

Closes gh-32946
2024-06-06 19:23:25 +02:00
Simon Baslé 0758ae5ead Polishing: remove unused import 2024-06-06 16:55:12 +02:00
Simon Baslé d38e4d869f Better support for FactoryBeans in BeanOverrideBeanFactoryPostProcessor
This commit makes sure to account for FactoryBean names when registering
a bean override. In the case of ReplaceDefinition mode, if there is a
factory bean name, it is used to check singleton status and as the name
in the registrar.

Closes gh-32971
2024-06-06 15:49:40 +02:00
Alexej Timonin 416eff1b04 Fix typo in WebTestClient expectedXml
Closes gh-32969
2024-06-06 14:24:40 +02:00
Brian Clozel 52af43d6d2 Handle ResponseStatusException thrown by MVC functional endpoints
Prior to this commit, exceptions thrown by MVC functional handlers would
not be considered by `ExceptionHandlerExceptionResolver`. This means
that common exceptions would not be handled consistently between
annotated and functional handlers. This is true, for example, for all
`ProblemDetails`-related exception handling.

While MVC functional and annotation models are separate concepts,
WebFlux has a different error handling model that processes all
exceptions in a central place.

This commit ensures that `ExceptionHandlerExceptionResolver` considers
exceptions thrown by handlers of type `HandlerFunction<?>` and processes
them accordingly.

Closes gh-32689
2024-06-06 14:21:17 +02:00
Arjen Poutsma 859b97ce05 Revert "Do not read Map in FormHttpMessageConverter"
This reverts commit 726ac9110c and
80faa94afc.

See gh-32826
2024-06-06 12:39:18 +02:00
Stéphane Nicoll c127421e38 Revert "Disable warnings for deprecated for removal in Eclipse"
We should not disable such warnings
2024-06-06 11:44:09 +02:00
Sébastien Deleuze d39fe9a444 Merge branch '6.1.x' 2024-06-06 10:06:24 +02:00
Sébastien Deleuze c28a0d5627 Add missing hints for Hibernate @TenantId
Closes gh-32967
2024-06-06 10:04:35 +02:00
Juergen Hoeller 09c1081645 Merge branch '6.1.x' 2024-06-06 08:55:16 +02:00
Juergen Hoeller 61d045ce52 Polishing 2024-06-06 08:54:37 +02:00
Juergen Hoeller c0bef2c693 Lazily start resources on demand (if necessary outside of lifecycle)
See gh-32945
2024-06-06 08:54:32 +02:00
Stéphane Nicoll 5706ee1762 Merge branch '6.1.x' 2024-06-06 08:08:47 +02:00
Stéphane Nicoll c3a0eaa95e Merge pull request #32966 from ypyf
* pr/32966:
  Use HttpStatusCode consistently in reference guide

Closes gh-32966
2024-06-06 08:08:45 +02:00
ypyf e12d1259d1 Use HttpStatusCode consistently in reference guide
See gh-32966
2024-06-06 08:06:33 +02:00
Brian Clozel 316e531c69 Merge branch '6.1.x' 2024-06-05 20:05:50 +02:00
Brian Clozel 404c4d9d92 Support @Valid on container elements for handler arguments
Prior to this commit, #31870 added support for constraint annotations on
container elements for handler method argument validation. Supporting
this use case:

```
public void addNames(List<@NotEmpty String> names)
```

This commit does the same for `@Valid` annotation:

```
public void addPeople(List<@Valid Person> people)
```

Fixes gh-32964
2024-06-05 20:02:46 +02:00
Juergen Hoeller 3305485d1e Merge branch '6.1.x' 2024-06-05 16:33:44 +02:00
Juergen Hoeller 7785f94c4c Revise and align Reactor client lifecycle management
Closes gh-32945
2024-06-05 16:32:40 +02:00
Juergen Hoeller 4f6f2c0d41 Revert to separate get/put steps against method cache for concurrency
Closes gh-32958
2024-06-05 16:32:27 +02:00
Sam Brannen 667b74b53f Return all events from EngineTestKitUtils.executeTestsForClass() 2024-06-05 16:29:11 +02:00
Sam Brannen 17e4c241c3 Avoid use of deprecated AssertJ APIs 2024-06-05 14:50:30 +02:00
Sam Brannen 43a60a7e3f Polishing 2024-06-05 14:50:01 +02:00
Sam Brannen 9e1ef83669 Avoid issues with system line separator in tests
See f10caf6aa6
2024-06-05 12:36:58 +02:00
rstoyanchev f4f89aa2a4 Add headers to data binding values
Closes gh-32676
2024-06-05 11:30:32 +01:00
rstoyanchev 23160a43dd Conditional use of URI vars for data binding in WebFlux
This commit aligns Spring WebFlux with WebMvc in adding URI variables
conditionally if not already in the map. The idea is that data
binding is primarily through form data and query params, with URI
variables, and request headers (to be implemented next) also made
available but without shadowing existing values.

See gh-32676
2024-06-05 11:30:32 +01:00
rstoyanchev 398aae2b9a Polishing in data binding tests
See gh-32676
2024-06-05 11:30:32 +01:00
Stéphane Nicoll 36b0702c0b Merge branch '6.1.x' 2024-06-05 10:45:06 +02:00
Stéphane Nicoll e6da2a86fc Merge pull request #32957 from soglad
* pr/32957:
  Fix entity name in MappingSqlQuery example of reference guide

Closes gh-32957
2024-06-05 10:45:01 +02:00
Tony Wen 301087e510 Fix entity name in MappingSqlQuery example of reference guide
See gh-32957
2024-06-05 10:43:14 +02:00
Juergen Hoeller a26d31ee3a Merge branch '6.1.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
2024-06-05 00:02:33 +02:00
Juergen Hoeller 6c054f88ea Defensively handle UncheckedIOException cause (for NullAway compliance) 2024-06-05 00:01:52 +02:00
Juergen Hoeller f58c7d80cc Upgrade to SLF4J 2.0.13, Jetty 12.0.10, Netty 4.1.110, JRuby 9.4.7 2024-06-04 23:44:54 +02:00
Juergen Hoeller e5be10d53d Consistently throw IOException from ReactorNettyClientResponse
Aligned with ReactorNettyClientRequest.

See gh-32952
2024-06-04 23:43:10 +02:00
Juergen Hoeller 017bf4534d Merge branch '6.1.x' 2024-06-04 23:00:46 +02:00
Juergen Hoeller 524da905db Consistently throw IOException from ReactorNettyClientRequest
This commit renames ReactorNettyClientRequestFactoryTests.

Closes gh-32952
2024-06-04 22:59:29 +02:00
Juergen Hoeller 4323c60513 Common context lifecycle management for ReactorResourceFactory
This commit moves ReactorResourceFactoryTests to same package.

Closes gh-32945
2024-06-04 22:59:18 +02:00
Juergen Hoeller 28eb9aebcf Add BeanFactoryInitializer callback before preInstantiateSingletons
Closes gh-32836
2024-06-04 22:50:42 +02:00
Juergen Hoeller f10caf6aa6 Compare text with system line separator (for Windows compatibility)
See gh-32756
2024-06-04 22:50:14 +02:00
Sam Brannen cf3171dae0 Find unique @⁠TestBean factory methods in class hierarchy
I accidentally introduced a regression in commit d185bb1d97 by no
longer checking the number of unique method names found when searching
for @⁠TestBean factory methods.

This commit reintroduces that check and introduces a proper unit test
in TestBeanOverrideProcessorTests.

It turns out that we already had an integration test that was intended
to check for this scenario; however, that test actually did not test
this scenario due to a copy-and-paste error. Thus, this commit also
updates TestBeanInheritanceIntegrationTests so that
fieldInSupertypeWithPrioritizedFactoryMethodInSubtype() tests what it's
supposed to.
2024-06-04 18:47:32 +02:00
Sam Brannen 069c6788f5 Polishing 2024-06-04 18:47:32 +02:00
Stéphane Nicoll aa4b226a22 Add support for converting json values using AssertFactory
This commit benefits from a feature introduced in AssertJ 3.26.0, see
https://github.com/assertj/assertj/pull/3377.

This allows to use any AssertFactory and convert the actual value to
the type the factory manages. Previously, we were using
ParameterizedTypeReference to express the type with its generic
signature but the returned assert object would not be narrowed to the
converted type.

Thanks to this change, we can request to convert the actual value to
`InstanceOfAssertFactories.list(Member.class)` and get a `ListAssert`
of `Member` as a result, rather than an `ObjectAssert` of `List<User>`.

Thanks very much to @scordio for his efforts.

Closes gh-32953
2024-06-04 17:11:08 +02:00
Sébastien Deleuze 6212831f5f Merge branch '6.1.x' 2024-06-04 16:47:36 +02:00
Sébastien Deleuze f6b608eecb Consistently support Hibernate annotation hint inference on methods
See gh-32842
2024-06-04 16:46:25 +02:00
Sébastien Deleuze 4da1511ed3 Infer hints for Hibernate generators
This commit updates
PersistenceManagedTypesBeanRegistrationAotProcessor
in order to infer hints for Hibernate annotations meta
annotated with `@ValueGenerationType` (like `@CreationTimestamp`)
and `@IdGeneratorType`.

`@GenericGenerator` is not supported as it is deprecated as of
Hibernate 6.5.

Closes gh-32842
2024-06-04 16:46:25 +02:00
Stéphane Nicoll 5cd4b87bfa Merge branch '6.1.x' 2024-06-04 15:52:26 +02:00
Stéphane Nicoll 7102c33661 Add section about using complex data structures with AOT
Closes gh-32273
2024-06-04 15:51:40 +02:00
Sam Brannen 4d961fa472 Find @⁠TestBean factory methods in multi-level @⁠Nested hierarchy
Prior to this commit, a @⁠TestBean factory method was found in the
directly enclosing class for a @⁠Nested test class; however, such a
factory method was not found in the enclosing class of the enclosing
class, etc.

This commit updates the search algorithm for @⁠TestBean factory methods
so that it recursively searches the enclosing class hierarchy for
@⁠Nested test classes.

Closes gh-32951
2024-06-04 15:36:40 +02:00
Sam Brannen f68130d2e5 Update Javadoc for @⁠TestBean support
See gh-32943
2024-06-04 15:12:06 +02:00
Stéphane Nicoll 42ace2c2c9 Provide dedicated AOT exception hierarchy
This commit adds a number of catch point that provides additional
context when an AOT processor fails to execute. Amongst other things,
this makes sure that the bean name and its descriptor is consistently
provided in the error message when available.

Closes gh-32777
2024-06-04 09:36:21 +02:00
Sébastien Deleuze f31113e325 Merge branch '6.1.x' 2024-06-03 18:58:33 +02:00
Sébastien Deleuze 43409b00d0 Refine KotlinDetector.isKotlinType documentation
This commit documents changes in lambda detection
as of Kotlin 2.0.

Closes gh-32905
2024-06-03 18:58:13 +02:00
Sébastien Deleuze eefdf42e7e Merge branch '6.1.x' 2024-06-03 18:28:17 +02:00
Sébastien Deleuze d55abc6cf9 Fix RegisterReflectionForBinding Javadoc
Closes gh-32947
2024-06-03 18:26:24 +02:00
Sébastien Deleuze 31806f3a6b Fix MethodValidationPostProcessor refdoc
Closes gh-32929
2024-06-03 18:20:52 +02:00
Sam Brannen acdd8a0015 Improve exception handling in bean override support
- Do not silently abort bean override processing if the ApplicationContext
  is not a BeanDefinitionRegistry.

- Include conflicting bean names in error messages instead of just the
  number of conflicting beans.

- Consistently throw IllegalStateException.

- etc.
2024-06-03 16:57:19 +02:00
Sam Brannen 7a11899c0c Stop using deprecated ThemeChangeInterceptor in WebConfiguration example 2024-06-03 16:14:07 +02:00
Sam Brannen d185bb1d97 Support @⁠TestBean factory methods defined in interfaces
Prior to this commit, @⁠TestBean factory methods were required to be
defined in the test class or one of its superclasses. However, users
may wish to define common factory methods in interfaces that can be
shared easily across multiple test classes simply by implementing the
necessary interface(s).

This commit therefore switches from ReflectionUtils to
MethodIntrospector to find @⁠TestBean factory methods in implemented
interfaces within the type hierarchy of the test class.

Closes gh-32943
2024-06-03 16:04:46 +02:00
Stéphane Nicoll 6a761412a8 Simplify BeanRegistrationsAotProcessor
Closes gh-32944
2024-06-03 16:01:12 +02:00
Juergen Hoeller 34eccbe8e6 Remove final declaration from getMessageSource() and getLocale() methods
Includes checking the Servlet 3.0+ ServletRequest.getServletContext() method in the request-only constructors, being able to fall back to the root WebApplicationContext.

See gh-32926
2024-06-03 15:27:33 +02:00
Andre Blanke a582e48dd0 Use getMessageSource internally in RequestContext 2024-06-03 15:22:44 +02:00
Sam Brannen 9ceaf21d24 Extract findMethods() logic in TestBeanOverrideProcessor 2024-06-03 14:56:43 +02:00
Sam Brannen 1536f34fff Fix broken tests 2024-06-03 14:40:13 +02:00
Sam Brannen 8047a22237 Polish TestBeanOverrideProcessor 2024-06-03 13:29:50 +02:00
Juergen Hoeller f7e7d1b7b0 Merge branch '6.1.x' 2024-06-03 12:47:17 +02:00
Juergen Hoeller 8a84241c1e Polishing 2024-06-03 12:46:31 +02:00
Juergen Hoeller 624be6d4e6 Report bean creation failure in sortAdvisors as AopConfigException
Closes gh-32230
2024-06-03 12:46:14 +02:00
Juergen Hoeller b08883b65c Avoid NoSuchMethodException for annotation attribute checks
Closes gh-32921
2024-06-03 12:45:11 +02:00
Sam Brannen df238d08eb Polishing 2024-05-31 18:01:49 +02:00
Sam Brannen 742c41a568 Polishing 2024-05-31 16:18:31 +02:00
Sam Brannen 3a448701f7 Improve class names 2024-05-31 15:49:26 +02:00
Sam Brannen 967800a2f9 Merge branch '6.1.x' 2024-05-31 12:23:22 +02:00
Cong-Xin Cynthia Qiu 542ba3517f Fix typo in Jakarta validation documentation
Closes gh-32928
2024-05-31 12:22:02 +02:00
Sam Brannen 87c93d35d6 Revise bean override tests with a focus on AOT support
As a follow up to the previous commit (31f8e12adb), this commit
polishes bean override tests and revises them with a focus on AOT
testing support and simplified maintenance.

- Introduce EngineTestKitUtils to simplify working with JUnit's
  EngineTestKit.

- Use idiomatic EngineTestKit APIs to simplify assertions on
  EngineTestKit results.

- Introduce BeanOverrideTestSuite to simplify running all bean override
  tests within the IDE.

- Separate failure and success scenario tests, so that failure tests do
  not launch the JUnit Platform to run tests using the Spring
  TestContext Framework (TCF) within a test class that itself uses the
  TCF.

- Make AbstractTestBeanIntegrationTestCase actually abstract.

- Rename test case classes to give them meaningful names and simplify
  understanding of what's being tested.

- Ensure tests for @⁠MockitoSpyBean functionality use @⁠MockitoSpyBean
  instead of @⁠MockitoBean.

- Declare @⁠Configuration classes local to @⁠SpringJUnitConfig test
  classes whenever possible.

See gh-29122
See gh-32925
2024-05-31 12:19:31 +02:00
Sam Brannen 31f8e12adb Separate failure and success scenario tests for @⁠TestBean
This commit also ensures that @⁠Bean methods are declared within
@⁠Configuration classes instead of within test classes.

See gh-29122
2024-05-29 14:21:58 +02:00
Sam Brannen 1f537b97d5 Demonstrate how to disable Bean Override tests in AOT mode
See gh-29122
2024-05-29 14:20:35 +02:00
Sam Brannen cade3c7b0e Ensure MockMvcTesterIntegrationTests runs in AOT mode
See gh-29122
2024-05-29 13:32:22 +02:00
Sam Brannen a0c9a204b8 Polishing 2024-05-29 13:32:02 +02:00
Juergen Hoeller 8f21137883 Merge branch '6.1.x' 2024-05-28 18:47:38 +02:00
Juergen Hoeller 8c6a7799be Upgrade to Checkstyle 10.17 2024-05-28 18:46:22 +02:00
Juergen Hoeller 557dbba585 Remove superfluous addToClassHierarchy call for Enum types
Closes gh-32906
2024-05-28 18:45:05 +02:00
Juergen Hoeller 5a275443b5 Apply ThreadLocal#remove() to pre-instantiation threads
See gh-13410
See gh-32874
2024-05-28 16:35:58 +02:00
Sam Brannen 27985b1439 Disable class data sharing (CDS) for tests
Prior to this commit, the Gradle build output the following warning
multiple times.

OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended

Since we don't need CDS enabled for our tests, I've added `-Xshare:off`
as a JVM argument for our tests to disable CDS.
2024-05-28 15:58:02 +02:00
Stéphane Nicoll bad4e18b4d Add support for building a request directly from MockMvcTester
Closes gh-32913'
2024-05-28 15:33:21 +02:00
Sam Brannen defb6b7a62 Polish documentation and implementation of SpEL's Indexer 2024-05-28 15:29:54 +02:00
Stéphane Nicoll 8d2bc3bdba Add support for fluent preparation of the request in MockMvcTester
See gh-32913
2024-05-28 15:29:14 +02:00
Stéphane Nicoll a3e7fd47c6 Allow MockHttpServletRequestBuilder to support AssertJ
This commit moves the features of MockHttpServletRequestBuilder in
an abstract class so that another class can offer the same feature
whilst providing AssertJ support. This wasn't possible previously as
the builder's return type would lose the concrete builder types.

This change benefits MockMultipartHttpServletRequestBuilder that can
use the same mechanism to offer additional settings.

This change also makes it so that a builder instance can be created
using only the HttpMethod. Previously, the URI had to be provided as
well and that makes it impossible to specify it using the builder.

See gh-32913
2024-05-28 15:29:14 +02:00
Arjen Poutsma 726ac9110c Do not read Map in FormHttpMessageConverter
This commit ensures that the FormHttpMessageConverter no longer supports
 reading Maps (just MultiValueMaps). Plain maps are often used to
 represent JSON.

See gh-32826
2024-05-28 15:25:08 +02:00
Stéphane Nicoll fc54cf4430 Harmonize use of uri in MockMvc
Closes gh-32915
2024-05-28 11:17:40 +02:00
Sam Brannen 54c07eddcc Merge branch '6.1.x' 2024-05-28 10:26:56 +02:00
Sam Brannen e9de426eb5 Support compilation of map indexing with primitive in SpEL
Prior to this commit, the Spring Expression Language (SpEL) failed to
compile an expression that indexed into a Map using a primitive literal
(boolean, int, long, float, or double).

This commit adds support for compilation of such expressions by
ensuring that primitive literals are boxed into their corresponding
wrapper types in the compiled bytecode.

Closes gh-32903
2024-05-28 10:19:15 +02:00
Stéphane Nicoll 2d1e58b928 Polish 2024-05-28 09:31:44 +02:00
Stéphane Nicoll f6504c5f91 Deprecate use of raw String for HttpMethod in MockMvc
Closes gh-32914
2024-05-28 09:24:08 +02:00
Sam Brannen 8871d67298 Merge branch '6.1.x' 2024-05-27 17:13:01 +02:00
Sam Brannen cda577d1aa Support compilation of array and list indexing with Integer in SpEL
Prior to this commit, the Spring Expression Language (SpEL) failed to
compile an expression that indexed into any array or list using an
Integer.

This commit adds support for compilation of such expressions by
ensuring that an Integer is unboxed into an int in the compiled
bytecode.

See gh-32694
Closes gh-32908
2024-05-27 17:06:48 +02:00
Marcus Hert Da Coregio 57fae7a59e Add update-antora-ui-spring.yml workflow 2024-05-27 16:56:13 +02:00
Sam Brannen b3cc603401 Avoid usage of deprecated AssertJ feature 2024-05-27 16:51:39 +02:00
Sam Brannen 870d15c0b6 Merge branch '6.1.x' 2024-05-27 16:44:19 +02:00
Sam Brannen 8feb842df5 Upgrade to AssertJ 3.26.0
See https://github.com/assertj/assertj/issues/3322
2024-05-27 16:43:22 +02:00
Brian Clozel 3b53165574 Expose WebSocketMessageBrokerStats contracts
Prior to this commit, the `WebSocketMessageBrokerStats` would be in
charge of periodically logging WebSocket stats. This class would also
publicly expose each stats type with dedicated methods, as `String`.
This would not allow observation libraries to easily extract information
and turn them into metrics.

This commit introduces new methods exposing the `Stats` types directly
and deprecates the former `String` variants. This will allow
observability libraries like Micrometer to expose this as metrics:

```
MeterRegistry meterRegistry = ...;

Gauge.builder("spring.stomp.frames", stats.getStompSubProtocolStats(),
      StompSubProtocolHandler.Stats::getTotalConnect)
  .tag("type", "CONNECT")
  .description("number of CONNECT frames processed")
  .register(meterRegistry);
```

Closes gh-31604
2024-05-27 16:06:32 +02:00
Brian Clozel e856e7e590 Add checkstyle rule for "@since" javadoc convention 2024-05-27 09:28:23 +02:00
Stéphane Nicoll e2c5887cea Allow JSON content assertions to be nested
Previously, AbstractJsonContentAssert worked on a raw String, which
made standard AssertJ nested calls, such as satisfies, to return an
assert on the raw string, rather than one with JSON support.

This commit rework AbstractJsonContentAssert so that it no longer
extend from AbstractStringAssert. This makes the list of methods more
focused on JSON assertions, and allow standard operations to provide
the right assert object.

Closes gh-32894
2024-05-27 09:25:12 +02:00
Sam Brannen 489d18a169 Merge branch '6.1.x' 2024-05-24 15:42:39 +02:00
Sam Brannen ea2931f24a Use Develocity Gradle plugin API to avoid deprecation warning
Prior to this commit, the Gradle build issued the following warning.

- The deprecated "gradleEnterprise.buildScan.value" API has been
  replaced by "develocity.buildScan.value"
2024-05-24 15:41:58 +02:00
Sam Brannen 7e3a4a12f8 Use consistent version strings for 6.2 2024-05-24 15:19:30 +02:00
Sam Brannen b82b83c8f0 Disable warnings for deprecated for removal in Eclipse 2024-05-24 14:30:56 +02:00
Sam Brannen 5d39598025 Disable warnings for unclosed @⁠AutoCloseable in Eclipse 2024-05-24 14:15:25 +02:00
Sam Brannen 159c2cd7c6 Remove obsolete code 2024-05-24 14:14:43 +02:00
Sam Brannen dac18a3ff1 Clean up warnings in Gradle build 2024-05-24 13:39:56 +02:00
Sam Brannen 77f7da01e4 Polishing 2024-05-24 13:39:56 +02:00
Sam Brannen e999f4e47d Sync changes to MockHttpServletRequest 2024-05-24 13:39:55 +02:00
Sam Brannen e3c268ef18 Fix formatting 2024-05-24 13:39:55 +02:00
Juergen Hoeller 49caa02584 Merge branch '6.1.x' 2024-05-24 13:06:21 +02:00
Juergen Hoeller 26d1c38d84 Polishing 2024-05-24 13:05:49 +02:00
Juergen Hoeller dae4366325 Merge branch '6.1.x' 2024-05-24 11:55:53 +02:00
Juergen Hoeller 345daaabbc Detect original generic method for CGLIB bridge method
Closes gh-32888
2024-05-24 11:49:10 +02:00
Arjen Poutsma 903493e9a9 Various MultiValueMap improvements
This commit makes several improvements to MultiValueMap:
- asSingleValueMap offers a single-value view (as opposed to the
  existing toSingleValueMap, which offers a copy)
- fromSingleValue is a static method that adapts a Map<?,?> to the
  MultiValueMap interface
- fromMultiValue is a static method that adapts a Map<?,List<?>> to the
  MultiValueMap interface

Closes gh-32832
2024-05-24 11:44:55 +02:00
Stéphane Nicoll 97647ef5f6 Flag tests using deprecated json method deprecated
See gh-32791
2024-05-24 11:03:33 +02:00
Juergen Hoeller 0110c5ac82 Merge branch '6.1.x' 2024-05-23 17:08:22 +02:00
Juergen Hoeller 6c08d93992 Polishing 2024-05-23 17:07:55 +02:00
Juergen Hoeller 6d7cd9c7dc Defensive handling of incompatible advice methods
This covers AspectJ transaction and caching aspects when encountered by Spring AOP.

Closes gh-32882
See gh-32793
2024-05-23 17:07:51 +02:00
Juergen Hoeller 35278d09ac Polishing 2024-05-23 16:34:24 +02:00
Stéphane Nicoll 975e2f4218 Revert "Avoid deprecation warnings for WebJarsResourceResolver"
This reverts commit 61db499ae2.
2024-05-23 16:21:42 +02:00
Stéphane Nicoll 0ac7e41beb Provide an implementation of JsonComparator
See gh-32791
2024-05-23 16:17:02 +02:00
Sébastien Deleuze f62275d674 Merge branch '6.1.x' 2024-05-23 16:05:54 +02:00
Attacktive 73eb6f0660 Complete a Kotlin code snippet in the refdoc
Closes gh-32877
2024-05-23 16:03:34 +02:00
Brian Clozel 51f6e78e25 Fall back on */* during content negotiation for errors
Prior to this commit, gh-31936 enabled content negotiation for
`@ExceptionHandler` annotated methods in Spring MVC and WebFlux.
In the case of WebFlux, HTTP clients sending invalid media types in the
"Accept" request header would fail with a `NotAcceptableStatusException`
This exception would be handled with an HTTP 406 response status,
instead of processing the original exception.

This commit ensures that invalid media types are ignored during the
exception handling phase and that we fall back to "*/*".

Fixes gh-32878
2024-05-23 13:57:02 +02:00
Stéphane Nicoll 94348d9d41 Revert "Merge pull request #32876 from quaff"
This reverts commit 3b2a4da023, reversing
changes made to 181b68088a.

See gh-32876
2024-05-23 13:13:02 +02:00
Phillip Webb d8dcd3af0b Introduce JSON comparison abstraction for tests
This commit introduces a JsonComparator abstraction, with an
implementation using JSONAssert. Previously, JSONAssert was the only
choice.

Test APIs have been adapted to allow the new abstraction while relying
on JSONAssert still for high-level methods.

Closes gh-32791

Co-authored-by: Stéphane Nicoll <stephane.nicoll@broadcom.com>
2024-05-23 12:32:39 +02:00
Arjen Poutsma 80faa94afc Support Map in FormHttpMessageConverter
This commit changes the FormHttpMessageConverter from a
HttpMessageConverter<MultiValueMap<String, ?>> to a
HttpMessageConverter<Map<String, ?>>, so that normal, single-value maps
can also be used as form representation, both for reading and writing.

Closes gh-32826
2024-05-23 10:33:49 +02:00
Arjen Poutsma 67d2b2566e Revert "WIP"
This reverts commit c09b0f57631905a7b9cca32be5516853e4263ac0.
2024-05-23 10:33:49 +02:00
Arjen Poutsma 14861024d5 WIP 2024-05-23 10:33:49 +02:00
Stéphane Nicoll fa275f908e Polish 2024-05-23 08:49:03 +02:00
Stéphane Nicoll 3b2a4da023 Merge pull request #32876 from quaff
* pr/32876:
  Polish "Extend nested placeholders resolution to any CharSequence"
  Extend nested placeholders resolution to any CharSequence

Closes gh-32876
2024-05-23 08:41:59 +02:00
Stéphane Nicoll 79b5ee75d3 Polish "Extend nested placeholders resolution to any CharSequence"
See gh-32876
2024-05-23 08:36:34 +02:00
Yanming Zhou 5a7bfa9dec Extend nested placeholders resolution to any CharSequence
See gh-32876
2024-05-23 08:36:15 +02:00
Stéphane Nicoll 181b68088a Merge branch '6.1.x' 2024-05-23 08:14:59 +02:00
Stéphane Nicoll 31f298b929 Merge pull request #32874 from Seungpang
* pr/32874:
  Polish
  Document using ThreadLocal#remove instead of ThreadLocal#set(null)

Closes gh-32874
2024-05-23 08:14:00 +02:00
Stéphane Nicoll c01aab5850 Polish
See gh-32874
2024-05-23 08:12:30 +02:00
Seungrae 61ef5a8930 Document using ThreadLocal#remove instead of ThreadLocal#set(null)
See gh-32874
2024-05-23 08:10:54 +02:00
Spring Builds 3b53ee7038 Next development version (v6.1.9-SNAPSHOT) 2024-05-22 16:45:49 +00:00
2081 changed files with 52013 additions and 21985 deletions
-17
View File
@@ -1,17 +0,0 @@
<!--
!!! For Security Vulnerabilities, please go to https://spring.io/security-policy !!!
-->
**Affects:** \<Spring Framework version>
---
<!--
Thanks for taking the time to create an issue. Please read the following:
- Questions should be asked on Stack Overflow.
- For bugs, specify affected versions and explain what you are trying to do.
- For enhancements, provide context and describe the problem.
Issue or Pull Request? Create only one, not both. GitHub treats them as the same.
If unsure, start with an issue, and if you submit a pull request later, the
issue will be closed as superseded.
-->
+6
View File
@@ -0,0 +1,6 @@
blank_issues_enabled: false
contact_links:
- name: Community Support
url: https://stackoverflow.com/tags/spring
about: Please ask and answer questions on StackOverflow with the tag `spring`.
+23
View File
@@ -0,0 +1,23 @@
---
name: General
about: Bugs, enhancements, documentation, tasks.
title: ''
labels: ''
assignees: ''
---
<!--
Have you considered asking for help on stackoverflow.com?
** Bug Reports **
Please submit issues against OSS supported versions, see https://spring.io/projects/spring-framework#support
Please provide a minimal sample application that reproduces the problem for faster issue triage.
** Enhancements requests **
Before explaining how you would like things to work,
please describe a concrete use case for this feature and how you have tried to solve this so far.
-->
@@ -0,0 +1,20 @@
name: Await HTTP Resource
description: 'Waits for an HTTP resource to be available (a HEAD request succeeds)'
inputs:
url:
description: 'URL of the resource to await'
required: true
runs:
using: composite
steps:
- name: Await HTTP resource
shell: bash
run: |
url=${{ inputs.url }}
echo "Waiting for $url"
until curl --fail --head --silent ${{ inputs.url }} > /dev/null
do
echo "."
sleep 60
done
echo "$url is available"
+61
View File
@@ -0,0 +1,61 @@
name: 'Build'
description: 'Builds the project, optionally publishing it to a local deployment repository'
inputs:
develocity-access-key:
description: 'Access key for authentication with ge.spring.io'
required: false
java-distribution:
description: 'Java distribution to use'
required: false
default: 'liberica'
java-early-access:
description: 'Whether the Java version is in early access'
required: false
default: 'false'
java-toolchain:
description: 'Whether a Java toolchain should be used'
required: false
default: 'false'
java-version:
description: 'Java version to compile and test with'
required: false
default: '17'
publish:
description: 'Whether to publish artifacts ready for deployment to Artifactory'
required: false
default: 'false'
outputs:
build-scan-url:
description: 'URL, if any, of the build scan produced by the build'
value: ${{ (inputs.publish == 'true' && steps.publish.outputs.build-scan-url) || steps.build.outputs.build-scan-url }}
version:
description: 'Version that was built'
value: ${{ steps.read-version.outputs.version }}
runs:
using: composite
steps:
- name: Prepare Gradle Build
uses: ./.github/actions/prepare-gradle-build
with:
develocity-access-key: ${{ inputs.develocity-access-key }}
java-distribution: ${{ inputs.java-distribution }}
java-early-access: ${{ inputs.java-early-access }}
java-toolchain: ${{ inputs.java-toolchain }}
java-version: ${{ inputs.java-version }}
- name: Build
id: build
if: ${{ inputs.publish == 'false' }}
shell: bash
run: ./gradlew check antora
- name: Publish
id: publish
if: ${{ inputs.publish == 'true' }}
shell: bash
run: ./gradlew -PdeploymentRepository=$(pwd)/deployment-repository build publishAllPublicationsToDeploymentRepository
- name: Read Version From gradle.properties
id: read-version
shell: bash
run: |
version=$(sed -n 's/version=\(.*\)/\1/p' gradle.properties)
echo "Version is $version"
echo "version=$version" >> $GITHUB_OUTPUT
@@ -0,0 +1,27 @@
name: Create GitHub Release
description: 'Create the release on GitHub with a changelog'
inputs:
milestone:
description: 'Name of the GitHub milestone for which a release will be created'
required: true
pre-release:
description: 'Whether the release is a pre-release (a milestone or release candidate)'
required: false
default: 'false'
token:
description: 'Token to use for authentication with GitHub'
required: true
runs:
using: composite
steps:
- name: Generate Changelog
uses: spring-io/github-changelog-generator@185319ad7eaa75b0e8e72e4b6db19c8b2cb8c4c1 #v0.0.11
with:
config-file: .github/actions/create-github-release/changelog-generator.yml
milestone: ${{ inputs.milestone }}
token: ${{ inputs.token }}
- name: Create GitHub Release
shell: bash
env:
GITHUB_TOKEN: ${{ inputs.token }}
run: gh release create ${{ format('v{0}', inputs.milestone) }} --notes-file changelog.md ${{ inputs.pre-release == 'true' && '--prerelease' || '' }}
@@ -17,4 +17,12 @@ changelog:
- "type: dependency-upgrade"
contributors:
exclude:
names: ["bclozel", "jhoeller", "poutsma", "rstoyanchev", "sbrannen", "sdeleuze", "snicoll", "simonbasle"]
names:
- "bclozel"
- "jhoeller"
- "poutsma"
- "rstoyanchev"
- "sbrannen"
- "sdeleuze"
- "simonbasle"
- "snicoll"
@@ -0,0 +1,53 @@
name: Prepare Gradle Build
description: 'Prepares a Gradle build. Sets up Java and Gradle and configures Gradle properties'
inputs:
develocity-access-key:
description: 'Access key for authentication with ge.spring.io'
required: false
java-distribution:
description: 'Java distribution to use'
required: false
default: 'liberica'
java-early-access:
description: 'Whether the Java version is in early access. When true, forces java-distribution to temurin'
required: false
default: 'false'
java-toolchain:
description: 'Whether a Java toolchain should be used'
required: false
default: 'false'
java-version:
description: 'Java version to use for the build'
required: false
default: '17'
runs:
using: composite
steps:
- name: Set Up Java
uses: actions/setup-java@v4
with:
distribution: ${{ inputs.java-early-access == 'true' && 'temurin' || (inputs.java-distribution || 'liberica') }}
java-version: |
${{ inputs.java-early-access == 'true' && format('{0}-ea', inputs.java-version) || inputs.java-version }}
${{ inputs.java-toolchain == 'true' && '17' || '' }}
- name: Set Up Gradle
uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
with:
cache-read-only: false
develocity-access-key: ${{ inputs.develocity-access-key }}
- name: Configure Gradle Properties
shell: bash
run: |
mkdir -p $HOME/.gradle
echo 'systemProp.user.name=spring-builds+github' >> $HOME/.gradle/gradle.properties
echo 'systemProp.org.gradle.internal.launcher.welcomeMessageEnabled=false' >> $HOME/.gradle/gradle.properties
echo 'org.gradle.daemon=false' >> $HOME/.gradle/gradle.properties
echo 'org.gradle.daemon=4' >> $HOME/.gradle/gradle.properties
- name: Configure Toolchain Properties
if: ${{ inputs.java-toolchain == 'true' }}
shell: bash
run: |
echo toolchainVersion=${{ inputs.java-version }} >> $HOME/.gradle/gradle.properties
echo systemProp.org.gradle.java.installations.auto-detect=false >> $HOME/.gradle/gradle.properties
echo systemProp.org.gradle.java.installations.auto-download=false >> $HOME/.gradle/gradle.properties
echo systemProp.org.gradle.java.installations.paths=${{ format('$JAVA_HOME_{0}_X64', inputs.java-version) }} >> $HOME/.gradle/gradle.properties
@@ -1,5 +1,5 @@
name: Print JVM thread dumps
description: Prints a thread dump for all running JVMs
description: 'Prints a thread dump for all running JVMs'
runs:
using: composite
steps:
@@ -7,7 +7,7 @@ runs:
shell: bash
run: |
for jvm_pid in $(jps -q -J-XX:+PerfDisableSharedMem); do
jcmd $java_pid Thread.print
jcmd $jvm_pid Thread.print
done
- if: ${{ runner.os == 'Windows' }}
shell: powershell
+20 -14
View File
@@ -1,33 +1,39 @@
name: Send notification
description: Sends a Google Chat message as a notification of the job's outcome
name: Send Notification
description: 'Sends a Google Chat message as a notification of the job''s outcome'
inputs:
webhook-url:
description: 'Google Chat Webhook URL'
required: true
build-scan-url:
description: 'URL of the build scan to include in the notification'
required: false
run-name:
description: 'Name of the run to include in the notification'
required: false
default: ${{ format('{0} {1}', github.ref_name, github.job) }}
status:
description: 'Status of the job'
required: true
build-scan-url:
description: 'URL of the build scan to include in the notification'
run-name:
description: 'Name of the run to include in the notification'
default: ${{ format('{0} {1}', github.ref_name, github.job) }}
webhook-url:
description: 'Google Chat Webhook URL'
required: true
runs:
using: composite
steps:
- shell: bash
- name: Prepare Variables
shell: bash
run: |
echo "BUILD_SCAN=${{ inputs.build-scan-url == '' && ' [build scan unavailable]' || format(' [<{0}|Build Scan>]', inputs.build-scan-url) }}" >> "$GITHUB_ENV"
echo "RUN_URL=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> "$GITHUB_ENV"
- shell: bash
- name: Success Notification
if: ${{ inputs.status == 'success' }}
shell: bash
run: |
curl -X POST '${{ inputs.webhook-url }}' -H 'Content-Type: application/json' -d '{ text: "<${{ env.RUN_URL }}|${{ inputs.run-name }}> was successful ${{ env.BUILD_SCAN }}"}' || true
- shell: bash
- name: Failure Notification
if: ${{ inputs.status == 'failure' }}
shell: bash
run: |
curl -X POST '${{ inputs.webhook-url }}' -H 'Content-Type: application/json' -d '{ text: "<users/all> *<${{ env.RUN_URL }}|${{ inputs.run-name }}> failed* ${{ env.BUILD_SCAN }}"}' || true
- shell: bash
- name: Cancel Notification
if: ${{ inputs.status == 'cancelled' }}
shell: bash
run: |
curl -X POST '${{ inputs.webhook-url }}' -H 'Content-Type: application/json' -d '{ text: "<${{ env.RUN_URL }}|${{ inputs.run-name }}> was cancelled"}' || true
@@ -0,0 +1,43 @@
name: Sync to Maven Central
description: 'Syncs a release to Maven Central and waits for it to be available for use'
inputs:
jfrog-cli-config-token:
description: 'Config token for the JFrog CLI'
required: true
ossrh-s01-staging-profile:
description: 'Staging profile to use when syncing to Central'
required: true
ossrh-s01-token-password:
description: 'Password for authentication with s01.oss.sonatype.org'
required: true
ossrh-s01-token-username:
description: 'Username for authentication with s01.oss.sonatype.org'
required: true
spring-framework-version:
description: 'Version of Spring Framework that is being synced to Central'
required: true
runs:
using: composite
steps:
- name: Set Up JFrog CLI
uses: jfrog/setup-jfrog-cli@9fe0f98bd45b19e6e931d457f4e98f8f84461fb5 # v4.4.1
env:
JF_ENV_SPRING: ${{ inputs.jfrog-cli-config-token }}
- name: Download Release Artifacts
shell: bash
run: jf rt download --spec ${{ format('{0}/artifacts.spec', github.action_path) }} --spec-vars 'buildName=${{ format('spring-framework-{0}', inputs.spring-framework-version) }};buildNumber=${{ github.run_number }}'
- name: Sync
uses: spring-io/nexus-sync-action@42477a2230a2f694f9eaa4643fa9e76b99b7ab84 # v0.0.1
with:
close: true
create: true
generate-checksums: true
password: ${{ inputs.ossrh-s01-token-password }}
release: true
staging-profile-name: ${{ inputs.ossrh-s01-staging-profile }}
upload: true
username: ${{ inputs.ossrh-s01-token-username }}
- name: Await
uses: ./.github/actions/await-http-resource
with:
url: ${{ format('https://repo.maven.apache.org/maven2/org/springframework/spring-context/{0}/spring-context-{0}.jar', inputs.spring-framework-version) }}
@@ -0,0 +1,20 @@
{
"files": [
{
"aql": {
"items.find": {
"$and": [
{
"@build.name": "${buildName}",
"@build.number": "${buildNumber}",
"path": {
"$nmatch": "org/springframework/framework-api/*"
}
}
]
}
},
"target": "nexus/"
}
]
}
+1 -2
View File
@@ -1,5 +1,4 @@
name: Backport Bot
on:
issues:
types: [labeled]
@@ -29,6 +28,6 @@ jobs:
run: wget https://github.com/spring-io/backport-bot/releases/download/latest/backport-bot-0.0.1-SNAPSHOT.jar
- name: Backport
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_EVENT: ${{ toJSON(github.event) }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: java -jar backport-bot-0.0.1-SNAPSHOT.jar --github.accessToken="$GITHUB_TOKEN" --github.event_name "$GITHUB_EVENT_NAME" --github.event "$GITHUB_EVENT"
+36 -40
View File
@@ -1,4 +1,4 @@
name: Build and deploy snapshot
name: Build and Deploy Snapshot
on:
push:
branches:
@@ -7,56 +7,52 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
build-and-deploy-snapshot:
name: Build and Deploy Snapshot
if: ${{ github.repository == 'spring-projects/spring-framework' }}
name: Build and deploy snapshot
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: 'liberica'
java-version: 17
- name: Check out code
- name: Check Out Code
uses: actions/checkout@v4
- name: Set up Gradle
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5
- name: Build and Publish
id: build-and-publish
uses: ./.github/actions/build
with:
cache-read-only: false
- name: Configure Gradle properties
shell: bash
run: |
mkdir -p $HOME/.gradle
echo 'systemProp.user.name=spring-builds+github' >> $HOME/.gradle/gradle.properties
echo 'systemProp.org.gradle.internal.launcher.welcomeMessageEnabled=false' >> $HOME/.gradle/gradle.properties
echo 'org.gradle.daemon=false' >> $HOME/.gradle/gradle.properties
echo 'org.gradle.daemon=4' >> $HOME/.gradle/gradle.properties
- name: Build and publish
id: build
env:
CI: 'true'
GRADLE_ENTERPRISE_URL: 'https://ge.spring.io'
DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_SECRET_ACCESS_KEY }}
run: ./gradlew -PdeploymentRepository=$(pwd)/deployment-repository build publishAllPublicationsToDeploymentRepository
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
publish: true
- name: Deploy
uses: spring-io/artifactory-deploy-action@v0.0.1
uses: spring-io/artifactory-deploy-action@26bbe925a75f4f863e1e529e85be2d0093cac116 # v0.0.1
with:
uri: 'https://repo.spring.io'
username: ${{ secrets.ARTIFACTORY_USERNAME }}
password: ${{ secrets.ARTIFACTORY_PASSWORD }}
build-name: ${{ format('spring-framework-{0}', github.ref_name)}}
repository: 'libs-snapshot-local'
folder: 'deployment-repository'
signing-key: ${{ secrets.GPG_PRIVATE_KEY }}
signing-passphrase: ${{ secrets.GPG_PASSPHRASE }}
artifact-properties: |
/**/framework-api-*.zip::zip.name=spring-framework,zip.deployed=false
/**/framework-api-*-docs.zip::zip.type=docs
/**/framework-api-*-schema.zip::zip.type=schema
- name: Send notification
uses: ./.github/actions/send-notification
build-name: 'spring-framework-6.2.x'
folder: 'deployment-repository'
password: ${{ secrets.ARTIFACTORY_PASSWORD }}
repository: 'libs-snapshot-local'
signing-key: ${{ secrets.GPG_PRIVATE_KEY }}
signing-passphrase: ${{ secrets.GPG_PASSPHRASE }}
uri: 'https://repo.spring.io'
username: ${{ secrets.ARTIFACTORY_USERNAME }}
- name: Send Notification
if: always()
uses: ./.github/actions/send-notification
with:
webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }}
build-scan-url: ${{ steps.build-and-publish.outputs.build-scan-url }}
run-name: ${{ format('{0} | Linux | Java 17', github.ref_name) }}
status: ${{ job.status }}
build-scan-url: ${{ steps.build.outputs.build-scan-url }}
run-name: ${{ format('{0} | Linux | Java 17', github.ref_name) }}
webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }}
outputs:
version: ${{ steps.build-and-publish.outputs.version }}
verify:
name: Verify
needs: build-and-deploy-snapshot
uses: ./.github/workflows/verify.yml
secrets:
google-chat-webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }}
repository-password: ${{ secrets.ARTIFACTORY_PASSWORD }}
repository-username: ${{ secrets.ARTIFACTORY_USERNAME }}
token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
with:
version: ${{ needs.build-and-deploy-snapshot.outputs.version }}
+14 -21
View File
@@ -1,43 +1,36 @@
name: Build Pull Request
on: pull_request
permissions:
contents: read
jobs:
build:
name: Build pull request
runs-on: ubuntu-latest
name: Build Pull Request
if: ${{ github.repository == 'spring-projects/spring-framework' }}
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Set up JDK 17
- name: Set Up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'liberica'
- name: Check out code
java-version: '17'
- name: Check Out
uses: actions/checkout@v4
- name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2
- name: Set up Gradle
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
- name: Set Up Gradle
uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
- name: Build
env:
CI: 'true'
GRADLE_ENTERPRISE_URL: 'https://ge.spring.io'
run: ./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false --no-daemon --no-parallel --continue build
- name: Print JVM thread dumps when cancelled
uses: ./.github/actions/print-jvm-thread-dumps
- name: Print JVM Thread Dumps When Cancelled
if: cancelled()
- name: Upload build reports
uses: actions/upload-artifact@v4
uses: ./.github/actions/print-jvm-thread-dumps
- name: Upload Build Reports
if: failure()
uses: actions/upload-artifact@v4
with:
name: build-reports
path: '**/build/reports/'
+21 -41
View File
@@ -6,7 +6,10 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
ci:
name: '${{ matrix.os.name}} | Java ${{ matrix.java.version}}'
if: ${{ github.repository == 'spring-projects/spring-framework' }}
runs-on: ${{ matrix.os.id }}
timeout-minutes: 60
strategy:
matrix:
os:
@@ -17,61 +20,38 @@ jobs:
toolchain: false
- version: 21
toolchain: true
- version: 22
toolchain: true
- version: 23
toolchain: true
exclude:
- os:
name: Linux
java:
version: 17
name: '${{ matrix.os.name}} | Java ${{ matrix.java.version}}'
runs-on: ${{ matrix.os.id }}
steps:
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: 'liberica'
java-version: |
${{ matrix.java.version }}
${{ matrix.java.toolchain && '17' || '' }}
- name: Prepare Windows runner
if: ${{ runner.os == 'Windows' }}
run: |
git config --global core.autocrlf true
git config --global core.longPaths true
Stop-Service -name Docker
- name: Check out code
- name: Check Out Code
uses: actions/checkout@v4
- name: Set up Gradle
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5
with:
cache-read-only: false
- name: Configure Gradle properties
shell: bash
run: |
mkdir -p $HOME/.gradle
echo 'systemProp.user.name=spring-builds+github' >> $HOME/.gradle/gradle.properties
echo 'systemProp.org.gradle.internal.launcher.welcomeMessageEnabled=false' >> $HOME/.gradle/gradle.properties
echo 'org.gradle.daemon=false' >> $HOME/.gradle/gradle.properties
echo 'org.gradle.daemon=4' >> $HOME/.gradle/gradle.properties
- name: Configure toolchain properties
if: ${{ matrix.java.toolchain }}
shell: bash
run: |
echo toolchainVersion=${{ matrix.java.version }} >> $HOME/.gradle/gradle.properties
echo systemProp.org.gradle.java.installations.auto-detect=false >> $HOME/.gradle/gradle.properties
echo systemProp.org.gradle.java.installations.auto-download=false >> $HOME/.gradle/gradle.properties
echo systemProp.org.gradle.java.installations.paths=${{ format('$JAVA_HOME_{0}_X64', matrix.java.version) }} >> $HOME/.gradle/gradle.properties
- name: Build
id: build
env:
CI: 'true'
GRADLE_ENTERPRISE_URL: 'https://ge.spring.io'
DEVELOCITY_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_SECRET_ACCESS_KEY }}
run: ./gradlew check antora
- name: Send notification
uses: ./.github/actions/send-notification
if: always()
uses: ./.github/actions/build
with:
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
java-early-access: ${{ matrix.java.early-access || 'false' }}
java-distribution: ${{ matrix.java.distribution }}
java-toolchain: ${{ matrix.java.toolchain }}
java-version: ${{ matrix.java.version }}
- name: Send Notification
if: always()
uses: ./.github/actions/send-notification
with:
webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }}
status: ${{ job.status }}
build-scan-url: ${{ steps.build.outputs.build-scan-url }}
run-name: ${{ format('{0} | {1} | Java {2}', github.ref_name, matrix.os.name, matrix.java.version) }}
run-name: ${{ format('{0} | {1} | Java {2}', github.ref_name, matrix.os.name, matrix.java.version) }}
status: ${{ job.status }}
webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }}
+3 -2
View File
@@ -14,14 +14,15 @@ permissions:
actions: write
jobs:
build:
runs-on: ubuntu-latest
name: Dispatch docs deployment
if: github.repository_owner == 'spring-projects'
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
ref: docs-build
fetch-depth: 1
ref: docs-build
- name: Dispatch (partial build)
if: github.ref_type == 'branch'
env:
@@ -1,13 +0,0 @@
name: "Validate Gradle Wrapper"
on: [push, pull_request]
permissions:
contents: read
jobs:
validation:
name: "Validation"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: gradle/wrapper-validation-action@v2
+79
View File
@@ -0,0 +1,79 @@
name: Release Milestone
on:
push:
tags:
- v6.2.0-M[1-9]
- v6.2.0-RC[1-9]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
build-and-stage-release:
if: ${{ github.repository == 'spring-projects/spring-framework' }}
name: Build and Stage Release
runs-on: ubuntu-latest
steps:
- name: Check Out Code
uses: actions/checkout@v4
- name: Build and Publish
id: build-and-publish
uses: ./.github/actions/build
with:
develocity-access-key: ${{ secrets.GRADLE_ENTERPRISE_SECRET_ACCESS_KEY }}
publish: true
- name: Stage Release
uses: spring-io/artifactory-deploy-action@26bbe925a75f4f863e1e529e85be2d0093cac116 # v0.0.1
with:
artifact-properties: |
/**/framework-api-*.zip::zip.name=spring-framework,zip.deployed=false
/**/framework-api-*-docs.zip::zip.type=docs
/**/framework-api-*-schema.zip::zip.type=schema
build-name: ${{ format('spring-framework-{0}', steps.build-and-publish.outputs.version)}}
folder: 'deployment-repository'
password: ${{ secrets.ARTIFACTORY_PASSWORD }}
repository: 'libs-staging-local'
signing-key: ${{ secrets.GPG_PRIVATE_KEY }}
signing-passphrase: ${{ secrets.GPG_PASSPHRASE }}
uri: 'https://repo.spring.io'
username: ${{ secrets.ARTIFACTORY_USERNAME }}
outputs:
version: ${{ steps.build-and-publish.outputs.version }}
verify:
name: Verify
needs: build-and-stage-release
uses: ./.github/workflows/verify.yml
with:
staging: true
version: ${{ needs.build-and-stage-release.outputs.version }}
secrets:
google-chat-webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }}
repository-password: ${{ secrets.ARTIFACTORY_PASSWORD }}
repository-username: ${{ secrets.ARTIFACTORY_USERNAME }}
token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
promote-release:
name: Promote Release
needs:
- build-and-stage-release
- verify
runs-on: ubuntu-latest
steps:
- name: Set up JFrog CLI
uses: jfrog/setup-jfrog-cli@9fe0f98bd45b19e6e931d457f4e98f8f84461fb5 # v4.4.1
env:
JF_ENV_SPRING: ${{ secrets.JF_ARTIFACTORY_SPRING }}
- name: Promote build
run: jfrog rt build-promote ${{ format('spring-framework-{0}', needs.build-and-stage-release.outputs.version)}} ${{ github.run_number }} libs-milestone-local
create-github-release:
name: Create GitHub Release
needs:
- build-and-stage-release
- promote-release
runs-on: ubuntu-latest
steps:
- name: Check Out Code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Create GitHub Release
uses: ./.github/actions/create-github-release
with:
milestone: ${{ needs.build-and-stage-release.outputs.version }}
pre-release: true
token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
+94
View File
@@ -0,0 +1,94 @@
name: Release
on:
push:
tags:
- v6.2.[0-9]+
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
build-and-stage-release:
name: Build and Stage Release
if: ${{ github.repository == 'spring-projects/spring-framework' }}
runs-on: ubuntu-latest
steps:
- name: Check Out Code
uses: actions/checkout@v4
- name: Build and Publish
id: build-and-publish
uses: ./.github/actions/build
with:
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
publish: true
- name: Stage Release
uses: spring-io/artifactory-deploy-action@26bbe925a75f4f863e1e529e85be2d0093cac116 # v0.0.1
with:
artifact-properties: |
/**/framework-api-*.zip::zip.name=spring-framework,zip.deployed=false
/**/framework-api-*-docs.zip::zip.type=docs
/**/framework-api-*-schema.zip::zip.type=schema
build-name: ${{ format('spring-framework-{0}', steps.build-and-publish.outputs.version)}}
folder: 'deployment-repository'
password: ${{ secrets.ARTIFACTORY_PASSWORD }}
repository: 'libs-staging-local'
signing-key: ${{ secrets.GPG_PRIVATE_KEY }}
signing-passphrase: ${{ secrets.GPG_PASSPHRASE }}
uri: 'https://repo.spring.io'
username: ${{ secrets.ARTIFACTORY_USERNAME }}
outputs:
version: ${{ steps.build-and-publish.outputs.version }}
verify:
name: Verify
needs: build-and-stage-release
uses: ./.github/workflows/verify.yml
secrets:
google-chat-webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }}
repository-password: ${{ secrets.ARTIFACTORY_PASSWORD }}
repository-username: ${{ secrets.ARTIFACTORY_USERNAME }}
token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
with:
staging: true
version: ${{ needs.build-and-stage-release.outputs.version }}
sync-to-maven-central:
name: Sync to Maven Central
needs:
- build-and-stage-release
- verify
runs-on: ubuntu-latest
steps:
- name: Check Out Code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Sync to Maven Central
uses: ./.github/actions/sync-to-maven-central
with:
jfrog-cli-config-token: ${{ secrets.JF_ARTIFACTORY_SPRING }}
ossrh-s01-staging-profile: ${{ secrets.OSSRH_S01_STAGING_PROFILE }}
ossrh-s01-token-password: ${{ secrets.OSSRH_S01_TOKEN_PASSWORD }}
ossrh-s01-token-username: ${{ secrets.OSSRH_S01_TOKEN_USERNAME }}
spring-framework-version: ${{ needs.build-and-stage-release.outputs.version }}
promote-release:
name: Promote Release
needs:
- build-and-stage-release
- sync-to-maven-central
runs-on: ubuntu-latest
steps:
- name: Set up JFrog CLI
uses: jfrog/setup-jfrog-cli@9fe0f98bd45b19e6e931d457f4e98f8f84461fb5 # v4.4.1
env:
JF_ENV_SPRING: ${{ secrets.JF_ARTIFACTORY_SPRING }}
- name: Promote build
run: jfrog rt build-promote ${{ format('spring-framework-{0}', needs.build-and-stage-release.outputs.version)}} ${{ github.run_number }} libs-release-local
create-github-release:
name: Create GitHub Release
needs:
- build-and-stage-release
- promote-release
runs-on: ubuntu-latest
steps:
- name: Check Out Code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Create GitHub Release
uses: ./.github/actions/create-github-release
with:
milestone: ${{ needs.build-and-stage-release.outputs.version }}
token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
@@ -0,0 +1,35 @@
name: Update Antora UI Spring
on:
schedule:
- cron: '0 10 * * *' # Once per day at 10am UTC
workflow_dispatch:
permissions:
pull-requests: write
issues: write
contents: write
jobs:
update-antora-ui-spring:
runs-on: ubuntu-latest
name: Update on Supported Branches
strategy:
matrix:
branch: [ '6.1.x' ]
steps:
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@5a57bcc6a0da2a1474136cf29571b277850432bc
name: Update
with:
docs-branch: ${{ matrix.branch }}
token: ${{ secrets.GITHUB_TOKEN }}
antora-file-path: 'framework-docs/antora-playbook.yml'
update-antora-ui-spring-docs-build:
runs-on: ubuntu-latest
name: Update on docs-build
steps:
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@5a57bcc6a0da2a1474136cf29571b277850432bc
name: Update
with:
docs-branch: 'docs-build'
token: ${{ secrets.GITHUB_TOKEN }}
+77
View File
@@ -0,0 +1,77 @@
name: Verify
on:
workflow_call:
inputs:
staging:
description: 'Whether the release to verify is in the staging repository'
required: false
default: false
type: boolean
version:
description: 'Version to verify'
required: true
type: string
secrets:
google-chat-webhook-url:
description: 'Google Chat Webhook URL'
required: true
repository-password:
description: 'Password for authentication with the repository'
required: false
repository-username:
description: 'Username for authentication with the repository'
required: false
token:
description: 'Token to use for authentication with GitHub'
required: true
jobs:
verify:
name: Verify
runs-on: ubuntu-latest
steps:
- name: Check Out Release Verification Tests
uses: actions/checkout@v4
with:
ref: 'v0.0.2'
repository: spring-projects/spring-framework-release-verification
token: ${{ secrets.token }}
- name: Check Out Send Notification Action
uses: actions/checkout@v4
with:
path: send-notification
sparse-checkout: .github/actions/send-notification
- name: Set Up Java
uses: actions/setup-java@v4
with:
distribution: 'liberica'
java-version: 17
- name: Set Up Gradle
uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
with:
cache-read-only: false
- name: Configure Gradle Properties
shell: bash
run: |
mkdir -p $HOME/.gradle
echo 'org.gradle.daemon=false' >> $HOME/.gradle/gradle.properties
- name: Run Release Verification Tests
env:
RVT_OSS_REPOSITORY_PASSWORD: ${{ secrets.repository-password }}
RVT_OSS_REPOSITORY_USERNAME: ${{ secrets.repository-username }}
RVT_RELEASE_TYPE: oss
RVT_STAGING: ${{ inputs.staging }}
RVT_VERSION: ${{ inputs.version }}
run: ./gradlew spring-framework-release-verification-tests:test
- name: Upload Build Reports on Failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: build-reports
path: '**/build/reports/'
- name: Send Notification
if: failure()
uses: ./send-notification/.github/actions/send-notification
with:
run-name: ${{ format('{0} | Verification | {1}', github.ref_name, inputs.version) }}
status: ${{ job.status }}
webhook-url: ${{ secrets.google-chat-webhook-url }}
+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.11-librca
java=17.0.12-librca
-44
View File
@@ -1,44 +0,0 @@
= Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of fostering an open
and welcoming community, we pledge to respect all people who contribute through reporting
issues, posting feature requests, updating documentation, submitting pull requests or
patches, and other activities.
We are committed to making participation in this project a harassment-free experience for
everyone, regardless of level of experience, gender, gender identity and expression,
sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic addresses,
without explicit permission
* Other unethical or unprofessional conduct
Project maintainers have the right and responsibility to remove, edit, or reject comments,
commits, code, wiki edits, issues, and other contributions that are not aligned to this
Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors
that they deem inappropriate, threatening, offensive, or harmful.
By adopting this Code of Conduct, project maintainers commit themselves to fairly and
consistently applying these principles to every aspect of managing this project. Project
maintainers who do not follow or enforce the Code of Conduct may be permanently removed
from the project team.
This Code of Conduct applies both within project spaces and in public spaces when an
individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
contacting a project maintainer at spring-code-of-conduct@pivotal.io . All complaints will
be reviewed and investigated and will result in a response that is deemed necessary and
appropriate to the circumstances. Maintainers are obligated to maintain confidentiality
with regard to the reporter of an incident.
This Code of Conduct is adapted from the
https://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
https://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]
+2 -2
View File
@@ -18,7 +18,7 @@ First off, thank you for taking the time to contribute! :+1: :tada:
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc).
By participating you are expected to uphold this code.
Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
Please report unacceptable behavior to spring-code-of-conduct@spring.io.
### How to Contribute
@@ -86,7 +86,7 @@ multiple edits or corrections of the same logical change. See
for an overview of streamlining the commit history.
1. Format commit messages using 55 characters for the subject line, 72 characters per line
for the description, followed by the issue fixed, e.g. `Closes gh-22276`. See the
for the description, followed by the issue fixed, for example, `Closes gh-22276`. See the
[Commit Guidelines section of Pro Git](https://git-scm.com/book/en/Distributed-Git-Contributing-to-a-Project#Commit-Guidelines)
for best practices around commit messages, and use `git log` to see some examples.
+1 -1
View File
@@ -6,7 +6,7 @@ Spring provides everything required beyond the Java programming language for cre
## Code of Conduct
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc). By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
This project is governed by the [Spring Code of Conduct](https://github.com/spring-projects/spring-framework/?tab=coc-ov-file#contributor-code-of-conduct). By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to spring-code-of-conduct@spring.io.
## Access to Binaries
+5 -11
View File
@@ -1,16 +1,10 @@
# Security Policy
# Reporting a Vulnerability
Please, [open a draft security advisory](https://github.com/spring-projects/security-advisories/security/advisories/new) if you need to disclose and discuss a security issue in private with the Spring Framework team. Note that we only accept reports against [supported versions](https://spring.io/projects/spring-framework#support).
For more details, check out our [security policy](https://spring.io/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
[Spring Framework Versions](https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Versions)
wiki page.
## Reporting a Vulnerability
Please see https://spring.io/security-policy.
+4 -4
View File
@@ -3,10 +3,10 @@ plugins {
// kotlinVersion is managed in gradle.properties
id 'org.jetbrains.kotlin.plugin.serialization' version "${kotlinVersion}" apply false
id 'org.jetbrains.dokka' version '1.9.20'
id 'org.unbroken-dome.xjc' version '2.0.0' apply false
id 'com.github.ben-manes.versions' version '0.51.0'
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
id 'com.github.bjornvester.xjc' version '1.8.2' apply false
id 'de.undercouch.download' version '5.4.0'
id 'io.github.goooler.shadow' version '8.1.8' apply false
id 'me.champeau.jmh' version '0.7.2' apply false
id 'me.champeau.mrjar' version '0.1.1'
id "net.ltgt.errorprone" version "3.1.0" apply false
@@ -96,13 +96,13 @@ configure([rootProject] + javaProjects) { project ->
"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://hc.apache.org/httpcomponents-client-5.4.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 execute Gradle with Java 18+.
// See https://github.com/spring-projects/spring-framework/issues/27497
//
// "https://junit.org/junit5/docs/5.10.2/api/",
// "https://junit.org/junit5/docs/5.11.3/api/",
"https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/",
//"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/",
"https://r2dbc.io/spec/1.0.0.RELEASE/api/",
+1 -1
View File
@@ -1,2 +1,2 @@
org.gradle.caching=true
javaFormatVersion=0.0.41
javaFormatVersion=0.0.42
@@ -50,7 +50,7 @@ public class CheckstyleConventions {
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.16.0");
checkstyle.setToolVersion("10.18.1");
checkstyle.getConfigDirectory().set(project.getRootProject().file("src/checkstyle"));
String version = SpringJavaFormatPlugin.class.getPackage().getImplementationVersion();
DependencySet checkstyleDependencies = project.getConfigurations().getByName("checkstyle").getDependencies();
@@ -64,7 +64,7 @@ public class CheckstyleConventions {
NoHttpExtension noHttp = project.getExtensions().getByType(NoHttpExtension.class);
noHttp.setAllowlistFile(project.file("src/nohttp/allowlist.lines"));
noHttp.getSource().exclude("**/test-output/**", "**/.settings/**",
"**/.classpath", "**/.project", "**/.gradle/**");
"**/.classpath", "**/.project", "**/.gradle/**", "**/node_modules/**");
List<String> buildFolders = List.of("bin", "build", "out");
project.allprojects(subproject -> {
Path rootPath = project.getRootDir().toPath();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 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.
@@ -62,9 +62,11 @@ class TestConventions {
if (project.hasProperty("testGroups")) {
test.systemProperty("testGroups", project.getProperties().get("testGroups"));
}
test.jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED",
test.jvmArgs(
"--add-opens=java.base/java.lang=ALL-UNNAMED",
"--add-opens=java.base/java.util=ALL-UNNAMED",
"-Djava.locale.providers=COMPAT");
"-Xshare:off"
);
}
private void configureTestRetryPlugin(Project project, Test test) {
@@ -26,7 +26,9 @@ 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.plugins.jvm.JvmTestSuite;
import org.gradle.api.tasks.testing.Test;
import org.gradle.testing.base.TestingExtension;
import java.util.Collections;
@@ -47,6 +49,8 @@ public class RuntimeHintsAgentPlugin implements Plugin<Project> {
public void apply(Project project) {
project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
TestingExtension testing = project.getExtensions().getByType(TestingExtension.class);
JvmTestSuite jvmTestSuite = (JvmTestSuite) testing.getSuites().getByName("test");
RuntimeHintsAgentExtension agentExtension = createRuntimeHintsAgentExtension(project);
Test agentTest = project.getTasks().create(RUNTIMEHINTS_TEST_TASK, Test.class, test -> {
test.useJUnitPlatform(options -> {
@@ -55,6 +59,8 @@ public class RuntimeHintsAgentPlugin implements Plugin<Project> {
test.include("**/*Tests.class", "**/*Test.class");
test.systemProperty("java.awt.headless", "true");
test.systemProperty("org.graalvm.nativeimage.imagecode", "runtime");
test.setTestClassesDirs(jvmTestSuite.getSources().getOutput().getClassesDirs());
test.setClasspath(jvmTestSuite.getSources().getRuntimeClasspath());
test.getJvmArgumentProviders().add(createRuntimeHintsAgentArgumentProvider(project, agentExtension));
});
project.getTasks().getByName("check", task -> task.dependsOn(agentTest));
-59
View File
@@ -1,59 +0,0 @@
== Spring Framework Concourse pipeline
NOTE: CI is being migrated to GitHub Actions.
The Spring Framework uses https://concourse-ci.org/[Concourse] for its CI build and other automated tasks.
The Spring team has a dedicated Concourse instance available at https://ci.spring.io with a build pipeline
for https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-6.2.x[Spring Framework 6.2.x].
=== Setting up your development environment
If you're part of the Spring Framework project on GitHub, you can get access to CI management features.
First, you need to go to https://ci.spring.io and install the client CLI for your platform (see bottom right of the screen).
You can then login with the instance using:
[source]
----
$ fly -t spring login -n spring-framework -c https://ci.spring.io
----
Once logged in, you should get something like:
[source]
----
$ fly ts
name url team expiry
spring https://ci.spring.io spring-framework Wed, 25 Mar 2020 17:45:26 UTC
----
=== Pipeline configuration and structure
The build pipelines are described in `pipeline.yml` file.
This file is listing Concourse resources, i.e. build inputs and outputs such as container images, artifact repositories, source repositories, notification services, etc.
It also describes jobs (a job is a sequence of inputs, tasks and outputs); jobs are organized by groups.
The `pipeline.yml` definition contains `((parameters))` which are loaded from the `parameters.yml` file or from our https://docs.cloudfoundry.org/credhub/[credhub instance].
You'll find in this folder the following resources:
* `pipeline.yml` the build pipeline
* `parameters.yml` the build parameters used for the pipeline
* `images/` holds the container images definitions used in this pipeline
* `scripts/` holds the build scripts that ship within the CI container images
* `tasks` contains the task definitions used in the main `pipeline.yml`
=== Updating the build pipeline
Updating files on the repository is not enough to update the build pipeline, as changes need to be applied.
The pipeline can be deployed using the following command:
[source]
----
$ fly -t spring set-pipeline -p spring-framework-6.2.x -c ci/pipeline.yml -l ci/parameters.yml
----
NOTE: This assumes that you have credhub integration configured with the appropriate secrets.
-10
View File
@@ -1,10 +0,0 @@
logging:
level:
io.spring.concourse: DEBUG
spring:
main:
banner-mode: off
sonatype:
exclude:
- 'build-info\.json'
- '.*\.zip'
-21
View File
@@ -1,21 +0,0 @@
== CI Images
These images are used by CI to run the actual builds.
To build the image locally run the following from this directory:
----
$ docker build --no-cache -f <image-folder>/Dockerfile .
----
For example
----
$ docker build --no-cache -f spring-framework-ci-image/Dockerfile .
----
To test run:
----
$ docker run -it --entrypoint /bin/bash <SHA>
----
-12
View File
@@ -1,12 +0,0 @@
FROM ubuntu:jammy-20240125
ADD setup.sh /setup.sh
ADD get-jdk-url.sh /get-jdk-url.sh
RUN ./setup.sh
ENV JAVA_HOME /opt/openjdk/java17
ENV JDK17 /opt/openjdk/java17
ENV JDK21 /opt/openjdk/java21
ENV JDK23 /opt/openjdk/java23
ENV PATH $JAVA_HOME/bin:$PATH
-17
View File
@@ -1,17 +0,0 @@
#!/bin/bash
set -e
case "$1" in
java17)
echo "https://github.com/bell-sw/Liberica/releases/download/17.0.10%2B13/bellsoft-jdk17.0.10+13-linux-amd64.tar.gz"
;;
java21)
echo "https://github.com/bell-sw/Liberica/releases/download/21.0.2%2B14/bellsoft-jdk21.0.2+14-linux-amd64.tar.gz"
;;
java23)
echo "https://download.java.net/java/early_access/jdk23/17/GPL/openjdk-23-ea+17_linux-x64_bin.tar.gz"
;;
*)
echo $"Unknown java version"
exit 1
esac
-40
View File
@@ -1,40 +0,0 @@
#!/bin/bash
set -ex
###########################################################
# UTILS
###########################################################
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install --no-install-recommends -y tzdata ca-certificates net-tools libxml2-utils git curl libudev1 libxml2-utils iptables iproute2 jq fontconfig
ln -fs /usr/share/zoneinfo/UTC /etc/localtime
dpkg-reconfigure --frontend noninteractive tzdata
rm -rf /var/lib/apt/lists/*
curl https://raw.githubusercontent.com/spring-io/concourse-java-scripts/v0.0.4/concourse-java.sh > /opt/concourse-java.sh
###########################################################
# JAVA
###########################################################
mkdir -p /opt/openjdk
pushd /opt/openjdk > /dev/null
for jdk in java17 java21 java23
do
JDK_URL=$( /get-jdk-url.sh $jdk )
mkdir $jdk
pushd $jdk > /dev/null
curl -L ${JDK_URL} | tar zx --strip-components=1
test -f bin/java
test -f bin/javac
popd > /dev/null
done
popd
###########################################################
# GRADLE ENTERPRISE
###########################################################
cd /
mkdir ~/.gradle
echo 'systemProp.user.name=concourse' > ~/.gradle/gradle.properties
-10
View File
@@ -1,10 +0,0 @@
github-repo: "https://github.com/spring-projects/spring-framework.git"
github-repo-name: "spring-projects/spring-framework"
sonatype-staging-profile: "org.springframework"
docker-hub-organization: "springci"
artifactory-server: "https://repo.spring.io"
branch: "main"
milestone: "6.2.x"
build-name: "spring-framework"
pipeline-name: "spring-framework"
concourse-url: "https://ci.spring.io"
-293
View File
@@ -1,293 +0,0 @@
anchors:
git-repo-resource-source: &git-repo-resource-source
uri: ((github-repo))
username: ((github-username))
password: ((github-ci-release-token))
branch: ((branch))
gradle-enterprise-task-params: &gradle-enterprise-task-params
DEVELOCITY_ACCESS_KEY: ((gradle_enterprise_secret_access_key))
sonatype-task-params: &sonatype-task-params
SONATYPE_USERNAME: ((sonatype-username))
SONATYPE_PASSWORD: ((sonatype-password))
SONATYPE_URL: ((sonatype-url))
SONATYPE_STAGING_PROFILE: ((sonatype-staging-profile))
artifactory-task-params: &artifactory-task-params
ARTIFACTORY_SERVER: ((artifactory-server))
ARTIFACTORY_USERNAME: ((artifactory-username))
ARTIFACTORY_PASSWORD: ((artifactory-password))
build-project-task-params: &build-project-task-params
BRANCH: ((branch))
<<: *gradle-enterprise-task-params
docker-resource-source: &docker-resource-source
username: ((docker-hub-username))
password: ((docker-hub-password))
changelog-task-params: &changelog-task-params
name: generated-changelog/tag
tag: generated-changelog/tag
body: generated-changelog/changelog.md
github-task-params: &github-task-params
GITHUB_USERNAME: ((github-username))
GITHUB_TOKEN: ((github-ci-release-token))
resource_types:
- name: registry-image
type: registry-image
source:
<<: *docker-resource-source
repository: concourse/registry-image-resource
tag: 1.8.0
- name: artifactory-resource
type: registry-image
source:
<<: *docker-resource-source
repository: springio/artifactory-resource
tag: 0.0.18
- name: github-release
type: registry-image
source:
<<: *docker-resource-source
repository: concourse/github-release-resource
tag: 1.8.0
- name: github-status-resource
type: registry-image
source:
<<: *docker-resource-source
repository: dpb587/github-status-resource
tag: master
resources:
- name: git-repo
type: git
icon: github
source:
<<: *git-repo-resource-source
- name: ci-images-git-repo
type: git
icon: github
source:
uri: ((github-repo))
branch: ((branch))
paths: ["ci/images/*"]
- name: ci-image
type: registry-image
icon: docker
source:
<<: *docker-resource-source
repository: ((docker-hub-organization))/spring-framework-ci
tag: ((milestone))
- name: artifactory-repo
type: artifactory-resource
icon: package-variant
source:
uri: ((artifactory-server))
username: ((artifactory-username))
password: ((artifactory-password))
build_name: ((build-name))
- name: github-pre-release
type: github-release
icon: briefcase-download-outline
source:
owner: spring-projects
repository: spring-framework
access_token: ((github-ci-release-token))
pre_release: true
release: false
- name: github-release
type: github-release
icon: briefcase-download
source:
owner: spring-projects
repository: spring-framework
access_token: ((github-ci-release-token))
pre_release: false
jobs:
- name: build-ci-images
plan:
- get: git-repo
- get: ci-images-git-repo
trigger: true
- task: build-ci-image
privileged: true
file: git-repo/ci/tasks/build-ci-image.yml
output_mapping:
image: ci-image
vars:
ci-image-name: ci-image
<<: *docker-resource-source
- put: ci-image
params:
image: ci-image/image.tar
- name: stage-milestone
serial: true
plan:
- get: ci-image
- get: git-repo
trigger: false
- task: stage
image: ci-image
file: git-repo/ci/tasks/stage-version.yml
params:
RELEASE_TYPE: M
<<: *gradle-enterprise-task-params
- put: artifactory-repo
params: &artifactory-params
signing_key: ((signing-key))
signing_passphrase: ((signing-passphrase))
repo: libs-staging-local
folder: distribution-repository
build_uri: "https://ci.spring.io/teams/${BUILD_TEAM_NAME}/pipelines/${BUILD_PIPELINE_NAME}/jobs/${BUILD_JOB_NAME}/builds/${BUILD_NAME}"
build_number: "${BUILD_PIPELINE_NAME}-${BUILD_JOB_NAME}-${BUILD_NAME}"
disable_checksum_uploads: true
threads: 8
artifact_set:
- include:
- "/**/framework-api-*.zip"
properties:
"zip.name": "spring-framework"
"zip.displayname": "Spring Framework"
"zip.deployed": "false"
- include:
- "/**/framework-api-*-docs.zip"
properties:
"zip.type": "docs"
- include:
- "/**/framework-api-*-schema.zip"
properties:
"zip.type": "schema"
get_params:
threads: 8
- put: git-repo
params:
repository: stage-git-repo
- name: promote-milestone
serial: true
plan:
- get: ci-image
- get: git-repo
trigger: false
- get: artifactory-repo
trigger: false
passed: [stage-milestone]
params:
download_artifacts: false
save_build_info: true
- task: promote
file: git-repo/ci/tasks/promote-version.yml
params:
RELEASE_TYPE: M
<<: *artifactory-task-params
- task: generate-changelog
file: git-repo/ci/tasks/generate-changelog.yml
params:
RELEASE_TYPE: M
<<: *github-task-params
<<: *docker-resource-source
- put: github-pre-release
params:
<<: *changelog-task-params
- name: stage-rc
serial: true
plan:
- get: ci-image
- get: git-repo
trigger: false
- task: stage
image: ci-image
file: git-repo/ci/tasks/stage-version.yml
params:
RELEASE_TYPE: RC
<<: *gradle-enterprise-task-params
- put: artifactory-repo
params:
<<: *artifactory-params
- put: git-repo
params:
repository: stage-git-repo
- name: promote-rc
serial: true
plan:
- get: ci-image
- get: git-repo
trigger: false
- get: artifactory-repo
trigger: false
passed: [stage-rc]
params:
download_artifacts: false
save_build_info: true
- task: promote
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
params:
RELEASE_TYPE: RC
<<: *github-task-params
- put: github-pre-release
params:
<<: *changelog-task-params
- name: stage-release
serial: true
plan:
- get: ci-image
- get: git-repo
trigger: false
- task: stage
image: ci-image
file: git-repo/ci/tasks/stage-version.yml
params:
RELEASE_TYPE: RELEASE
<<: *gradle-enterprise-task-params
- put: artifactory-repo
params:
<<: *artifactory-params
- put: git-repo
params:
repository: stage-git-repo
- name: promote-release
serial: true
plan:
- get: ci-image
- get: git-repo
trigger: false
- get: artifactory-repo
trigger: false
passed: [stage-release]
params:
download_artifacts: true
save_build_info: true
- task: promote
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
serial: true
plan:
- get: ci-image
- get: git-repo
- get: artifactory-repo
trigger: true
passed: [promote-release]
params:
download_artifacts: false
save_build_info: true
- task: generate-changelog
file: git-repo/ci/tasks/generate-changelog.yml
params:
RELEASE_TYPE: RELEASE
<<: *docker-resource-source
<<: *github-task-params
- put: github-release
params:
<<: *changelog-task-params
groups:
- 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"]
-2
View File
@@ -1,2 +0,0 @@
source /opt/concourse-java.sh
setup_symlinks
-12
View File
@@ -1,12 +0,0 @@
#!/bin/bash
set -e
CONFIG_DIR=git-repo/ci/config
version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
java -jar /github-changelog-generator.jar \
--spring.config.location=${CONFIG_DIR}/changelog-generator.yml \
${version} generated-changelog/changelog.md
echo ${version} > generated-changelog/version
echo v${version} > generated-changelog/tag
-17
View File
@@ -1,17 +0,0 @@
#!/bin/bash
CONFIG_DIR=git-repo/ci/config
version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
export BUILD_INFO_LOCATION=$(pwd)/artifactory-repo/build-info.json
java -jar /concourse-release-scripts.jar \
--spring.config.location=${CONFIG_DIR}/release-scripts.yml \
publishToCentral $RELEASE_TYPE $BUILD_INFO_LOCATION artifactory-repo || { exit 1; }
java -jar /concourse-release-scripts.jar \
--spring.config.location=${CONFIG_DIR}/release-scripts.yml \
promote $RELEASE_TYPE $BUILD_INFO_LOCATION || { exit 1; }
echo "Promotion complete"
echo $version > version/version
-51
View File
@@ -1,51 +0,0 @@
#!/bin/bash
set -e
source $(dirname $0)/common.sh
repository=$(pwd)/distribution-repository
pushd git-repo > /dev/null
git fetch --tags --all > /dev/null
popd > /dev/null
git clone git-repo stage-git-repo > /dev/null
pushd stage-git-repo > /dev/null
snapshotVersion=$( awk -F '=' '$1 == "version" { print $2 }' gradle.properties )
if [[ $RELEASE_TYPE = "M" ]]; then
stageVersion=$( get_next_milestone_release $snapshotVersion)
nextVersion=$snapshotVersion
elif [[ $RELEASE_TYPE = "RC" ]]; then
stageVersion=$( get_next_rc_release $snapshotVersion)
nextVersion=$snapshotVersion
elif [[ $RELEASE_TYPE = "RELEASE" ]]; then
stageVersion=$( get_next_release $snapshotVersion)
nextVersion=$( bump_version_number $snapshotVersion)
else
echo "Unknown release type $RELEASE_TYPE" >&2; exit 1;
fi
echo "Staging $stageVersion (next version will be $nextVersion)"
sed -i "s/version=$snapshotVersion/version=$stageVersion/" gradle.properties
git config user.name "Spring Builds" > /dev/null
git config user.email "spring-builds@users.noreply.github.com" > /dev/null
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} -Porg.gradle.java.installations.fromEnv=JDK17,JDK21 \
build publishAllPublicationsToDeploymentRepository
git reset --hard HEAD^ > /dev/null
if [[ $nextVersion != $snapshotVersion ]]; then
echo "Setting next development version (v$nextVersion)"
sed -i "s/version=$snapshotVersion/version=$nextVersion/" gradle.properties
git add gradle.properties > /dev/null
git commit -m"Next development version (v$nextVersion)" > /dev/null
fi;
echo "Staging Complete"
popd > /dev/null
-30
View File
@@ -1,30 +0,0 @@
---
platform: linux
image_resource:
type: registry-image
source:
repository: concourse/oci-build-task
tag: 0.10.0
username: ((docker-hub-username))
password: ((docker-hub-password))
inputs:
- name: ci-images-git-repo
outputs:
- name: image
caches:
- path: ci-image-cache
params:
CONTEXT: ci-images-git-repo/ci/images
DOCKERFILE: ci-images-git-repo/ci/images/ci-image/Dockerfile
DOCKER_HUB_AUTH: ((docker-hub-auth))
run:
path: /bin/sh
args:
- "-c"
- |
mkdir -p /root/.docker
cat > /root/.docker/config.json <<EOF
{ "auths": { "https://index.docker.io/v1/": { "auth": "$DOCKER_HUB_AUTH" }}}
EOF
build
-22
View File
@@ -1,22 +0,0 @@
---
platform: linux
image_resource:
type: registry-image
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
outputs:
- name: generated-changelog
params:
GITHUB_ORGANIZATION:
GITHUB_REPO:
GITHUB_USERNAME:
GITHUB_TOKEN:
RELEASE_TYPE:
run:
path: git-repo/ci/scripts/generate-changelog.sh
-25
View File
@@ -1,25 +0,0 @@
---
platform: linux
image_resource:
type: registry-image
source:
repository: springio/concourse-release-scripts
tag: '0.4.0'
username: ((docker-hub-username))
password: ((docker-hub-password))
inputs:
- name: git-repo
- name: artifactory-repo
outputs:
- name: version
params:
RELEASE_TYPE:
ARTIFACTORY_SERVER:
ARTIFACTORY_USERNAME:
ARTIFACTORY_PASSWORD:
SONATYPE_USER:
SONATYPE_PASSWORD:
SONATYPE_URL:
SONATYPE_STAGING_PROFILE:
run:
path: git-repo/ci/scripts/promote-version.sh
-17
View File
@@ -1,17 +0,0 @@
---
platform: linux
inputs:
- name: git-repo
outputs:
- name: stage-git-repo
- name: distribution-repository
params:
RELEASE_TYPE:
CI: true
GRADLE_ENTERPRISE_CACHE_USERNAME:
GRADLE_ENTERPRISE_CACHE_PASSWORD:
GRADLE_ENTERPRISE_URL: https://ge.spring.io
caches:
- path: gradle
run:
path: git-repo/ci/scripts/stage-version.sh
+2 -2
View File
@@ -28,7 +28,7 @@ javadoc {
header = rootProject.description
use = true
overview = project.relativePath("$rootProject.rootDir/framework-docs/src/docs/api/overview.html")
destinationDir = file("$project.docsDir/javadoc-api")
destinationDir = project.java.docsDir.dir("javadoc-api").get().asFile
splitIndex = true
links(rootProject.ext.javadocLinks)
addBooleanOption('Xdoclint:syntax,reference', true) // only check syntax and reference with doclint
@@ -52,7 +52,7 @@ rootProject.tasks.dokkaHtmlMultiModule.configure {
tasks.named("javadoc")
}
moduleName.set("spring-framework")
outputDirectory.set(file("$docsDir/kdoc-api"))
outputDirectory.set(project.java.docsDir.dir("kdoc-api").get().asFile)
includes.from("$rootProject.rootDir/framework-docs/src/docs/api/dokka-overview.md")
}
+2 -2
View File
@@ -13,7 +13,7 @@ content:
- url: https://github.com/spring-projects/spring-framework
# Refname matching:
# https://docs.antora.org/antora/latest/playbook/content-refname-matching/
branches: ['main', '{6..9}.+({0..9}).x']
branches: ['main', '{6..9}.+({1..9}).x']
tags: ['v{6..9}.+({0..9}).+({0..9})?(-{RC,M}*)', '!(v6.0.{0..8})', '!(v6.0.0-{RC,M}{0..9})']
start_path: framework-docs
asciidoc:
@@ -36,4 +36,4 @@ runtime:
failure_level: warn
ui:
bundle:
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.15/ui-bundle.zip
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.17/ui-bundle.zip
+7 -2
View File
@@ -42,7 +42,8 @@ asciidoc:
spring-framework-reference: '{spring-framework-docs-root}/{spring-version}/reference'
#
# Other Spring portfolio projects
spring-boot-docs: '{docs-site}/spring-boot/docs/current/reference/html'
spring-boot-docs: '{docs-site}/spring-boot'
spring-boot-docs-ref: '{spring-boot-docs}/reference'
spring-boot-issues: '{spring-github-org}/spring-boot/issues'
# TODO add more projects / links or just build up on {docs-site}?
# TODO rename the below using new conventions
@@ -72,6 +73,9 @@ asciidoc:
kotlin-coroutines-api: '{kotlin-site}/api/kotlinx.coroutines'
kotlin-github-org: 'https://github.com/Kotlin'
kotlin-issues: 'https://youtrack.jetbrains.com/issue'
micrometer-docs: 'https://docs.micrometer.io/micrometer/reference'
micrometer-context-propagation-docs: 'https://docs.micrometer.io/context-propagation/reference'
petclinic-github-org: 'https://github.com/spring-petclinic'
reactive-streams-site: 'https://www.reactive-streams.org'
reactive-streams-spec: 'https://github.com/reactive-streams/reactive-streams-jvm/blob/master/README.md#specification'
reactor-github-org: 'https://github.com/reactor'
@@ -89,4 +93,5 @@ asciidoc:
stackoverflow-questions: '{stackoverflow-site}/questions'
stackoverflow-spring-tag: "{stackoverflow-questions}/tagged/spring"
stackoverflow-spring-kotlin-tags: "{stackoverflow-spring-tag}+kotlin"
testcontainers-site: 'https://www.testcontainers.org'
testcontainers-site: 'https://www.testcontainers.org'
vavr-docs: 'https://vavr-io.github.io/vavr-docs'
+14 -11
View File
@@ -42,29 +42,32 @@ repositories {
}
dependencies {
api(project(":spring-aspects"))
api(project(":spring-context"))
api(project(":spring-context-support"))
api(project(":spring-jdbc"))
api(project(":spring-jms"))
api(project(":spring-test"))
api(project(":spring-web"))
api(project(":spring-webflux"))
api(project(":spring-webmvc"))
api(project(":spring-context-support"))
api(project(":spring-aspects"))
api(project(":spring-websocket"))
api("org.jetbrains.kotlin:kotlin-stdlib")
api("jakarta.jms:jakarta.jms-api")
api("jakarta.servlet:jakarta.servlet-api")
api("org.apache.commons:commons-dbcp2:2.11.0")
api("com.mchange:c3p0:0.9.5.5")
api("com.fasterxml.jackson.core:jackson-databind")
api("com.fasterxml.jackson.module:jackson-module-parameter-names")
api("jakarta.validation:jakarta.validation-api")
api("org.aspectj:aspectjweaver")
api("com.mchange:c3p0:0.9.5.5")
api("com.oracle.database.jdbc:ojdbc11")
api("io.projectreactor.netty:reactor-netty-http")
api("org.eclipse.jetty.websocket:jetty-websocket-jetty-api")
api("javax.cache:cache-api")
api("jakarta.jms:jakarta.jms-api")
api("jakarta.servlet:jakarta.servlet-api")
api("jakarta.resource:jakarta.resource-api")
api("jakarta.validation:jakarta.validation-api")
api("javax.cache:cache-api")
api("org.apache.activemq:activemq-ra:6.1.2")
api("org.apache.commons:commons-dbcp2:2.11.0")
api("org.aspectj:aspectjweaver")
api("org.eclipse.jetty.websocket:jetty-websocket-jetty-api")
api("org.jetbrains.kotlin:kotlin-stdlib")
implementation(project(":spring-core-test"))
implementation("org.assertj:assertj-core")
+96 -86
View File
@@ -106,90 +106,6 @@
*** 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/bean-overriding.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-testbean.adoc[]
***** xref:testing/annotations/integration-spring/annotation-mockitobean.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[]
@@ -248,6 +164,7 @@
**** xref:web/webmvc/mvc-servlet/multipart.adoc[]
**** xref:web/webmvc/mvc-servlet/logging.adoc[]
*** xref:web/webmvc/filters.adoc[]
*** xref:web/webmvc/message-converters.adoc[]
*** xref:web/webmvc/mvc-controller.adoc[]
**** xref:web/webmvc/mvc-controller/ann.adoc[]
**** xref:web/webmvc/mvc-controller/ann-requestmapping.adoc[]
@@ -288,6 +205,7 @@
**** 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-fragments.adoc[]
**** xref:web/webmvc-view/mvc-jsp.adoc[]
**** xref:web/webmvc-view/mvc-feeds.adoc[]
**** xref:web/webmvc-view/mvc-document.adoc[]
@@ -395,6 +313,97 @@
** xref:web/webflux-test.adoc[]
** xref:rsocket.adoc[]
** xref:web/webflux-reactive-libraries.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/bean-overriding.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/mockmvc.adoc[]
*** xref:testing/mockmvc/overview.adoc[]
*** xref:testing/mockmvc/setup-options.adoc[]
*** xref:testing/mockmvc/hamcrest.adoc[]
**** xref:testing/mockmvc/hamcrest/static-imports.adoc[]
**** xref:testing/mockmvc/hamcrest/setup.adoc[]
**** xref:testing/mockmvc/hamcrest/setup-steps.adoc[]
**** xref:testing/mockmvc/hamcrest/requests.adoc[]
**** xref:testing/mockmvc/hamcrest/expectations.adoc[]
**** xref:testing/mockmvc/hamcrest/async-requests.adoc[]
**** xref:testing/mockmvc/hamcrest/vs-streaming-response.adoc[]
**** xref:testing/mockmvc/hamcrest/filters.adoc[]
*** xref:testing/mockmvc/assertj.adoc[]
**** xref:testing/mockmvc/assertj/setup.adoc[]
**** xref:testing/mockmvc/assertj/requests.adoc[]
**** xref:testing/mockmvc/assertj/assertions.adoc[]
**** xref:testing/mockmvc/assertj/integration.adoc[]
*** xref:testing/mockmvc/htmlunit.adoc[]
**** xref:testing/mockmvc/htmlunit/why.adoc[]
**** xref:testing/mockmvc/htmlunit/mah.adoc[]
**** xref:testing/mockmvc/htmlunit/webdriver.adoc[]
**** xref:testing/mockmvc/htmlunit/geb.adoc[]
*** xref:testing/mockmvc/vs-end-to-end-integration-tests.adoc[]
*** xref:testing/mockmvc/resources.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-testbean.adoc[]
***** xref:testing/annotations/integration-spring/annotation-mockitobean.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:integration.adoc[]
** xref:integration/rest-clients.adoc[]
** xref:integration/jms.adoc[]
@@ -442,5 +451,6 @@
** xref:languages/groovy.adoc[]
** xref:languages/dynamic.adoc[]
* xref:appendix.adoc[]
* {spring-framework-wiki}[Wiki]
* {spring-framework-docs-root}/{spring-version}/javadoc-api/[Java API,window=_blank, role=link-external]
* {spring-framework-api-kdoc}/[Kotlin API,window=_blank, role=link-external]
* {spring-framework-wiki}[Wiki, window=_blank, role=link-external]
@@ -58,7 +58,7 @@ The following example shows a simple `MethodInterceptor` implementation:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class DebugInterceptor implements MethodInterceptor {
@@ -73,7 +73,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class DebugInterceptor : MethodInterceptor {
@@ -139,7 +139,7 @@ The following example shows a before advice in Spring, which counts all method i
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class CountingBeforeAdvice implements MethodBeforeAdvice {
@@ -157,7 +157,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class CountingBeforeAdvice : MethodBeforeAdvice {
@@ -197,7 +197,7 @@ The following advice is invoked if a `RemoteException` is thrown (including from
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class RemoteThrowsAdvice implements ThrowsAdvice {
@@ -209,7 +209,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class RemoteThrowsAdvice : ThrowsAdvice {
@@ -228,7 +228,7 @@ arguments, and target object. The following advice is invoked if a `ServletExcep
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class ServletThrowsAdviceWithArguments implements ThrowsAdvice {
@@ -240,7 +240,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class ServletThrowsAdviceWithArguments : ThrowsAdvice {
@@ -259,7 +259,7 @@ methods can be combined in a single class. The following listing shows the final
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public static class CombinedThrowsAdvice implements ThrowsAdvice {
@@ -275,7 +275,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class CombinedThrowsAdvice : ThrowsAdvice {
@@ -326,7 +326,7 @@ not thrown exceptions:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class CountingAfterReturningAdvice implements AfterReturningAdvice {
@@ -345,7 +345,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class CountingAfterReturningAdvice : AfterReturningAdvice {
@@ -420,7 +420,7 @@ introduce the following interface to one or more objects:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public interface Lockable {
void lock();
@@ -431,7 +431,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
interface Lockable {
fun lock()
@@ -480,7 +480,7 @@ The following example shows the example `LockMixin` class:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class LockMixin extends DelegatingIntroductionInterceptor implements Lockable {
@@ -510,7 +510,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class LockMixin : DelegatingIntroductionInterceptor(), Lockable {
@@ -556,7 +556,7 @@ The following example shows our `LockMixinAdvisor` class:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class LockMixinAdvisor extends DefaultIntroductionAdvisor {
@@ -568,7 +568,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class LockMixinAdvisor : DefaultIntroductionAdvisor(LockMixin(), Lockable::class.java)
----
@@ -10,7 +10,7 @@ following methods:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
Advisor[] getAdvisors();
@@ -35,7 +35,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
fun getAdvisors(): Array<Advisor>
@@ -90,7 +90,7 @@ manipulating its advice:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
Advised advised = (Advised) myObject;
Advisor[] advisors = advised.getAdvisors();
@@ -110,7 +110,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val advised = myObject as Advised
val advisors = advised.advisors
@@ -196,14 +196,14 @@ follows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
Person person = (Person) factory.getBean("person");
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val person = factory.getBean("person") as Person
----
@@ -187,7 +187,7 @@ following example shows how to subclass `StaticMethodMatcherPointcut`:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
class TestStaticPointcut extends StaticMethodMatcherPointcut {
@@ -199,7 +199,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class TestStaticPointcut : StaticMethodMatcherPointcut() {
@@ -12,7 +12,7 @@ interceptor and one advisor:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl);
factory.addAdvice(myMethodInterceptor);
@@ -22,7 +22,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val factory = ProxyFactory(myBusinessInterfaceImpl)
factory.addAdvice(myMethodInterceptor)
@@ -38,7 +38,7 @@ You can change the target by using the `swap()` method on HotSwappableTargetSour
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper");
Object oldTarget = swapper.swap(newTarget);
@@ -46,7 +46,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val swapper = beanFactory.getBean("swapper") as HotSwappableTargetSource
val oldTarget = swapper.swap(newTarget)
@@ -152,7 +152,7 @@ The cast is defined as follows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject");
System.out.println("Max pool size is " + conf.getMaxSize());
@@ -160,7 +160,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val conf = beanFactory.getBean("businessObject") as PoolingConfig
println("Max pool size is " + conf.maxSize)
@@ -221,8 +221,8 @@ NOTE: `ThreadLocal` instances come with serious issues (potentially resulting in
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
always remember to correctly set and unset (where the latter involves a call to
`ThreadLocal.remove()`) 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.
@@ -15,7 +15,7 @@ The basic usage for this class is very simple, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
// create a factory that can generate a proxy for the given target object
AspectJProxyFactory factory = new AspectJProxyFactory(targetObject);
@@ -34,7 +34,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
// create a factory that can generate a proxy for the given target object
val factory = AspectJProxyFactory(targetObject)
@@ -17,7 +17,7 @@ The following example uses an inline pointcut expression.
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@@ -34,7 +34,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Before
@@ -57,7 +57,7 @@ as follows:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@@ -74,7 +74,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Before
@@ -101,7 +101,7 @@ You can declare it by using the `@AfterReturning` annotation.
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;
@@ -118,7 +118,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.AfterReturning
@@ -146,7 +146,7 @@ access, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;
@@ -165,7 +165,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.AfterReturning
@@ -204,7 +204,7 @@ following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
@@ -221,7 +221,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.AfterThrowing
@@ -247,7 +247,7 @@ The following example shows how to do so:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
@@ -266,7 +266,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.AfterThrowing
@@ -311,7 +311,7 @@ purposes. The following example shows how to use after finally advice:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.After;
@@ -328,7 +328,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.After
@@ -417,7 +417,7 @@ The following example shows how to use around advice:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
@@ -438,7 +438,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Around
@@ -500,7 +500,7 @@ You could write the following:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Before("execution(* com.xyz.dao.*.*(..)) && args(account,..)")
public void validateAccount(Account account) {
@@ -510,7 +510,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Before("execution(* com.xyz.dao.*.*(..)) && args(account,..)")
fun validateAccount(account: Account) {
@@ -533,7 +533,7 @@ from the advice. This would look as follows:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Pointcut("execution(* com.xyz.dao.*.*(..)) && args(account,..)")
private void accountDataAccessOperation(Account account) {}
@@ -546,7 +546,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Pointcut("execution(* com.xyz.dao.*.*(..)) && args(account,..)")
private fun accountDataAccessOperation(account: Account) {
@@ -572,7 +572,7 @@ The following shows the definition of the `@Auditable` annotation:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@@ -583,7 +583,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
@@ -597,7 +597,7 @@ The following shows the advice that matches the execution of `@Auditable` method
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Before("com.xyz.Pointcuts.publicMethod() && @annotation(auditable)") // <1>
public void audit(Auditable auditable) {
@@ -609,7 +609,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Before("com.xyz.Pointcuts.publicMethod() && @annotation(auditable)") // <1>
fun audit(auditable: Auditable) {
@@ -630,7 +630,7 @@ you have a generic type like the following:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
public interface Sample<T> {
void sampleGenericMethod(T param);
@@ -640,7 +640,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
interface Sample<T> {
fun sampleGenericMethod(param: T)
@@ -656,7 +656,7 @@ tying the advice parameter to the parameter type for which you want to intercept
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Before("execution(* ..Sample+.sampleGenericMethod(*)) && args(param)")
public void beforeSampleMethod(MyType param) {
@@ -666,7 +666,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Before("execution(* ..Sample+.sampleGenericMethod(*)) && args(param)")
fun beforeSampleMethod(param: MyType) {
@@ -682,7 +682,7 @@ pointcut as follows:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Before("execution(* ..Sample+.sampleGenericCollectionMethod(*)) && args(param)")
public void beforeSampleMethod(Collection<MyType> param) {
@@ -692,7 +692,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Before("execution(* ..Sample+.sampleGenericCollectionMethod(*)) && args(param)")
fun beforeSampleMethod(param: Collection<MyType>) {
@@ -756,7 +756,7 @@ The following example shows how to use the `argNames` attribute:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Before(
value = "com.xyz.Pointcuts.publicMethod() && target(bean) && @annotation(auditable)", // <1>
@@ -771,7 +771,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Before(
value = "com.xyz.Pointcuts.publicMethod() && target(bean) && @annotation(auditable)", // <1>
@@ -794,7 +794,7 @@ point object, the `argNames` attribute does not need to include it:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Before(
value = "com.xyz.Pointcuts.publicMethod() && target(bean) && @annotation(auditable)", // <1>
@@ -809,7 +809,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Before(
value = "com.xyz.Pointcuts.publicMethod() && target(bean) && @annotation(auditable)", // <1>
@@ -833,7 +833,7 @@ the `argNames` attribute:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Before("com.xyz.Pointcuts.publicMethod()") // <1>
public void audit(JoinPoint jp) {
@@ -844,7 +844,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Before("com.xyz.Pointcuts.publicMethod()") // <1>
fun audit(jp: JoinPoint) {
@@ -867,7 +867,7 @@ The following example shows how to do so:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Around("execution(List<Account> find*(..)) && " +
"com.xyz.CommonPointcuts.inDataAccessLayer() && " +
@@ -882,7 +882,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Around("execution(List<Account> find*(..)) && " +
"com.xyz.CommonPointcuts.inDataAccessLayer() && " +
@@ -923,7 +923,7 @@ Each of the distinct advice types of a particular aspect is conceptually meant t
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
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
@@ -17,7 +17,7 @@ annotation. Consider the following example:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Aspect("perthis(execution(* com.xyz..service.*.*(..)))")
public class MyAspect {
@@ -33,7 +33,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Aspect("perthis(execution(* com.xyz..service.*.*(..)))")
class MyAspect {
@@ -9,13 +9,13 @@ You can make an introduction by using the `@DeclareParents` annotation. This ann
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):
interfaces also implement the `UsageTracked` interface (for example, for statistics via JMX):
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Aspect
public class UsageTracking {
@@ -33,7 +33,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Aspect
class UsageTracking {
@@ -63,14 +63,14 @@ you would write the following:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
UsageTracked usageTracked = context.getBean("myService", UsageTracked.class);
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
val usageTracked = context.getBean<UsageTracked>("myService")
----
@@ -19,7 +19,7 @@ matches the execution of any method named `transfer`:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Pointcut("execution(* transfer(..))") // the pointcut expression
private void anyOldTransfer() {} // the pointcut signature
@@ -27,7 +27,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Pointcut("execution(* transfer(..))") // the pointcut expression
private fun anyOldTransfer() {} // the pointcut signature
@@ -150,7 +150,7 @@ pointcut expressions by name. The following example shows three pointcut express
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz;
@@ -174,7 +174,7 @@ trading module.
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz
@@ -217,7 +217,7 @@ expressions for this purpose. Such a class typically resembles the following
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages",fold="none"]
[source,java,indent=0,subs="verbatim",chomp="-packages",fold="none"]
----
package com.xyz;
@@ -279,7 +279,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages",fold="none"]
[source,kotlin,indent=0,subs="verbatim",chomp="-packages",fold="none"]
----
package com.xyz
@@ -59,7 +59,7 @@ For example, in the @AspectJ style you can write something like the following:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Pointcut("execution(* get*())")
public void propertyAccess() {}
@@ -73,7 +73,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Pointcut("execution(* get*())")
fun propertyAccess() {}
@@ -65,7 +65,7 @@ with less potential for errors. For example, you do not need to invoke the `proc
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
the appropriate type (for example, 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
@@ -6,22 +6,26 @@ target object. JDK dynamic proxies are built into the JDK, whereas CGLIB is a co
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.
proxy is used, and 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 which
is a runtime-generated subclass of the target type.
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.
* Your CGLIB proxy usage may face limitations with the JDK 9+ platform module system.
As a typical case, you cannot create a CGLIB proxy for a class from the `java.lang`
package when deploying on the module path. Such cases require a JVM bootstrap flag
* `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.
* Methods that are not visible for example, package-private methods in a parent class
from a different package cannot be advised because they are effectively private.
* The constructor of your proxied object will not be called twice, since the CGLIB proxy
instance is created through Objenesis. However, if your JVM does not allow for
constructor bypassing, you might see double invocations and corresponding debug log
entries from Spring's AOP support.
* Your CGLIB proxy usage may face limitations with the Java Module System. As a typical
case, you cannot create a CGLIB proxy for a class from the `java.lang` package when
deploying on the module path. Such cases require a JVM bootstrap flag
`--add-opens=java.base/java.lang=ALL-UNNAMED` which is not available for modules.
To force the use of CGLIB proxies, set the value of the `proxy-target-class` attribute
@@ -65,15 +69,14 @@ Spring AOP is proxy-based. It is vitally important that you grasp the semantics
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:
Consider first the scenario where you have a plain-vanilla, un-proxied object reference,
as the following code snippet shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
public class SimplePojo implements Pojo {
@@ -90,7 +93,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
class SimplePojo : Pojo {
@@ -115,7 +118,7 @@ image::aop-proxy-plain-pojo-call.png[]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
public class Main {
@@ -129,7 +132,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
fun main() {
val pojo = SimplePojo()
@@ -148,7 +151,7 @@ image::aop-proxy-call.png[]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
public class Main {
@@ -166,7 +169,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
fun main() {
val factory = ProxyFactory(SimplePojo())
@@ -187,26 +190,35 @@ the interceptors (advice) that are relevant to that particular method call. Howe
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.
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. In other words,
self invocation via an explicit or implicit `this` reference will bypass the advice.
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:
To address that, you have the following options.
Avoid self invocation ::
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.
Inject a self reference ::
An alternative approach is to make use of
xref:core/beans/annotation-config/autowired.adoc#beans-autowired-annotation-self-injection[self injection],
and invoke methods on the proxy via the self reference instead of via `this`.
Use `AopContext.currentProxy()` ::
This last approach is highly discouraged, and we hesitate to point it out, in favor of
the previous options. However, as a last resort you can choose to tie the logic within
your class to Spring AOP, as the following example shows.
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
public class SimplePojo implements Pojo {
public void foo() {
// this works, but... gah!
// This works, but it should be avoided if possible.
((Pojo) AopContext.currentProxy()).bar();
}
@@ -218,12 +230,12 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
class SimplePojo : Pojo {
fun foo() {
// this works, but... gah!
// This works, but it should be avoided if possible.
(AopContext.currentProxy() as Pojo).bar()
}
@@ -234,16 +246,16 @@ Kotlin::
----
======
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:
The use of `AopContext.currentProxy()` 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
reduces some of the benefits of AOP. It also requires that the `ProxyFactory` is
configured to expose the proxy, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
public class Main {
@@ -262,7 +274,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
fun main() {
val factory = ProxyFactory(SimplePojo())
@@ -277,9 +289,6 @@ Kotlin::
----
======
Finally, it must be noted that AspectJ does not have this self-invocation issue because
it is not a proxy-based AOP framework.
NOTE: AspectJ compile-time weaving and load-time weaving do not have this self-invocation
issue because they apply advice within the bytecode instead of via a proxy.
@@ -136,7 +136,7 @@ parameters of the matching names, as follows:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
public void monitor(Object service) {
// ...
@@ -145,7 +145,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
fun monitor(service: Any) {
// ...
@@ -282,14 +282,14 @@ example, you can declare the method signature as follows:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
public void doAccessCheck(Object retVal) {...
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
fun doAccessCheck(retVal: Any) {...
----
@@ -340,14 +340,14 @@ The type of this parameter constrains matching in the same way as described for
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
public void doRecoveryActions(DataAccessException dataAccessEx) {...
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
fun doRecoveryActions(dataAccessEx: DataAccessException) {...
----
@@ -421,7 +421,7 @@ The implementation of the `doBasicProfiling` advice can be exactly the same as i
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
@@ -433,7 +433,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
fun doBasicProfiling(pjp: ProceedingJoinPoint): Any? {
// start stopwatch
@@ -475,7 +475,7 @@ some around advice used in conjunction with a number of strongly typed parameter
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz.service;
@@ -494,7 +494,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz.service
@@ -521,7 +521,7 @@ proceed with the method call. The presence of this parameter is an indication th
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz;
@@ -545,7 +545,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz
@@ -610,7 +610,7 @@ Consider the following driver script:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
public class Boot {
@@ -624,7 +624,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
fun main() {
val ctx = ClassPathXmlApplicationContext("beans.xml")
@@ -714,7 +714,7 @@ The class that backs the `usageTracking` bean would then contain the following m
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
public void recordUsage(UsageTracked usageTracked) {
usageTracked.incrementUseCount();
@@ -723,7 +723,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
fun recordUsage(usageTracked: UsageTracked) {
usageTracked.incrementUseCount()
@@ -742,14 +742,14 @@ following:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
UsageTracked usageTracked = context.getBean("myService", UsageTracked.class);
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
val usageTracked = context.getBean("myService", UsageTracked.class)
----
@@ -829,7 +829,7 @@ call `proceed` multiple times. The following listing shows the basic aspect impl
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
public class ConcurrentOperationExecutor implements Ordered {
@@ -869,7 +869,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
class ConcurrentOperationExecutor : Ordered {
@@ -953,7 +953,7 @@ to annotate the implementation of service operations, as the following example s
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Retention(RetentionPolicy.RUNTIME)
// marker annotation
@@ -963,7 +963,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Retention(AnnotationRetention.RUNTIME)
// marker annotation
@@ -36,7 +36,7 @@ following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz.domain;
@@ -50,7 +50,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz.domain
@@ -84,7 +84,7 @@ can do so directly in the annotation, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz.domain;
@@ -98,7 +98,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz.domain
@@ -153,14 +153,14 @@ available for use in the body of the constructors, you need to define this on th
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary"]
[source,java,indent=0,subs="verbatim"]
----
@Configurable(preConstruction = true)
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
[source,kotlin,indent=0,subs="verbatim"]
----
@Configurable(preConstruction = true)
----
@@ -389,7 +389,7 @@ who typically are in charge of the deployment configuration, such as the launch
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
{spring-github-org}/spring-petclinic[Petclinic sample application].
{petclinic-github-org}/spring-framework-petclinic[Petclinic sample application based on Spring Framework].
[[aop-aj-ltw-first-example]]
@@ -413,7 +413,7 @@ It is a time-based profiler that uses the @AspectJ-style of aspect declaration:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz;
@@ -446,7 +446,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz
@@ -544,7 +544,7 @@ driver class with a `main(..)` method to demonstrate the LTW in action:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz;
@@ -566,7 +566,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz
@@ -625,7 +625,7 @@ result:
======
Java::
+
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz;
@@ -647,7 +647,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim",chomp="-packages"]
----
package com.xyz
+152 -37
View File
@@ -140,7 +140,7 @@ Taking our previous example, let's assume that `DataSourceConfiguration` is as f
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration(proxyBeanMethods = false)
public class DataSourceConfiguration {
@@ -155,7 +155,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration(proxyBeanMethods = false)
class DataSourceConfiguration {
@@ -176,7 +176,7 @@ The AOT engine will convert the configuration class above to code similar to the
======
Java::
+
[source,java,indent=0,role="primary"]
[source,java,indent=0]
----
/**
* Bean definitions for {@link DataSourceConfiguration}
@@ -278,7 +278,7 @@ Consider the following example:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration(proxyBeanMethods = false)
public class UserConfiguration {
@@ -290,6 +290,19 @@ Java::
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration(proxyBeanMethods = false)
class UserConfiguration {
@Bean
fun myInterface(): MyInterface = MyImplementation()
}
----
======
In the example above, the declared type for the `myInterface` bean is `MyInterface`.
@@ -302,7 +315,7 @@ The example above should be rewritten as follows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration(proxyBeanMethods = false)
public class UserConfiguration {
@@ -314,6 +327,19 @@ Java::
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration(proxyBeanMethods = false)
class UserConfiguration {
@Bean
fun myInterface() = MyImplementation()
}
----
======
If you are registering bean definitions programmatically, consider using `RootBeanBefinition` as it allows to specify a `ResolvableType` that handles generics.
@@ -326,6 +352,19 @@ However, this is not a best practice and flagging the preferred constructor with
In case you are working on a code base that you cannot modify, you can set the {spring-framework-api}/beans/factory/support/AbstractBeanDefinition.html#PREFERRED_CONSTRUCTORS_ATTRIBUTE[`preferredConstructors` attribute] on the related bean definition to indicate which constructor should be used.
[[aot.bestpractices.comlext-data-structure]]
=== Avoid Complex Data Structure for Constructor Parameters and Properties
When crafting a `RootBeanDefinition` programmatically, you are not constrained in terms of types that you can use.
For instance, you may have a custom `record` with several properties that your bean takes as a constructor argument.
While this works fine with the regular runtime, AOT does not know how to generate the code of your custom data structure.
A good rule of thumb is to keep in mind that bean definitions are an abstraction on top of several models.
Rather than using such structure, decomposing to simple types or referring to a bean that is built as such is recommended.
As a last resort, you can implement your own `org.springframework.aot.generate.ValueCodeGenerator$Delegate`.
To use it, register its fully qualified name in `META-INF/spring/aot.factories` using the `Delegate` as the key.
[[aot.bestpractices.custom-arguments]]
=== Avoid Creating Bean with Custom Arguments
@@ -352,12 +391,21 @@ Consider the following example:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class ClientFactoryBean<T extends AbstractClient> implements FactoryBean<T> {
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class ClientFactoryBean<T : AbstractClient> : FactoryBean<T> {
// ...
}
----
======
A concrete client declaration should provide a resolved generic for the client, as shown in the following example:
@@ -366,7 +414,7 @@ A concrete client declaration should provide a resolved generic for the client,
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration(proxyBeanMethods = false)
public class UserConfiguration {
@@ -378,6 +426,19 @@ Java::
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration(proxyBeanMethods = false)
class UserConfiguration {
@Bean
fun myClient() = ClientFactoryBean<MyClient>(...)
}
----
======
If the `FactoryBean` bean definition is registered programmatically, make sure to follow these steps:
@@ -392,13 +453,23 @@ The following example showcases a basic definition:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
RootBeanDefinition beanDefinition = new RootBeanDefinition(ClientFactoryBean.class);
beanDefinition.setTargetType(ResolvableType.forClassWithGenerics(ClientFactoryBean.class, MyClient.class));
// ...
registry.registerBeanDefinition("myClient", beanDefinition);
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val beanDefinition = RootBeanDefinition(ClientFactoryBean::class.java)
beanDefinition.setTargetType(ResolvableType.forClassWithGenerics(ClientFactoryBean::class.java, MyClient::class.java));
// ...
registry.registerBeanDefinition("myClient", beanDefinition)
----
======
[[aot.bestpractices.jpa]]
@@ -410,7 +481,7 @@ The JPA persistence unit has to be known upfront for certain optimizations to ap
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Bean
LocalContainerEntityManagerFactoryBean customDBEntityManagerFactory(DataSource dataSource) {
@@ -420,6 +491,19 @@ Java::
return factoryBean;
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Bean
fun customDBEntityManagerFactory(dataSource: DataSource): LocalContainerEntityManagerFactoryBean {
val factoryBean = LocalContainerEntityManagerFactoryBean()
factoryBean.dataSource = 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
@@ -429,7 +513,7 @@ factory bean definition, as shown by the following example:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Bean
PersistenceManagedTypes persistenceManagedTypes(ResourceLoader resourceLoader) {
@@ -445,6 +529,25 @@ Java::
return factoryBean;
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Bean
fun persistenceManagedTypes(resourceLoader: ResourceLoader): PersistenceManagedTypes {
return PersistenceManagedTypesScanner(resourceLoader)
.scan("com.example.app")
}
@Bean
fun customDBEntityManagerFactory(dataSource: DataSource, managedTypes: PersistenceManagedTypes): LocalContainerEntityManagerFactoryBean {
val factoryBean = LocalContainerEntityManagerFactoryBean()
factoryBean.dataSource = dataSource
factoryBean.setManagedTypes(managedTypes)
return factoryBean
}
----
======
[[aot.hints]]
@@ -462,10 +565,17 @@ The following example makes sure that `config/app.properties` can be loaded from
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
runtimeHints.resources().registerPattern("config/app.properties");
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
runtimeHints.resources().registerPattern("config/app.properties")
----
======
A number of contracts are handled automatically during AOT processing.
@@ -496,40 +606,45 @@ It is also possible to register an implementation statically by adding an entry
{spring-framework-api}/aot/hint/annotation/Reflective.html[`@Reflective`] provides an idiomatic way to flag the need for reflection on an annotated element.
For instance, `@EventListener` is meta-annotated with `@Reflective` since the underlying implementation invokes the annotated method using reflection.
By default, only Spring beans are considered, and an invocation hint is registered for the annotated element.
This can be tuned by specifying a custom `ReflectiveProcessor` implementation via the
`@Reflective` annotation.
Out-of-the-box, only Spring beans are considered but you can opt-in for scanning using `@ReflectiveScan`.
In the example below, all types of the package `com.example.app` and their subpackages are considered:
include-code::./MyConfiguration[]
Scanning happens during AOT processing and the types in the target packages do not need to have a class-level annotation to be considered.
This performs a "deep scan" and the presence of `@Reflective`, either directly or as a meta-annotation, is checked on types, fields, constructors, methods, and enclosed elements.
By default, `@Reflective` registers an invocation hint for the annotated element.
This can be tuned by specifying a custom `ReflectiveProcessor` implementation via the `@Reflective` annotation.
Library authors can reuse this annotation for their own purposes.
If components other than Spring beans need to be processed, a `BeanFactoryInitializationAotProcessor` can detect the relevant types and use `ReflectiveRuntimeHintsRegistrar` to process them.
An example of such customization is covered in the next section.
[[aot.hints.register-reflection-for-binding]]
=== `@RegisterReflectionForBinding`
[[aot.hints.register-reflection]]
=== `@RegisterReflection`
{spring-framework-api}/aot/hint/annotation/RegisterReflectionForBinding.html[`@RegisterReflectionForBinding`] is a specialization of `@Reflective` that registers the need for serializing arbitrary types.
{spring-framework-api}/aot/hint/annotation/RegisterReflection.html[`@RegisterReflection`] is a specialization of `@Reflective` that provides a declarative way of registering reflection for arbitrary types.
NOTE: As a specialization of `@Reflective`, this is also detected if you're using `@ReflectiveScan`.
In the following example, public constructors and public methods can be invoked via reflection on `AccountService`:
include-code::./MyConfiguration[tag=snippet,indent=0]
`@RegisterReflection` can be applied to any target type at the class level, but it can also be applied directly to a method to better indicate where the hints are actually required.
`@RegisterReflection` can be used as a meta-annotation to provide more specific needs.
{spring-framework-api}/aot/hint/annotation/RegisterReflectionForBinding.html[`@RegisterReflectionForBinding`] is such composed annotation and registers the need for serializing arbitrary types.
A typical use case is the use of DTOs that the container cannot infer, such as using a web client within a method body.
`@RegisterReflectionForBinding` can be applied to any Spring bean at the class level, but it can also be applied directly to a method, field, or constructor to better indicate where the hints are actually required.
The following example registers `Account` for serialization.
The following example registers `Order` for serialization.
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Component
public class OrderService {
include-code::./OrderService[tag=snippet,indent=0]
@RegisterReflectionForBinding(Account.class)
public void process(Order order) {
// ...
}
}
----
======
This registers hints for constructors, fields, properties, and record components of `Order`.
Hints are also registered for types transitively used on properties and record components.
In other words, if `Order` exposes others types, hints are registered for those as well.
[[aot.hints.testing]]
=== Testing Runtime Hints
@@ -561,7 +676,7 @@ If you forgot to contribute a hint, the test will fail and provide some details
[source,txt,indent=0,subs="verbatim,quotes"]
----
org.springframework.docs.core.aot.hints.testing.SampleReflection performReflection
INFO: Spring version:6.0.0-SNAPSHOT
INFO: Spring version: 6.2.0
Missing <"ReflectionHints"> for invocation <java.lang.Class#forName>
with arguments ["org.springframework.core.SpringVersion",
@@ -145,7 +145,7 @@ use the `NamespaceHandlerSupport` class:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package org.springframework.samples.xml;
@@ -161,7 +161,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package org.springframework.samples.xml
@@ -202,7 +202,7 @@ we can parse our custom XML content, as you can see in the following example:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package org.springframework.samples.xml;
@@ -240,7 +240,7 @@ single `BeanDefinition` represents.
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package org.springframework.samples.xml
@@ -416,7 +416,7 @@ The following listing shows the `Component` class:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package com.foo;
@@ -449,7 +449,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package com.foo
@@ -480,7 +480,7 @@ setter property for the `components` property. The following listing shows such
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package com.foo;
@@ -522,7 +522,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package com.foo
@@ -598,7 +598,7 @@ we then create a custom `NamespaceHandler`:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package com.foo;
@@ -614,7 +614,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package com.foo
@@ -637,7 +637,7 @@ listing shows our custom `BeanDefinitionParser` implementation:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package com.foo;
@@ -688,7 +688,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package com.foo
@@ -787,7 +787,7 @@ JCache-initializing `BeanDefinition`. The following listing shows our `JCacheIni
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package com.foo;
@@ -807,7 +807,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package com.foo
@@ -843,7 +843,7 @@ Next, we need to create the associated `NamespaceHandler`, as follows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package com.foo;
@@ -861,7 +861,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package com.foo
@@ -886,7 +886,7 @@ The following listing shows our `BeanDefinitionDecorator` implementation:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package com.foo;
@@ -942,7 +942,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package com.foo
@@ -121,7 +121,7 @@ The following example enumeration shows how easy injecting an enum value is:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package jakarta.persistence;
@@ -134,7 +134,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package jakarta.persistence
@@ -152,7 +152,7 @@ Now consider the following setter of type `PersistenceContextType` and the corre
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package example;
@@ -168,7 +168,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package example
@@ -20,7 +20,7 @@ can be found in the xref:core/beans/standard-annotations.adoc[relevant section].
[NOTE]
====
Annotation injection is performed before external property injection. Thus, external
configuration (e.g. XML-specified bean properties) effectively overrides the annotations
configuration (for example, XML-specified bean properties) effectively overrides the annotations
for properties when wired through mixed approaches.
====
@@ -15,7 +15,7 @@ primary `MovieCatalog`:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class MovieConfiguration {
@@ -33,7 +33,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class MovieConfiguration {
@@ -58,7 +58,7 @@ bean is left, it is effectively primary as well:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class MovieConfiguration {
@@ -76,7 +76,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class MovieConfiguration {
@@ -100,7 +100,7 @@ With both variants of the preceding configuration, the following
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MovieRecommender {
@@ -113,7 +113,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MovieRecommender {
@@ -14,7 +14,7 @@ this can be a plain descriptive value, as shown in the following example:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MovieRecommender {
@@ -28,7 +28,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MovieRecommender {
@@ -50,7 +50,7 @@ method parameters, as shown in the following example:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MovieRecommender {
@@ -71,7 +71,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MovieRecommender {
@@ -154,50 +154,35 @@ Letting qualifier values select against target bean names, within the type-match
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 is, the field name or parameter name) against the target bean names and chooses
the same-named candidate, if any (either by bean name or by associated alias).
Since version 6.1, this requires the `-parameters` Java compiler flag to be present.
As of 6.2, the container applies fast shortcut resolution for bean name matches,
bypassing the full type matching algorithm when the parameter name matches the
bean name and no type, qualifier or primary conditions override the match. It is
therefore recommendable for your parameter names to match the target bean names.
====
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`
As an alternative for injection by name, consider 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
That said, 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` also considers self references for injection (that is, references back to
the bean that is currently injected). See
xref:core/beans/annotation-config/autowired.adoc#beans-autowired-annotation-self-injection[Self Injection]
for details.
`@Autowired` applies to fields, constructors, and multi-argument methods, allowing for
narrowing through qualifier annotations at the parameter level. In contrast, `@Resource`
@@ -213,7 +198,7 @@ provide the `@Qualifier` annotation within your definition, as the following exa
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@@ -226,7 +211,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER)
@Retention(AnnotationRetention.RUNTIME)
@@ -244,7 +229,7 @@ following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MovieRecommender {
@@ -265,7 +250,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MovieRecommender {
@@ -337,7 +322,7 @@ the simple annotation, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@@ -348,7 +333,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER)
@Retention(AnnotationRetention.RUNTIME)
@@ -366,7 +351,7 @@ following example:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MovieRecommender {
@@ -381,7 +366,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MovieRecommender {
@@ -421,7 +406,7 @@ consider the following annotation definition:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@@ -436,7 +421,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER)
@Retention(AnnotationRetention.RUNTIME)
@@ -453,7 +438,7 @@ In this case `Format` is an enum, defined as follows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public enum Format {
VHS, DVD, BLURAY
@@ -462,7 +447,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
enum class Format {
VHS, DVD, BLURAY
@@ -479,7 +464,7 @@ for both attributes: `genre` and `format`, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MovieRecommender {
@@ -505,7 +490,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MovieRecommender {
@@ -13,7 +13,7 @@ You can apply the `@Autowired` annotation to constructors, as the following exam
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MovieRecommender {
@@ -30,7 +30,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MovieRecommender @Autowired constructor(
private val customerPreferenceDao: CustomerPreferenceDao)
@@ -54,7 +54,7 @@ as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class SimpleMovieLister {
@@ -71,7 +71,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class SimpleMovieLister {
@@ -91,7 +91,7 @@ arguments, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MovieRecommender {
@@ -112,7 +112,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MovieRecommender {
@@ -139,7 +139,7 @@ following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MovieRecommender {
@@ -159,7 +159,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MovieRecommender @Autowired constructor(
private val customerPreferenceDao: CustomerPreferenceDao) {
@@ -186,14 +186,37 @@ implementation type, consider declaring the most specific return type on your fa
method (at least as specific as required by the injection points referring to your bean).
====
.[[beans-autowired-annotation-self-injection]]Self Injection
****
`@Autowired` also considers self references for injection (that is, references back to
the bean that is currently injected).
Note, however, that self injection is a fallback mechanism. Regular dependencies on other
components always have precedence. In that sense, self references do not participate in
regular autowiring 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. As an
alternative, consider factoring out the affected methods to a separate delegate bean in
such a scenario.
Another alternative is to use `@Resource`, which may obtain a proxy back to the current
bean by its unique name.
======
[NOTE]
====
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.
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.
Trying to inject the results from `@Bean` methods in 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).
====
======
****
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
@@ -203,7 +226,7 @@ expects an array of that type, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MovieRecommender {
@@ -216,7 +239,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MovieRecommender {
@@ -234,7 +257,7 @@ The same applies for typed collections, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MovieRecommender {
@@ -251,7 +274,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MovieRecommender {
@@ -296,7 +319,7 @@ corresponding bean names, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MovieRecommender {
@@ -313,7 +336,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MovieRecommender {
@@ -338,7 +361,7 @@ non-required (i.e., by setting the `required` attribute in `@Autowired` to `fals
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class SimpleMovieLister {
@@ -355,7 +378,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class SimpleMovieLister {
@@ -421,15 +444,15 @@ through Java 8's `java.util.Optional`, as the following example shows:
}
----
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:
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"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class SimpleMovieLister {
@@ -442,7 +465,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class SimpleMovieLister {
@@ -465,7 +488,7 @@ an `ApplicationContext` object:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MovieRecommender {
@@ -481,7 +504,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MovieRecommender {
@@ -9,7 +9,7 @@ configuration:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class MyConfiguration {
@@ -28,7 +28,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class MyConfiguration {
@@ -50,7 +50,7 @@ used as a qualifier, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Autowired
private Store<String> s1; // <String> qualifier, injects the stringStore bean
@@ -61,7 +61,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Autowired
private lateinit var s1: Store<String> // <String> qualifier, injects the stringStore bean
@@ -78,7 +78,7 @@ following example autowires a generic `List`:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
// Inject all Store beans as long as they have an <Integer> generic
// Store<String> beans will not appear in this list
@@ -88,7 +88,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
// Inject all Store beans as long as they have an <Integer> generic
// Store<String> beans will not appear in this list
@@ -17,7 +17,7 @@ cleared upon destruction:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class CachingMovieLister {
@@ -35,7 +35,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class CachingMovieLister {
@@ -15,7 +15,7 @@ as demonstrated in the following example:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class SimpleMovieLister {
@@ -31,7 +31,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class SimpleMovieLister {
@@ -54,7 +54,7 @@ named `movieFinder` injected into its setter method:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class SimpleMovieLister {
@@ -69,7 +69,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class SimpleMovieLister {
@@ -103,7 +103,7 @@ named "customerPreferenceDao" and then falls back to a primary type match for th
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MovieRecommender {
@@ -124,7 +124,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MovieRecommender {
@@ -7,7 +7,7 @@
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Component
public class MovieRecommender {
@@ -22,7 +22,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Component
class MovieRecommender(@Value("\${catalog.name}") private val catalog: String)
@@ -35,7 +35,7 @@ With the following configuration:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@PropertySource("classpath:application.properties")
@@ -44,7 +44,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
@PropertySource("classpath:application.properties")
@@ -71,7 +71,7 @@ example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class AppConfig {
@@ -85,7 +85,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class AppConfig {
@@ -117,7 +117,7 @@ It is possible to provide a default value as following:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Component
public class MovieRecommender {
@@ -132,7 +132,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Component
class MovieRecommender(@Value("\${catalog.name:defaultCatalog}") private val catalog: String)
@@ -148,7 +148,7 @@ provide conversion support for your own custom type, you can provide your own
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class AppConfig {
@@ -164,7 +164,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class AppConfig {
@@ -186,7 +186,7 @@ computed at runtime as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Component
public class MovieRecommender {
@@ -201,7 +201,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Component
class MovieRecommender(
@@ -215,7 +215,7 @@ SpEL also enables the use of more complex data structures:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Component
public class MovieRecommender {
@@ -231,7 +231,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Component
class MovieRecommender(
@@ -110,14 +110,14 @@ as the local file system, the Java `CLASSPATH`, and so on.
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val context = ClassPathXmlApplicationContext("services.xml", "daos.xml")
----
@@ -294,7 +294,7 @@ example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
// create and configure beans
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
@@ -308,7 +308,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
import org.springframework.beans.factory.getBean
@@ -331,14 +331,14 @@ The following example shows Groovy configuration:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy");
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val context = GenericGroovyApplicationContext("services.groovy", "daos.groovy")
----
@@ -352,7 +352,7 @@ example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
GenericApplicationContext context = new GenericApplicationContext();
new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml");
@@ -361,7 +361,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val context = GenericApplicationContext()
XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml")
@@ -376,7 +376,7 @@ example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
GenericApplicationContext context = new GenericApplicationContext();
new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy");
@@ -385,7 +385,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val context = GenericApplicationContext()
GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy")
@@ -90,7 +90,7 @@ you need to programmatically call `addBeanPostProcessor`, as the following examp
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// populate the factory with bean definitions
@@ -104,7 +104,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val factory = DefaultListableBeanFactory()
// populate the factory with bean definitions
@@ -124,7 +124,7 @@ you need to call its `postProcessBeanFactory` method, as the following example s
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
@@ -140,7 +140,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val factory = DefaultListableBeanFactory()
val reader = XmlBeanDefinitionReader(factory)
@@ -59,7 +59,7 @@ is meta-annotated with `@Component`, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@@ -74,7 +74,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.RUNTIME)
@@ -103,7 +103,7 @@ customization of the `proxyMode`. The following listing shows the definition of
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@@ -123,7 +123,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Target(AnnotationTarget.TYPE, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
@@ -142,7 +142,7 @@ You can then use `@SessionScope` without declaring the `proxyMode` as follows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Service
@SessionScope
@@ -153,7 +153,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Service
@SessionScope
@@ -169,7 +169,7 @@ You can also override the value for the `proxyMode`, as the following example sh
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Service
@SessionScope(proxyMode = ScopedProxyMode.INTERFACES)
@@ -180,7 +180,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Service
@SessionScope(proxyMode = ScopedProxyMode.INTERFACES)
@@ -207,7 +207,7 @@ are eligible for such autodetection:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Service
public class SimpleMovieLister {
@@ -222,7 +222,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Service
class SimpleMovieLister(private val movieFinder: MovieFinder)
@@ -233,7 +233,7 @@ Kotlin::
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Repository
public class JpaMovieFinder implements MovieFinder {
@@ -243,7 +243,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Repository
class JpaMovieFinder : MovieFinder {
@@ -262,7 +262,7 @@ comma- or semicolon- or space-separated list that includes the parent package of
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@ComponentScan(basePackages = "org.example")
@@ -273,7 +273,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
@ComponentScan(basePackages = ["org.example"])
@@ -317,8 +317,8 @@ exposed based on security policies in some environments -- for example, standalo
JDK 1.7.0_45 and higher (which requires 'Trusted-Library' setup in your manifests -- see
{stackoverflow-questions}/19394570/java-jre-7u45-breaks-classloader-getresources).
On JDK 9's module path (Jigsaw), Spring's classpath scanning generally works as expected.
However, make sure that your component classes are exported in your `module-info`
On the module path (Java Module System), Spring's classpath scanning generally works as
expected. However, make sure that your component classes are exported in your `module-info`
descriptors. If you expect Spring to invoke non-public members of your classes, make
sure that they are 'opened' (that is, that they use an `opens` declaration instead of an
`exports` declaration in your `module-info` descriptor).
@@ -380,7 +380,7 @@ and using "`stub`" repositories instead:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@ComponentScan(basePackages = "org.example",
@@ -393,7 +393,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
@ComponentScan(basePackages = ["org.example"],
@@ -438,7 +438,7 @@ annotated classes. The following example shows how to do so:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Component
public class FactoryMethodComponent {
@@ -457,7 +457,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Component
class FactoryMethodComponent {
@@ -493,7 +493,7 @@ support for autowiring of `@Bean` methods. The following example shows how to do
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Component
public class FactoryMethodComponent {
@@ -532,7 +532,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Component
class FactoryMethodComponent {
@@ -585,7 +585,7 @@ The following example shows how to use `InjectionPoint`:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Component
public class FactoryMethodComponent {
@@ -599,7 +599,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Component
class FactoryMethodComponent {
@@ -699,7 +699,7 @@ following component classes were detected, the names would be `myMovieLister` an
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Service("myMovieLister")
public class SimpleMovieLister {
@@ -709,7 +709,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Service("myMovieLister")
class SimpleMovieLister {
@@ -722,7 +722,7 @@ Kotlin::
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Repository
public class MovieFinderImpl implements MovieFinder {
@@ -732,7 +732,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Repository
class MovieFinderImpl : MovieFinder {
@@ -751,7 +751,7 @@ and bean definition show.
TIP: If you run into naming conflicts due to multiple autodetected components having the
same non-qualified class name (i.e., classes with identical names but residing in
different packages), you may need to configure a `BeanNameGenerator` that defaults to the
fully qualified class name for the generated bean name. As of Spring Framework 5.2.3, the
fully qualified class name for the generated bean name. The
`FullyQualifiedAnnotationBeanNameGenerator` located in package
`org.springframework.context.annotation` can be used for such purposes.
@@ -759,7 +759,7 @@ fully qualified class name for the generated bean name. As of Spring Framework 5
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@ComponentScan(basePackages = "org.example", nameGenerator = MyNameGenerator.class)
@@ -770,7 +770,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
@ComponentScan(basePackages = ["org.example"], nameGenerator = MyNameGenerator::class)
@@ -806,7 +806,7 @@ scope within the annotation, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Scope("prototype")
@Repository
@@ -817,7 +817,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Scope("prototype")
@Repository
@@ -849,7 +849,7 @@ an annotation and a bean definition shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@ComponentScan(basePackages = "org.example", scopeResolver = MyScopeResolver.class)
@@ -860,7 +860,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
@ComponentScan(basePackages = ["org.example"], scopeResolver = MyScopeResolver::class)
@@ -887,7 +887,7 @@ the following configuration results in standard JDK dynamic proxies:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@ComponentScan(basePackages = "org.example", scopedProxy = ScopedProxyMode.INTERFACES)
@@ -898,7 +898,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
@ComponentScan(basePackages = ["org.example"], scopedProxy = ScopedProxyMode.INTERFACES)
@@ -920,7 +920,8 @@ Kotlin::
[[beans-scanning-qualifiers]]
== Providing Qualifier Metadata with Annotations
The `@Qualifier` annotation is discussed in xref:core/beans/annotation-config/autowired-qualifiers.adoc[Fine-tuning Annotation-based Autowiring with Qualifiers].
The `@Qualifier` annotation is discussed in
xref:core/beans/annotation-config/autowired-qualifiers.adoc[Fine-tuning Annotation-based Autowiring with Qualifiers].
The examples in that section demonstrate the use of the `@Qualifier` annotation and
custom qualifier annotations to provide fine-grained control when you resolve autowire
candidates. Because those examples were based on XML bean definitions, the qualifier
@@ -934,7 +935,7 @@ technique:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Component
@Qualifier("Action")
@@ -945,7 +946,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Component
@Qualifier("Action")
@@ -957,7 +958,7 @@ Kotlin::
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Component
@Genre("Action")
@@ -968,7 +969,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Component
@Genre("Action")
@@ -982,7 +983,7 @@ Kotlin::
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Component
@Offline
@@ -993,7 +994,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Component
@Offline
@@ -1,7 +1,7 @@
[[context-introduction]]
= Additional Capabilities of the `ApplicationContext`
As discussed in the xref:web/webmvc-view/mvc-xslt.adoc#mvc-view-xslt-beandefs[chapter introduction], the `org.springframework.beans.factory`
As discussed in the xref:core/beans/introduction.adoc[chapter introduction], the `org.springframework.beans.factory`
package provides basic functionality for managing and manipulating beans, including in a
programmatic way. The `org.springframework.context` package adds the
{spring-framework-api}/context/ApplicationContext.html[`ApplicationContext`]
@@ -102,7 +102,7 @@ implementations and so can be cast to the `MessageSource` interface.
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public static void main(String[] args) {
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
@@ -113,7 +113,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
fun main() {
val resources = ClassPathXmlApplicationContext("beans.xml")
@@ -161,7 +161,7 @@ converted into `String` objects and inserted into placeholders in the lookup mes
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class Example {
@@ -181,7 +181,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class Example {
@@ -224,7 +224,7 @@ argument.required=Ebagum lad, the ''{0}'' argument is required, I say, required.
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public static void main(final String[] args) {
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
@@ -236,7 +236,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
fun main() {
val resources = ClassPathXmlApplicationContext("beans.xml")
@@ -344,7 +344,7 @@ simple class that extends Spring's `ApplicationEvent` base class:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class BlockedListEvent extends ApplicationEvent {
@@ -363,7 +363,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class BlockedListEvent(source: Any,
val address: String,
@@ -380,7 +380,7 @@ example shows such a class:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class EmailService implements ApplicationEventPublisherAware {
@@ -407,7 +407,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class EmailService : ApplicationEventPublisherAware {
@@ -447,7 +447,7 @@ shows such a class:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class BlockedListNotifier implements ApplicationListener<BlockedListEvent> {
@@ -465,7 +465,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class BlockedListNotifier : ApplicationListener<BlockedListEvent> {
@@ -484,7 +484,7 @@ You can register as many event listeners as you wish, but note that, by default,
This means that the `publishEvent()` method blocks until all listeners have finished processing the event.
One advantage of this synchronous and single-threaded approach is that, when a listener receives an event,
it operates inside the transaction context of the publisher if a transaction context is available.
If another strategy for event publication becomes necessary, e.g. asynchronous event processing by default,
If another strategy for event publication becomes necessary, for example, asynchronous event processing by default,
see the javadoc for Spring's {spring-framework-api}/context/event/ApplicationEventMulticaster.html[`ApplicationEventMulticaster`] interface
and {spring-framework-api}/context/event/SimpleApplicationEventMulticaster.html[`SimpleApplicationEventMulticaster`] implementation
for configuration options which can be applied to a custom "applicationEventMulticaster" bean definition.
@@ -545,7 +545,7 @@ You can register an event listener on any method of a managed bean by using the
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class BlockedListNotifier {
@@ -564,7 +564,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class BlockedListNotifier {
@@ -591,7 +591,7 @@ following example shows how to do so:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@EventListener({ContextStartedEvent.class, ContextRefreshedEvent.class})
public void handleContextStart() {
@@ -601,7 +601,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@EventListener(ContextStartedEvent::class, ContextRefreshedEvent::class)
fun handleContextStart() {
@@ -621,7 +621,7 @@ The following example shows how our notifier can be rewritten to be invoked only
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@EventListener(condition = "#blEvent.content == 'my-event'")
public void processBlockedListEvent(BlockedListEvent blEvent) {
@@ -631,7 +631,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@EventListener(condition = "#blEvent.content == 'my-event'")
fun processBlockedListEvent(blEvent: BlockedListEvent) {
@@ -644,7 +644,7 @@ Each `SpEL` expression evaluates against a dedicated context. The following tabl
items made available to the context so that you can use them for conditional event processing:
[[context-functionality-events-annotation-tbl]]
.Event SpEL available metadata
.Event metadata available in SpEL expressions
|===
| Name| Location| Description| Example
@@ -660,8 +660,8 @@ items made available to the context so that you can use them for conditional eve
| __Argument name__
| evaluation context
| The name of any of the method arguments. If, for some reason, the names are not available
(for example, because there is no debug information in the compiled byte code), individual
| The name of a particular method argument. If the names are not available
(for example, because the code was compiled without the `-parameters` flag), individual
arguments are also available using the `#a<#arg>` syntax where `<#arg>` stands for the
argument index (starting from 0).
| `#blEvent` or `#a0` (you can also use `#p0` or `#p<#arg>` parameter notation as an alias)
@@ -677,7 +677,7 @@ method signature to return the event that should be published, as the following
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@EventListener
public ListUpdateEvent handleBlockedListEvent(BlockedListEvent event) {
@@ -688,7 +688,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@EventListener
fun handleBlockedListEvent(event: BlockedListEvent): ListUpdateEvent {
@@ -717,7 +717,7 @@ The following example shows how to do so:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@EventListener
@Async
@@ -728,7 +728,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@EventListener
@Async
@@ -763,7 +763,7 @@ annotation to the method declaration, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@EventListener
@Order(42)
@@ -774,7 +774,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@EventListener
@Order(42)
@@ -797,7 +797,7 @@ can create the following listener definition to receive only `EntityCreatedEvent
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@EventListener
public void onPersonCreated(EntityCreatedEvent<Person> event) {
@@ -807,7 +807,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@EventListener
fun onPersonCreated(event: EntityCreatedEvent<Person>) {
@@ -829,7 +829,7 @@ environment provides. The following event shows how to do so:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class EntityCreatedEvent<T> extends ApplicationEvent implements ResolvableTypeProvider {
@@ -846,7 +846,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class EntityCreatedEvent<T>(entity: T) : ApplicationEvent(entity), ResolvableTypeProvider {
@@ -864,7 +864,7 @@ Finally, as with classic `ApplicationListener` implementations, the actual multi
happens via a context-wide `ApplicationEventMulticaster` at runtime. By default, this is a
`SimpleApplicationEventMulticaster` with synchronous event publication in the caller thread.
This can be replaced/customized through an "applicationEventMulticaster" bean definition,
e.g. for processing all events asynchronously and/or for handling listener exceptions:
for example, for processing all events asynchronously and/or for handling listener exceptions:
[source,java,indent=0,subs="verbatim,quotes"]
----
@@ -935,7 +935,7 @@ Here is an example of instrumentation in the `AnnotationConfigApplicationContext
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
// create a startup step and start recording
StartupStep scanPackages = getApplicationStartup().start("spring.context.base-packages.scan");
@@ -949,7 +949,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
// create a startup step and start recording
val scanPackages = getApplicationStartup().start("spring.context.base-packages.scan")
@@ -11,7 +11,7 @@ To enable load-time weaving, you can add the `@EnableLoadTimeWeaving` to one of
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@EnableLoadTimeWeaving
@@ -21,7 +21,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
@EnableLoadTimeWeaving
@@ -73,23 +73,37 @@ runtime (concurrently with live access to the factory) is not officially support
lead to concurrent access exceptions, inconsistent state in the bean container, or both.
====
[[beans-definition-overriding]]
== Overriding Beans
Bean overriding is happening when a bean is registered using an identifier that is
already allocated. While bean overriding is possible, it makes the configuration harder
to read and this feature will be deprecated in a future release.
Bean overriding occurs when a bean is registered using an identifier that is already
allocated. While bean overriding is possible, it makes the configuration harder to read.
WARNING: Bean overriding will be deprecated in a future release.
To disable bean overriding altogether, you can set the `allowBeanDefinitionOverriding`
to `false` on the `ApplicationContext` before it is refreshed. In such setup, an
flag to `false` on the `ApplicationContext` before it is refreshed. In such a setup, an
exception is thrown if bean overriding is used.
By default, the container logs every bean overriding at `INFO` level so that you can
adapt your configuration accordingly. While not recommended, you can silence those logs
by setting the `allowBeanDefinitionOverriding` flag to `true`.
By default, the container logs every attempt to override a bean at `INFO` level so that
you can adapt your configuration accordingly. While not recommended, you can silence
those logs by setting the `allowBeanDefinitionOverriding` flag to `true`.
.Java Configuration
****
If you use Java Configuration, a corresponding `@Bean` method always silently overrides
a scanned bean class with the same component name as long as the return type of the
`@Bean` method matches that bean class. This simply means that the container will call
the `@Bean` factory method in favor of any pre-declared constructor on the bean class.
****
NOTE: We acknowledge that overriding beans in test scenarios is convenient, and there is
explicit support for this as of Spring Framework 6.2. Please refer to
xref:testing/testcontext-framework/bean-overriding.adoc[this section] for more details.
NOTE: We acknowledge that overriding beans in a test is convenient, and there is
explicit support for this. For more details please refer to xref:testing/testcontext-framework/bean-overriding.adoc[this section].
[[beans-beanname]]
== Naming Beans
@@ -284,7 +298,7 @@ The following example shows a class that would work with the preceding bean defi
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class ClientService {
private static ClientService clientService = new ClientService();
@@ -298,7 +312,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class ClientService private constructor() {
companion object {
@@ -364,7 +378,7 @@ The following example shows the corresponding class:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class DefaultServiceLocator {
@@ -378,7 +392,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class DefaultServiceLocator {
companion object {
@@ -414,7 +428,7 @@ The following example shows the corresponding class:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class DefaultServiceLocator {
@@ -434,7 +448,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class DefaultServiceLocator {
companion object {
@@ -60,6 +60,7 @@ instance's values consist of all bean instances that match the expected type, an
`Map` instance's keys contain the corresponding bean names.
[[beans-autowired-exceptions]]
== Limitations and Disadvantages of Autowiring
@@ -101,10 +102,10 @@ In the latter scenario, you have several options:
== Excluding a Bean from Autowiring
On a per-bean basis, you can exclude a bean from autowiring. In Spring's XML format, set
the `autowire-candidate` attribute of the `<bean/>` element to `false`. The container
makes that specific bean definition unavailable to the autowiring infrastructure
(including annotation style configurations such as xref:core/beans/annotation-config/autowired.adoc[`@Autowired`]
).
the `autowire-candidate` attribute of the `<bean/>` element to `false`; with the `@Bean`
annotation, the attribute is named `autowireCandidate`. The container makes that specific
bean definition unavailable to the autowiring infrastructure, including annotation-based
injection points such as xref:core/beans/annotation-config/autowired.adoc[`@Autowired`].
NOTE: The `autowire-candidate` attribute is designed to only affect type-based autowiring.
It does not affect explicit references by name, which get resolved even if the
@@ -119,9 +120,25 @@ provide multiple patterns, define them in a comma-separated list. An explicit va
`true` or `false` for a bean definition's `autowire-candidate` attribute always takes
precedence. For such beans, the pattern matching rules do not apply.
These techniques are useful for beans that you never want to be injected into other
beans by autowiring. It does not mean that an excluded bean cannot itself be configured by
These techniques are useful for beans that you never want to be injected into other beans
by autowiring. It does not mean that an excluded bean cannot itself be configured by
using autowiring. Rather, the bean itself is not a candidate for autowiring other beans.
[NOTE]
====
As of 6.2, `@Bean` methods support two variants of the autowire candidate flag:
`autowireCandidate` and `defaultCandidate`.
When using xref:core/beans/annotation-config/autowired-qualifiers.adoc[qualifiers],
a bean marked with `defaultCandidate=false` is only available for injection points
where an additional qualifier indication is present. This is useful for restricted
delegates that are supposed to be injectable in certain areas but are not meant to
get in the way of beans of the same type in other places. Such a bean will never
get injected by plain declared type only, rather by type plus specific qualifier.
In contrast, `autowireCandidate=false` behaves exactly like the `autowire-candidate`
attribute as explained above: Such a bean will never get injected by type at all.
====
@@ -34,7 +34,7 @@ injection:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class SimpleMovieLister {
@@ -52,7 +52,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
// a constructor so that the Spring container can inject a MovieFinder
class SimpleMovieLister(private val movieFinder: MovieFinder) {
@@ -77,7 +77,7 @@ being instantiated. Consider the following class:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package x.y;
@@ -91,7 +91,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package x.y
@@ -127,7 +127,7 @@ by type without help. Consider the following class:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package examples;
@@ -148,7 +148,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package examples
@@ -159,10 +159,12 @@ Kotlin::
----
======
.[[beans-factory-ctor-arguments-type]]Constructor argument type matching
--
[discrete]
[[beans-factory-ctor-arguments-type]]
==== Constructor argument type matching
In the preceding scenario, the container can use type matching with simple types if
you explicitly specify the type of the constructor argument by using the `type` attribute,
you explicitly specify the type of the constructor argument via the `type` attribute,
as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
@@ -172,10 +174,11 @@ as the following example shows:
<constructor-arg type="java.lang.String" value="42"/>
</bean>
----
--
.[[beans-factory-ctor-arguments-index]]Constructor argument index
--
[discrete]
[[beans-factory-ctor-arguments-index]]
==== Constructor argument index
You can use the `index` attribute to specify explicitly the index of constructor arguments,
as the following example shows:
@@ -191,10 +194,11 @@ In addition to resolving the ambiguity of multiple simple values, specifying an
resolves ambiguity where a constructor has two arguments of the same type.
NOTE: The index is 0-based.
--
.[[beans-factory-ctor-arguments-name]]Constructor argument name
--
[discrete]
[[beans-factory-ctor-arguments-name]]
==== Constructor argument name
You can also use the constructor parameter name for value disambiguation, as the following
example shows:
@@ -207,8 +211,8 @@ example shows:
----
Keep in mind that, to make this work out of the box, your code must be compiled with the
debug flag enabled so that Spring can look up the parameter name from the constructor.
If you cannot or do not want to compile your code with the debug flag, you can use the
`-parameters` flag enabled so that Spring can look up the parameter name from the constructor.
If you cannot or do not want to compile your code with the `-parameters` flag, you can use the
https://download.oracle.com/javase/8/docs/api/java/beans/ConstructorProperties.html[@ConstructorProperties]
JDK annotation to explicitly name your constructor arguments. The sample class would
then have to look as follows:
@@ -217,7 +221,7 @@ then have to look as follows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package examples;
@@ -235,7 +239,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package examples
@@ -244,7 +248,6 @@ Kotlin::
constructor(val years: Int, val ultimateAnswer: String)
----
======
--
[[beans-setter-injection]]
@@ -262,7 +265,7 @@ on container specific interfaces, base classes, or annotations.
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class SimpleMovieLister {
@@ -280,7 +283,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class SimpleMovieLister {
@@ -437,7 +440,7 @@ The following example shows the corresponding `ExampleBean` class:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class ExampleBean {
@@ -463,7 +466,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class ExampleBean {
lateinit var beanOne: AnotherBean
@@ -500,7 +503,7 @@ The following example shows the corresponding `ExampleBean` class:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class ExampleBean {
@@ -521,7 +524,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class ExampleBean(
private val beanOne: AnotherBean,
@@ -554,7 +557,7 @@ The following example shows the corresponding `ExampleBean` class:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class ExampleBean {
@@ -578,7 +581,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class ExampleBean private constructor() {
companion object {
@@ -2,13 +2,15 @@
= Using `depends-on`
If a bean is a dependency of another bean, that usually means that one bean is set as a
property of another. Typically you accomplish this with the <<beans-ref-element, `<ref/>`
element>> in XML-based configuration metadata. However, sometimes dependencies between
beans are less direct. An example is when a static initializer in a class needs to be
triggered, such as for database driver registration. The `depends-on` attribute can
explicitly force one or more beans to be initialized before the bean using this element
is initialized. The following example uses the `depends-on` attribute to express a
dependency on a single bean:
property of another. Typically you accomplish this with the
xref:core/beans/dependencies/factory-properties-detailed.adoc#beans-ref-element[`<ref/>` element>]
in XML-based metadata or through xref:core/beans/dependencies/factory-autowire.adoc[autowiring].
However, sometimes dependencies between beans are less direct. An example is when a static
initializer in a class needs to be triggered, such as for database driver registration.
The `depends-on` attribute or `@DependsOn` annotation can explicitly force one or more beans
to be initialized before the bean using this element is initialized. The following example
uses the `depends-on` attribute to express a dependency on a single bean:
[source,xml,indent=0,subs="verbatim,quotes"]
----
@@ -31,10 +33,10 @@ delimiters):
----
NOTE: The `depends-on` attribute can specify both an initialization-time dependency and,
in the case of xref:core/beans/factory-scopes.adoc#beans-factory-scopes-singleton[singleton] beans only, a corresponding
destruction-time dependency. Dependent beans that define a `depends-on` relationship
with a given bean are destroyed first, prior to the given bean itself being destroyed.
Thus, `depends-on` can also control shutdown order.
in the case of xref:core/beans/factory-scopes.adoc#beans-factory-scopes-singleton[singleton]
beans only, a corresponding destruction-time dependency. Dependent beans that define a
`depends-on` relationship with a given bean are destroyed first, prior to the given bean
itself being destroyed. Thus, `depends-on` can also control shutdown order.
@@ -21,7 +21,7 @@ shows this approach:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages",fold="none"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages",fold="none"]
----
package fiona.apple;
@@ -60,7 +60,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages",fold="none"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages",fold="none"]
----
package fiona.apple
@@ -137,7 +137,7 @@ the reworked example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages",fold="none"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages",fold="none"]
----
package fiona.apple;
@@ -160,7 +160,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages",fold="none"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages",fold="none"]
----
package fiona.apple
@@ -201,7 +201,7 @@ the original class. Consider the following example:
<!-- inject dependencies here as required -->
</bean>
<!-- commandProcessor uses statefulCommandHelper -->
<!-- commandManager uses myCommand prototype bean -->
<bean id="commandManager" class="fiona.apple.CommandManager">
<lookup-method name="createCommand" bean="myCommand"/>
</bean>
@@ -220,7 +220,7 @@ method through the `@Lookup` annotation, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public abstract class CommandManager {
@@ -237,7 +237,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
abstract class CommandManager {
@@ -260,7 +260,7 @@ declared return type of the lookup method:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public abstract class CommandManager {
@@ -277,7 +277,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
abstract class CommandManager {
@@ -324,7 +324,7 @@ the following class, which has a method called `computeValue` that we want to ov
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class MyValueCalculator {
@@ -338,7 +338,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class MyValueCalculator {
@@ -358,7 +358,7 @@ interface provides the new method definition, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
/**
* meant to be used to override the existing computeValue(String)
@@ -377,7 +377,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
/**
* meant to be used to override the existing computeValue(String)
@@ -354,7 +354,7 @@ The following Java class and bean definition show how to do so:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class SomeClass {
@@ -368,7 +368,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class SomeClass {
lateinit var accounts: Map<String, Float>
@@ -418,14 +418,14 @@ The preceding example is equivalent to the following Java code:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
exampleBean.setEmail("");
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
exampleBean.email = ""
----
@@ -449,14 +449,14 @@ The preceding configuration is equivalent to the following Java code:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
exampleBean.setEmail(null);
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
exampleBean.email = null
----
@@ -582,7 +582,7 @@ it needs to be declared in the XML file even though it is not defined in an XSD
(it exists inside the Spring core).
For the rare cases where the constructor argument names are not available (usually if
the bytecode was compiled without debugging information), you can use fallback to the
the bytecode was compiled without the `-parameters` flag), you can fall back to the
argument indexes, as follows:
[source,xml,indent=0,subs="verbatim,quotes"]
@@ -43,7 +43,7 @@ Consider the first use case in a practical application that requires a
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Bean
public DataSource dataSource() {
@@ -57,7 +57,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Bean
fun dataSource(): DataSource {
@@ -79,7 +79,7 @@ now looks like the following listing:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Bean(destroyMethod = "")
public DataSource dataSource() throws Exception {
@@ -90,7 +90,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Bean(destroyMethod = "")
fun dataSource(): DataSource {
@@ -128,7 +128,7 @@ can rewrite the `dataSource` configuration as follows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@Profile("development")
@@ -147,7 +147,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
@Profile("development")
@@ -171,7 +171,7 @@ Kotlin::
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@Profile("production")
@@ -188,7 +188,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
@Profile("production")
@@ -233,7 +233,7 @@ of creating a custom composed annotation. The following example defines a custom
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@@ -244,7 +244,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@@ -272,7 +272,7 @@ the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class AppConfig {
@@ -300,7 +300,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class AppConfig {
@@ -454,7 +454,7 @@ it programmatically against the `Environment` API which is available through an
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("development");
@@ -464,7 +464,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val ctx = AnnotationConfigApplicationContext().apply {
environment.setActiveProfiles("development")
@@ -491,14 +491,14 @@ activates multiple profiles:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
ctx.getEnvironment().setActiveProfiles("profile1", "profile2");
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
ctx.getEnvironment().setActiveProfiles("profile1", "profile2")
----
@@ -523,7 +523,7 @@ the following example:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@Profile("default")
@@ -541,7 +541,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
@Profile("default")
@@ -578,7 +578,7 @@ hierarchy of property sources. Consider the following listing:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
ApplicationContext ctx = new GenericApplicationContext();
Environment env = ctx.getEnvironment();
@@ -588,7 +588,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val ctx = GenericApplicationContext()
val env = ctx.environment
@@ -643,7 +643,7 @@ current `Environment`. The following example shows how to do so:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
ConfigurableApplicationContext ctx = new GenericApplicationContext();
MutablePropertySources sources = ctx.getEnvironment().getPropertySources();
@@ -652,7 +652,7 @@ sources.addFirst(new MyPropertySource());
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val ctx = GenericApplicationContext()
val sources = ctx.environment.propertySources
@@ -684,7 +684,7 @@ a call to `testBean.getName()` returns `myTestBean`:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@PropertySource("classpath:/com/myco/app.properties")
@@ -704,7 +704,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
@PropertySource("classpath:/com/myco/app.properties")
@@ -729,7 +729,7 @@ environment, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")
@@ -749,7 +749,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
@PropertySource("classpath:/com/\${my.placeholder:default/path}/app.properties")
@@ -123,7 +123,7 @@ The following listing shows the custom `BeanPostProcessor` implementation class
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package scripting;
@@ -145,7 +145,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
[source,kotlin,indent=0,subs="verbatim,quotes",chomp="-packages"]
----
package scripting
@@ -205,7 +205,7 @@ The following Java application runs the preceding code and configuration:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@@ -224,7 +224,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
import org.springframework.beans.factory.getBean
@@ -439,7 +439,7 @@ dataSource.url=jdbc:mysql:mydb
----
This example file can be used with a container definition that contains a bean called
`dataSource` that has `driver` and `url` properties.
`dataSource` that has `driverClassName` and `url` properties.
Compound property names are also supported, as long as every component of the path
except the final property being overridden is already non-null (presumably initialized
@@ -72,7 +72,7 @@ no-argument signature. With Java configuration, you can use the `initMethod` att
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class ExampleBean {
@@ -84,7 +84,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class ExampleBean {
@@ -107,7 +107,7 @@ The preceding example has almost exactly the same effect as the following exampl
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class AnotherExampleBean implements InitializingBean {
@@ -120,7 +120,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class AnotherExampleBean : InitializingBean {
@@ -144,7 +144,7 @@ based on the given configuration but no further activity with external bean acce
Otherwise there is a risk for an initialization deadlock.
For a scenario where expensive post-initialization activity is to be triggered,
e.g. asynchronous database preparation steps, your bean should either implement
for example, asynchronous database preparation steps, your bean should either implement
`SmartInitializingSingleton.afterSingletonsInstantiated()` or rely on the context
refresh event: implementing `ApplicationListener<ContextRefreshedEvent>` or
declaring its annotation equivalent `@EventListener(ContextRefreshedEvent.class)`.
@@ -187,7 +187,7 @@ xref:core/beans/java/bean-annotation.adoc#beans-java-lifecycle-callbacks[Receivi
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class ExampleBean {
@@ -199,7 +199,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class ExampleBean {
@@ -221,7 +221,7 @@ The preceding definition has almost exactly the same effect as the following def
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class AnotherExampleBean implements DisposableBean {
@@ -234,7 +234,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class AnotherExampleBean : DisposableBean {
@@ -295,7 +295,7 @@ following example:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class DefaultBlogService implements BlogService {
@@ -316,7 +316,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class DefaultBlogService : BlogService {
@@ -551,7 +551,7 @@ declared on the `ConfigurableApplicationContext` interface, as the following exa
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@@ -573,7 +573,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
import org.springframework.context.support.ClassPathXmlApplicationContext
@@ -607,7 +607,7 @@ bean creation phase and its subsequent initial publication, they need to be decl
`volatile` or guarded by a common lock whenever accessed.
Note that concurrent access to such configuration state in singleton bean instances,
e.g. for controller instances or repository instances, is perfectly thread-safe after
for example, for controller instances or repository instances, is perfectly thread-safe after
such safe initial publication from the container side. This includes common singleton
`FactoryBean` instances which are processed within the general singleton lock as well.
@@ -617,7 +617,7 @@ structures (or in `volatile` fields for simple cases) as per common Java guideli
Deeper `Lifecycle` integration as shown above involves runtime-mutable state such as
a `runnable` field which will have to be declared as `volatile`. While the common
lifecycle callbacks follow a certain order, e.g. a start callback is guaranteed to
lifecycle callbacks follow a certain order, for example, a start callback is guaranteed to
only happen after full initialization and a stop callback only after an initial start,
there is a special case with the common stop before destroy arrangement: It is strongly
recommended that the internal state in any such bean also allows for an immediate
@@ -251,7 +251,7 @@ to do so:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@RequestScope
@Component
@@ -262,7 +262,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@RequestScope
@Component
@@ -301,7 +301,7 @@ When using annotation-driven components or Java configuration, you can use the
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@SessionScope
@Component
@@ -312,7 +312,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@SessionScope
@Component
@@ -350,7 +350,7 @@ following example shows how to do so:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@ApplicationScope
@Component
@@ -361,7 +361,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@ApplicationScope
@Component
@@ -584,14 +584,14 @@ underlying scope:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
Object get(String name, ObjectFactory<?> objectFactory)
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
fun get(name: String, objectFactory: ObjectFactory<*>): Any
----
@@ -606,14 +606,14 @@ the underlying scope:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
Object remove(String name)
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
fun remove(name: String): Any
----
@@ -626,14 +626,14 @@ destroyed or when the specified object in the scope is destroyed:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
void registerDestructionCallback(String name, Runnable destructionCallback)
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
fun registerDestructionCallback(name: String, destructionCallback: Runnable)
----
@@ -648,14 +648,14 @@ The following method obtains the conversation identifier for the underlying scop
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
String getConversationId()
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
fun getConversationId(): String
----
@@ -677,14 +677,14 @@ method to register a new `Scope` with the Spring container:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
void registerScope(String scopeName, Scope scope);
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
fun registerScope(scopeName: String, scope: Scope)
----
@@ -710,7 +710,7 @@ implementations.
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
Scope threadScope = new SimpleThreadScope();
beanFactory.registerScope("thread", threadScope);
@@ -718,7 +718,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
val threadScope = SimpleThreadScope()
beanFactory.registerScope("thread", threadScope)
@@ -19,7 +19,7 @@ The simplest possible `@Configuration` class reads as follows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class AppConfig {
@@ -33,7 +33,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class AppConfig {
@@ -25,7 +25,7 @@ the method name. The following example shows a `@Bean` method declaration:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class AppConfig {
@@ -39,7 +39,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class AppConfig {
@@ -75,7 +75,7 @@ configurations by implementing interfaces with bean definitions on default metho
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public interface BaseConfig {
@@ -99,7 +99,7 @@ return type, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class AppConfig {
@@ -113,7 +113,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class AppConfig {
@@ -153,7 +153,7 @@ parameter, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class AppConfig {
@@ -167,7 +167,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class AppConfig {
@@ -211,7 +211,7 @@ on the `bean` element, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public class BeanOne {
@@ -244,7 +244,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
class BeanOne {
@@ -291,7 +291,7 @@ The following example shows how to prevent an automatic destruction callback for
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Bean(destroyMethod = "")
public DataSource dataSource() throws NamingException {
@@ -301,7 +301,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Bean(destroyMethod = "")
fun dataSource(): DataSource {
@@ -326,7 +326,7 @@ following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class AppConfig {
@@ -344,7 +344,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class AppConfig {
@@ -382,7 +382,7 @@ as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class MyConfiguration {
@@ -397,7 +397,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class MyConfiguration {
@@ -431,7 +431,7 @@ it resembles the following:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
// an HTTP Session-scoped bean exposed as a proxy
@Bean
@@ -451,7 +451,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
// an HTTP Session-scoped bean exposed as a proxy
@Bean
@@ -479,7 +479,7 @@ as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class AppConfig {
@@ -493,7 +493,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class AppConfig {
@@ -517,7 +517,7 @@ The following example shows how to set a number of aliases for a bean:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class AppConfig {
@@ -531,7 +531,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class AppConfig {
@@ -559,7 +559,7 @@ annotation, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class AppConfig {
@@ -574,7 +574,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class AppConfig {
@@ -16,7 +16,7 @@ another configuration class, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class ConfigA {
@@ -40,7 +40,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class ConfigA {
@@ -67,7 +67,7 @@ following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
@@ -80,7 +80,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
import org.springframework.beans.factory.getBean
@@ -116,14 +116,14 @@ the configuration model, in that references to other beans must be valid Java sy
Fortunately, solving this problem is simple. As
xref:core/beans/java/bean-annotation.adoc#beans-java-dependencies[we already discussed],
a `@Bean` method can have an arbitrary number of parameters that describe the bean
dependencies. Consider the following more real-world scenario with several `@Configuration`
dependencies. Consider the following more realistic scenario with several `@Configuration`
classes, each depending on beans declared in the others:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class ServiceConfig {
@@ -163,7 +163,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
import org.springframework.beans.factory.getBean
@@ -219,7 +219,7 @@ parameter-based injection, as in the preceding example.
Avoid access to locally defined beans within a `@PostConstruct` method on the same configuration
class. This effectively leads to a circular reference since non-static `@Bean` methods semantically
require a fully initialized configuration class instance to be called on. With circular references
disallowed (e.g. in Spring Boot 2.6+), this may trigger a `BeanCurrentlyInCreationException`.
disallowed (for example, in Spring Boot 2.6+), this may trigger a `BeanCurrentlyInCreationException`.
Also, be particularly careful with `BeanPostProcessor` and `BeanFactoryPostProcessor` definitions
through `@Bean`. Those should usually be declared as `static @Bean` methods, not triggering the
@@ -234,7 +234,7 @@ The following example shows how one bean can be autowired to another bean:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class ServiceConfig {
@@ -283,7 +283,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
import org.springframework.beans.factory.getBean
@@ -331,8 +331,10 @@ TIP: Constructor injection in `@Configuration` classes is only supported as of S
Framework 4.3. Note also that there is no need to specify `@Autowired` if the target
bean defines only one constructor.
.[[beans-java-injecting-imported-beans-fq]]Fully-qualifying imported beans for ease of navigation
--
[discrete]
[[beans-java-injecting-imported-beans-fq]]
==== Fully-qualifying imported beans for ease of navigation
In the preceding scenario, using `@Autowired` works well and provides the desired
modularity, but determining exactly where the autowired bean definitions are declared is
still somewhat ambiguous. For example, as a developer looking at `ServiceConfig`, how do
@@ -351,7 +353,7 @@ configuration classes themselves. The following example shows how to do so:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class ServiceConfig {
@@ -369,7 +371,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class ServiceConfig {
@@ -395,7 +397,7 @@ abstract class-based `@Configuration` classes. Consider the following example:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class ServiceConfig {
@@ -445,7 +447,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
import org.springframework.beans.factory.getBean
@@ -501,7 +503,6 @@ Now `ServiceConfig` is loosely coupled with respect to the concrete
get a type hierarchy of `RepositoryConfig` implementations. In this
way, navigating `@Configuration` classes and their dependencies becomes no different
than the usual process of navigating interface-based code.
--
[[beans-java-startup]]
@@ -569,7 +570,7 @@ method that returns `true` or `false`. For example, the following listing shows
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
@@ -577,7 +578,7 @@ Java::
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
for (Object value : attrs.get("value")) {
if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
if (context.getEnvironment().matchesProfiles((String[]) value)) {
return true;
}
}
@@ -589,14 +590,14 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
override fun matches(context: ConditionContext, metadata: AnnotatedTypeMetadata): Boolean {
// Read the @Profile annotation attributes
val attrs = metadata.getAllAnnotationAttributes(Profile::class.java.name)
if (attrs != null) {
for (value in attrs["value"]!!) {
if (context.environment.acceptsProfiles(Profiles.of(*value as Array<String>))) {
if (context.environment.matchesProfiles(*value as Array<String>)) {
return true
}
}
@@ -631,22 +632,24 @@ that uses Spring XML, it is easier to create `@Configuration` classes on an
as-needed basis and include them from the existing XML files. Later in this section, we cover the
options for using `@Configuration` classes in this kind of "`XML-centric`" situation.
.[[beans-java-combining-xml-centric-declare-as-bean]]Declaring `@Configuration` classes as plain Spring `<bean/>` elements
--
Remember that `@Configuration` classes are ultimately bean definitions in the
container. In this series examples, we create a `@Configuration` class named `AppConfig` and
[discrete]
[[beans-java-combining-xml-centric-declare-as-bean]]
==== Declaring `@Configuration` classes as plain Spring `<bean/>` elements
Remember that `@Configuration` classes are ultimately bean definitions in the container.
In this series of examples, we create a `@Configuration` class named `AppConfig` and
include it within `system-test-config.xml` as a `<bean/>` definition. Because
`<context:annotation-config/>` is switched on, the container recognizes the
`@Configuration` annotation and processes the `@Bean` methods declared in `AppConfig`
properly.
The following example shows an ordinary configuration class in Java:
The following example shows the `AppConfig` configuration class in Java and Kotlin:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class AppConfig {
@@ -661,14 +664,14 @@ Java::
@Bean
public TransferService transferService() {
return new TransferService(accountRepository());
return new TransferServiceImpl(accountRepository());
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class AppConfig {
@@ -694,6 +697,7 @@ The following example shows part of a sample `system-test-config.xml` file:
<beans>
<!-- enable processing of annotations such as @Autowired and @Configuration -->
<context:annotation-config/>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
<bean class="com.acme.AppConfig"/>
@@ -719,7 +723,7 @@ jdbc.password=
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml");
@@ -730,7 +734,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
fun main() {
val ctx = ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml")
@@ -740,20 +744,20 @@ Kotlin::
----
======
NOTE: In `system-test-config.xml` file, the `AppConfig` `<bean/>` does not declare an `id`
element. While it would be acceptable to do so, it is unnecessary, given that no other bean
NOTE: In the `system-test-config.xml` file, the `AppConfig` `<bean/>` does not declare an `id`
attribute. While it would be acceptable to do so, it is unnecessary, given that no other bean
ever refers to it, and it is unlikely to be explicitly fetched from the container by name.
Similarly, the `DataSource` bean is only ever autowired by type, so an explicit bean `id`
is not strictly required.
--
.[[beans-java-combining-xml-centric-component-scan]] Using <context:component-scan/> to pick up `@Configuration` classes
--
[discrete]
[[beans-java-combining-xml-centric-component-scan]]
==== Using <context:component-scan/> to pick up `@Configuration` classes
Because `@Configuration` is meta-annotated with `@Component`, `@Configuration`-annotated
classes are automatically candidates for component scanning. Using the same scenario as
described in the previous example, we can redefine `system-test-config.xml` to take advantage of component-scanning.
Note that, in this case, we need not explicitly declare
described in the previous example, we can redefine `system-test-config.xml` to take
advantage of component-scanning. Note that, in this case, we need not explicitly declare
`<context:annotation-config/>`, because `<context:component-scan/>` enables the same
functionality.
@@ -764,6 +768,7 @@ The following example shows the modified `system-test-config.xml` file:
<beans>
<!-- picks up and registers AppConfig as a bean definition -->
<context:component-scan base-package="com.acme"/>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
@@ -773,25 +778,23 @@ The following example shows the modified `system-test-config.xml` file:
</bean>
</beans>
----
--
[[beans-java-combining-java-centric]]
=== `@Configuration` Class-centric Use of XML with `@ImportResource`
In applications where `@Configuration` classes are the primary mechanism for configuring
the container, it is still likely necessary to use at least some XML. In these
scenarios, you can use `@ImportResource` and define only as much XML as you need. Doing
so achieves a "`Java-centric`" approach to configuring the container and keeps XML to a
bare minimum. The following example (which includes a configuration class, an XML file
that defines a bean, a properties file, and the `main` class) shows how to use
the `@ImportResource` annotation to achieve "`Java-centric`" configuration that uses XML
as needed:
the container, it may still be necessary to use at least some XML. In such scenarios, you
can use `@ImportResource` and define only as much XML as you need. Doing so achieves a
"`Java-centric`" approach to configuring the container and keeps XML to a bare minimum.
The following example (which includes a configuration class, an XML file that defines a
bean, a properties file, and the `main()` method) shows how to use the `@ImportResource`
annotation to achieve "`Java-centric`" configuration that uses XML as needed:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@ImportResource("classpath:/com/acme/properties-config.xml")
@@ -810,12 +813,23 @@ Java::
public DataSource dataSource() {
return new DriverManagerDataSource(url, username, password);
}
@Bean
public AccountRepository accountRepository(DataSource dataSource) {
return new JdbcAccountRepository(dataSource);
}
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
@ImportResource("classpath:/com/acme/properties-config.xml")
@@ -834,21 +848,32 @@ Kotlin::
fun dataSource(): DataSource {
return DriverManagerDataSource(url, username, password)
}
@Bean
fun accountRepository(dataSource: DataSource): AccountRepository {
return JdbcAccountRepository(dataSource)
}
@Bean
fun transferService(accountRepository: AccountRepository): TransferService {
return TransferServiceImpl(accountRepository)
}
}
----
======
.properties-config.xml
[source,xml,indent=0,subs="verbatim,quotes"]
----
properties-config.xml
<beans>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
</beans>
----
.jdbc.properties
[literal,subs="verbatim,quotes"]
----
jdbc.properties
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
jdbc.username=sa
jdbc.password=
@@ -858,7 +883,7 @@ jdbc.password=
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
@@ -869,7 +894,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
import org.springframework.beans.factory.getBean
@@ -881,5 +906,3 @@ Kotlin::
----
======
@@ -17,7 +17,7 @@ as having one bean method call another, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class AppConfig {
@@ -36,7 +36,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class AppConfig {
@@ -72,7 +72,7 @@ following example shows how to use lookup method injection:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public abstract class CommandManager {
public Object process(Object commandState) {
@@ -90,7 +90,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
abstract class CommandManager {
fun process(commandState: Any): Any {
@@ -115,7 +115,7 @@ the abstract `createCommand()` method is overridden in such a way that it looks
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Bean
@Scope("prototype")
@@ -139,7 +139,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Bean
@Scope("prototype")
@@ -172,7 +172,7 @@ Consider the following example, which shows a `@Bean` annotated method being cal
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
public class AppConfig {
@@ -200,7 +200,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
class AppConfig {
@@ -27,7 +27,7 @@ XML-free usage of the Spring container, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
@@ -38,7 +38,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
import org.springframework.beans.factory.getBean
@@ -58,7 +58,7 @@ as input to the constructor, as the following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
@@ -69,7 +69,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
import org.springframework.beans.factory.getBean
@@ -97,7 +97,7 @@ example shows how to do so:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
@@ -111,7 +111,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
import org.springframework.beans.factory.getBean
@@ -136,7 +136,7 @@ To enable component scanning, you can annotate your `@Configuration` class as fo
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@ComponentScan(basePackages = "com.acme") // <1>
@@ -148,7 +148,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Configuration
@ComponentScan(basePackages = ["com.acme"]) // <1>
@@ -183,7 +183,7 @@ following example shows:
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
[source,java,indent=0,subs="verbatim,quotes"]
----
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
@@ -195,7 +195,7 @@ Java::
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
fun main() {
val ctx = AnnotationConfigApplicationContext()

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