Compare commits

...

1455 Commits

Author SHA1 Message Date
Spring Builds e6585e0250 Release v6.1.0 2023-11-16 14:21:14 +00:00
rstoyanchev af1b3c72d5 Merge branch '6.0.x' 2023-11-16 11:15:44 +00:00
Juergen Hoeller d1867f1b73 Merge branch '6.0.x' 2023-11-16 11:35:12 +01:00
Juergen Hoeller 99378fe947 Polishing 2023-11-16 11:22:09 +01:00
Juergen Hoeller b0e29acd23 Upgrade to SmallRye Mutiny 1.10.0 2023-11-16 11:22:01 +01:00
Brian Clozel c02f735056 Merge branch '6.0.x' 2023-11-16 09:04:09 +01:00
Stéphane Nicoll c485e9b74f Merge branch '6.0.x' 2023-11-15 20:50:02 +01:00
rstoyanchev 3a70c71c5e Merge branch '6.0.x' 2023-11-15 18:57:35 +00:00
Stéphane Nicoll f15b8b95ad Merge branch '6.0.x' 2023-11-15 19:04:11 +01:00
Sébastien Deleuze 183c2f82b2 Refine @EmbeddableInstantiator reflection hints
Based on @odrotbohm proposal to manage a wider set
of use cases.

Closes gh-31534
2023-11-15 18:48:27 +01:00
Brian Clozel 8eebb5e27b Polish
See gh-31575
2023-11-15 15:26:49 +01:00
Arjen Poutsma 0ef3cb9b9e Merge branch '6.0.x' 2023-11-15 14:33:55 +01:00
Juergen Hoeller ca9634143c Upgrade to Reactor 2023.0.0
Includes Protobuf 3.25.0, Artemis 2.31.2, Checkstyle 10.12.5

Closes gh-31557
2023-11-15 14:06:43 +01:00
Juergen Hoeller 0e6bf098cb Merge branch '6.0.x'
# Conflicts:
#	build.gradle
#	framework-platform/framework-platform.gradle
#	spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java
2023-11-15 13:36:03 +01:00
Juergen Hoeller 01fc1ee3bb Introduce update variant with KeyHolder and explicit key column names
Closes gh-31607
2023-11-15 12:20:22 +01:00
Stéphane Nicoll 510caad6c3 Merge branch '6.0.x' 2023-11-15 12:07:50 +01:00
Sébastien Deleuze 92c3843dae Add required AspectJ field hints
This commit adds reflection hints on fields for
classes compiled by AspectJ.

Closes gh-31575
2023-11-15 10:30:02 +01:00
rstoyanchev e12269ef1a Merge branch '6.0.x' 2023-11-14 20:01:14 +00:00
rstoyanchev 2613dfce0b Merge branch '6.0.x' 2023-11-14 19:24:43 +00:00
Sam Brannen 978e81e72e Merge branch '6.0.x' 2023-11-14 15:15:53 +01:00
Juergen Hoeller 2b7a9209b3 Merge branch '6.0.x' 2023-11-14 12:52:25 +01:00
Arjen Poutsma 8f21479234 Add body conversion capabilities in RestClient::exchange
This commit introduces a ConvertibleClientHttpResponse type that
extends ClientHttpResponse, and that can convert the body to a desired
type. Before this commit, it was not easy to use the configured HTTP
message converters in combination with RestClient::exchange.

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

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

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

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

See gh-28055
Closes gh-31587
2023-11-10 11:36:27 +01:00
Sam Brannen 8a7144ba42 Document how to log @⁠Sql scripts and statements
Closes gh-31589
2023-11-10 11:19:38 +01:00
Sam Brannen 6c3a3dc7d9 Polishing 2023-11-10 11:18:26 +01:00
Sam Brannen b1a7161218 Document @⁠Sql class-level execution phase support in the reference manual
Closes gh-31377
2023-11-09 15:22:14 +01:00
Sam Brannen 332de60586 Update @⁠Sql docs regarding Kotlin and Java 8 2023-11-09 15:19:52 +01:00
rstoyanchev 769128a0b2 Merge branch '6.0.x' 2023-11-09 12:53:36 +00:00
rstoyanchev d8441fc80c Invoke handleEmptyBody if there is no content-type
Closes gh-30522
2023-11-09 12:53:05 +00:00
Sébastien Deleuze d8ed7c7906 Merge branch '6.0.x' 2023-11-09 13:11:58 +01:00
Juergen Hoeller 8841b7c3bb Upgrade to SnakeYAML 2.2 2023-11-09 11:52:02 +01:00
Juergen Hoeller 6c00e6162b Merge branch '6.0.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
#	spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/GenericCallMetaDataProvider.java
2023-11-09 11:50:55 +01:00
Simon Baslé 42874178ce Polish RecordApplicationEvents javadoc: add note on captured threads
This commit clarifies that the annotation is used to capture events that
are fired from the test `Thread` or descendant threads, since the test
framework uses `InheritableThreadLocal` to store captured events now.

See gh-31079
See gh-30020
2023-11-09 11:07:53 +01:00
Juergen Hoeller 9414c2ddba Coordinated stop before destroy when ExecutorService not terminated yet
Closes gh-31549
2023-11-09 10:22:27 +01:00
Sébastien Deleuze 38724a1205 Fix RestClient generic type handling
For client side use case, the context class should be null,
consistently with what is done in HttpMessageConverterExtractor.

Closes gh-31574
2023-11-09 08:50:31 +01:00
Sam Brannen 55d13a0232 Document @⁠DisabledInAotMode & @[Enabled|Disabled]InNativeImage in ref docs
Closes gh-31437
Closes gh-31438
2023-11-08 16:22:35 +01:00
Sam Brannen a207e5e1b0 Ensure framework-docs can be imported into Eclipse IDE 2023-11-08 15:26:09 +01:00
Sam Brannen b7c579954c Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMapping.java
2023-11-08 13:48:22 +01:00
rstoyanchev ba4d459f81 Merge branch '6.0.x' 2023-11-08 11:47:18 +00:00
Stéphane Nicoll d34b3c1a71 Merge branch '6.0.x' 2023-11-08 08:04:27 +01:00
Sam Brannen 9759bf5964 Merge branch '6.0.x' 2023-11-07 17:13:46 +01:00
Arjen Poutsma 5afb00d270 Merge branch '6.0.x' 2023-11-07 15:10:59 +01:00
Arjen Poutsma 486503bd31 Buffer writes in JettyClientHttpRequest
This commit ensures that not every OutputStream.write gets written as a
separate chunk, by buffering the written data in a BufferedOutputStream.
In some cases, a large quantity of small writes would result in many
sent chunks.

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

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

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

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

Closes gh-31534
2023-11-07 11:04:43 +01:00
Stéphane Nicoll c30b3796f2 Merge branch '6.0.x' 2023-11-07 10:37:22 +01:00
wakingrufus 8c77e398b6 Add extension for PropertyResolver#getProperty(String, Class<T>, T)
Allows Kotlin caller to get a non-nullable property,
using a default value when the property is not set.
A method already exists on PropertyResolver which does this,
but takes a Class parameter.
The extension method can eliminate the parameter via reified type,
similar to the other extension methods which exist already.

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

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

Closes gh-31516
See gh-31449
2023-11-02 15:51:36 +01:00
Stéphane Nicoll ab316d9bc8 Merge branch '6.0.x' 2023-11-02 15:41:18 +01:00
Stéphane Nicoll 27b5813591 Merge pull request #31542 from Young-Zen
* pr/31542:
  Fix link in Javadoc of ConfigurableMockMvcBuilder

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

Closes gh-31536
2023-11-01 16:33:44 +01:00
Sam Brannen a5841fede5 Polishing 2023-11-01 16:23:18 +01:00
rstoyanchev 2a5653c7d6 Merge branch '6.0.x' 2023-11-01 13:26:34 +00:00
Stéphane Nicoll 115a46c5e8 Polish 2023-10-31 17:58:13 +01:00
Stéphane Nicoll 199d5e5f37 Polish 2023-10-31 13:02:01 +01:00
Sam Brannen 3d248607dc Update copyright headers 2023-10-30 15:21:02 +01:00
Sam Brannen 574c57739e Further polishing 2023-10-30 15:10:13 +01:00
Johnny Lim 2b750926c3 Polishing
Closes gh-31522
2023-10-30 15:05:20 +01:00
Sam Brannen 8a2acbeac1 Merge branch '6.0.x' 2023-10-30 13:32:08 +01:00
Sam Brannen 8770544769 Remove classpath entries for non-existent libraries added by mrjar plugin
The me.champeau.mrjar Gradle plugin causes non-existent libraries to be
added to the Eclipse classpath, such as:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

See gh-31208
2023-10-24 14:36:10 +02:00
rstoyanchev 2864c12887 Merge branch '6.0.x' 2023-10-24 12:58:31 +01:00
rstoyanchev 3f8bbdb116 Merge branch '6.0.x' 2023-10-24 12:53:55 +01:00
Stéphane Nicoll 999b5d4462 Better error reporting when instance does not match factory method
This commit improves the handling of IllegalArgumentException in
SimpleInstantiationStrategy. Previously, only arguments mismatch were
handled but the exception can also be thrown if the factory instance
does not match the target method.

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

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

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

Closes gh-31449
2023-10-24 12:11:13 +02:00
Sam Brannen 71330ddb0f Revise support for quoted identifiers in SimpleJdbcInsert
Closes gh-31208
2023-10-24 11:52:51 +02:00
Sam Brannen a803206d5f Polishing 2023-10-24 11:52:51 +02:00
rstoyanchev e57b942b4d MockMvcBuilder supports filter name in addition to initParams
Closes gh-31474
2023-10-24 10:33:58 +01:00
Stéphane Nicoll ef47eef92a Merge branch '6.0.x' 2023-10-24 10:57:09 +02:00
Juergen Hoeller 8712fdcd3b Polishing 2023-10-23 17:36:06 +02:00
Juergen Hoeller cf3a25bfac Merge branch '6.0.x' 2023-10-23 17:34:45 +02:00
Juergen Hoeller 8457c768e8 Polishing 2023-10-23 16:56:40 +02:00
Juergen Hoeller 6dc79b5105 Declare empty default postProcessBeanFactory method
Closes gh-31476
2023-10-23 16:56:05 +02:00
Arjen Poutsma cb4d44b83e JdkClientHttpRequest does not support Content-Length 0
This commit ensures the correct HttpRequest.BodyPublisher is used with
Content-Length 0.

Closes gh-31451
2023-10-23 12:25:10 +02:00
Stéphane Nicoll 3cb700c103 Merge branch '6.0.x' 2023-10-23 11:34:12 +02:00
Sam Brannen 2d792f000a Polish "Apply SingleSpaceSeparator Checkstyle module"
See gh-31469
2023-10-22 14:18:18 +02:00
Johnny Lim 64e9fcad53 Apply SingleSpaceSeparator Checkstyle module
This commit also fixes its violations.

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

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

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

See gh-29496
2023-10-20 16:35:21 +02:00
Brian Clozel 631a5d1dc1 Remove support for Protobuf 2.x and protobuf-java-format
Closes gh-31465
2023-10-20 15:05:02 +02:00
rstoyanchev 7271dfed68 Use CopyOnWriteArrayList for beforeCommit actions
Closes gh-27587
2023-10-20 13:21:09 +01:00
rstoyanchev a2f2f7c348 Use correct RequestParam resolver
Closes gh-31329
2023-10-20 12:39:50 +01:00
Sébastien Deleuze c1437f9817 Refine CRaC restoration logs
Closes gh-31462
2023-10-20 11:40:44 +02:00
Brian Clozel daaccce918 Merge branch '6.0.x' 2023-10-19 16:07:41 +02:00
Brian Clozel c73c16f07f Configure JDK 22 compatibility build on CI
This commit does not enable this build right now as testing libraries
are not ready yet for JDK 22.

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

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

Closes gh-28878
2023-10-18 10:42:28 +02:00
Stéphane Nicoll 46cc75b3f1 Merge branch '6.0.x' 2023-10-18 10:13:49 +02:00
rstoyanchev a53d3f3cea Apply DisconnectedClientHelper to @ExceptionHandler methods
Use the helper to reduce logging when an @ExceptionHandler fails
to write to the response due to a network failure where the client
has gone away.

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

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

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

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

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

Current AOT test results for the spring-test module:

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

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

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

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

Current AOT test results for the spring-test module:

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

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

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

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

Current results for the spring-test module:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

See gh-31417
2023-10-13 15:04:03 +02:00
Brian Clozel 579f29857f Merge branch '6.0.x' 2023-10-13 15:03:56 +02:00
rstoyanchev b5b9386be6 Polishing
Closes gh-31413
2023-10-13 11:47:47 +01:00
Olga MaciaszekSharma 0cd196e3dd Add UriBuilderFactoryArgumentResolver
See gh-31413
2023-10-13 11:47:47 +01:00
Sam Brannen 364186e699 Polishing 2023-10-12 17:52:55 +02:00
Sam Brannen 047c2c1c20 Do not swallow failures in tests 2023-10-12 17:51:26 +02:00
Sam Brannen a4fe57a9e2 Restore imports for deprecated types in tests 2023-10-12 17:35:01 +02:00
Stéphane Nicoll 1e7fc6035d Merge branch '6.0.x' 2023-10-12 16:19:49 +02:00
Stephane Nicoll 37c2619fc4 Add AOT support for TypedStringValue
This commit adds support for TypeStringValue when generating AOT code.
If the value does not specify an explicit type, it's specified as is.
Otherwise, the TypeStringValue instance is restored via the appropriate
code generation.

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

Closes gh-31419
2023-10-12 13:55:33 +02:00
Brian Clozel aab538d1f0 Merge branch '6.0.x' 2023-10-12 11:58:10 +02:00
Brian Clozel bb23032a78 Merge branch '6.0.x' 2023-10-11 19:16:41 +02:00
rstoyanchev 776e28a6c4 MockMvc supports filter initParams and DispatcherType's
Closes gh-27717, gh-31362
2023-10-11 17:09:18 +01:00
rstoyanchev 0542fe5232 Update ClientHttpRequestInterceptor javadoc
Clarify the interceptor is responsible for closing the response
if it throws an exception after receiving it.

Closes gh-29751
2023-10-11 17:09:18 +01:00
Juergen Hoeller c7b832cfc8 Enforce REQUIRES_NEW for correct transaction configuration
Closes gh-31414
2023-10-11 17:14:32 +02:00
Juergen Hoeller 2cdc114273 Merge branch '6.0.x' 2023-10-11 16:11:34 +02:00
Sam Brannen 25778e2f0e Clean up warnings in tests 2023-10-11 13:32:48 +02:00
Sam Brannen 00dde8bd88 Polishing 2023-10-11 13:32:47 +02:00
Juergen Hoeller 653a631df5 Merge branch '6.0.x'
# Conflicts:
#	spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java
2023-10-11 13:28:11 +02:00
rstoyanchev 3277b0d6ac Handle STOMP messages to user destination in order
Closes gh-31395
2023-10-11 12:16:04 +01:00
Rossen Stoyanchev 9eb39e182e Polishing
See gh-21798
2023-10-11 12:16:04 +01:00
rstoyanchev a205eab618 Handle STOMP messages from client in order
See gh-21798
2023-10-11 12:16:04 +01:00
rstoyanchev 4195e6906c OrderedMessageChannelDecorator supports multiple subscribers
See gh-21798
2023-10-11 12:16:04 +01:00
rstoyanchev d62d7f5ff1 Polishing
See gh-21798
2023-10-11 12:16:04 +01:00
Juergen Hoeller e76b453685 Translate Hibernate TransactionException through SQLException cause
Closes gh-31274
2023-10-11 13:09:19 +02:00
OnlyWick eafbcfd385 Remove redundant static declaration on Search class
Closes gh-31381
2023-10-11 13:01:21 +02:00
Brian Clozel d1cf71cc70 Merge branch '6.0.x' 2023-10-11 11:24:00 +02:00
Arjen Poutsma c692d7e020 Merge branch '6.0.x' 2023-10-11 10:37:26 +02:00
Sébastien Deleuze bbaa35e69e Merge branch '6.0.x' 2023-10-11 10:13:12 +02:00
Stéphane Nicoll dc0d6a41d6 Polish 2023-10-11 09:00:40 +02:00
Stéphane Nicoll 93206c3f6e Add support for custom locale to render compiler messages
Closes gh-31408
2023-10-11 09:00:40 +02:00
Sébastien Deleuze ae88bbaac3 Reintroduce org.springframework.http.client.reactive.ReactorResourceFactory
This commit reintroduces a deprecated ReactorResourceFactory in
org.springframework.http.client.reactive package that extends
the one in org.springframework.http.client package to avoid an
API breaking change and to provide a smoother upgrade experience.

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

Closes gh-31406
2023-10-11 00:46:24 +02:00
Juergen Hoeller 38de3d5b57 Merge branch '6.0.x'
# Conflicts:
#	build.gradle
#	framework-platform/framework-platform.gradle
#	spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
2023-10-11 00:19:54 +02:00
Juergen Hoeller c0d98fcc7a Consistent Object result declarations for ResultQuerySpec
Closes gh-31403
2023-10-10 22:58:13 +02:00
Juergen Hoeller de6692e7d8 Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMapping.java
2023-10-10 21:58:31 +02:00
Juergen Hoeller d339bbbf91 Remove test for MessageSource access after context close
See gh-31397
2023-10-10 20:46:58 +02:00
Brian Clozel 8d6b499cf1 Polish
See gh-31398
2023-10-10 20:42:45 +02:00
Stéphane Nicoll da24c6b346 Merge branch '6.0.x' 2023-10-10 20:34:11 +02:00
Stéphane Nicoll 96b32580ec Handle deprecation warning in AOT-generated code
Closes gh-29597
2023-10-10 20:16:32 +02:00
Stéphane Nicoll ea66883d79 Detect use of deprecated API
This commit is a best effort attempt at identifying the members that
code generation invokes and might be deprecated. It introduces
a CodeWarnings helper class that records warnings, with special
handling for `@Deprecated`.

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

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

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

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

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

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

This commit registers the required reflection metadata.

Closes gh-31390
2023-10-09 20:03:06 +02:00
Brian Clozel 30a94b041f Upgrade CI image to Ubuntu jammy-20230916 2023-10-09 20:02:43 +02:00
Sébastien Deleuze 22a2847809 Merge branch '6.0.x' 2023-10-09 12:42:44 +02:00
Sam Brannen d1b43386b1 Test status quo for @⁠Sql in @⁠Nested test class w/ class-level execution phases 2023-10-08 18:16:31 +02:00
Johnny Lim 8ed302bfa4 Add @⁠since tags for DataBufferUtils.outputStreamPublisher() methods
See gh-31184
Closes gh-31376
2023-10-08 18:09:21 +02:00
Sam Brannen b98b999997 Test status quo for inherited @⁠Sql in @⁠Nested test class 2023-10-08 18:09:13 +02:00
Sam Brannen af4652db36 Merge branch '6.0.x' 2023-10-08 16:24:53 +02:00
Stéphane Nicoll ae731fbb78 Merge branch '6.0.x' 2023-10-05 16:57:04 +02:00
Arjen Poutsma 59d123a18e Introduce OutputStream BodyInserter
This commit introduces a BodyInserter that inssert any bytes written to
an output stream to the body of an output message.

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

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

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

- Polish Javadoc and add missing @⁠since tags.

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

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

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

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

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

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

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

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

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

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

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

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

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

Closes gh-31327
2023-09-29 18:01:18 +01:00
rstoyanchev a6ab636614 Merge branch '6.0.x' 2023-09-29 18:00:52 +01:00
Sam Brannen 95838e18cc Clean up (boolean) (Boolean) casts in tests 2023-09-29 18:16:04 +02:00
Sam Brannen c3795731b5 Merge branch '6.0.x' 2023-09-29 17:48:15 +02:00
Sam Brannen cddff46165 Merge branch '6.0.x' 2023-09-29 16:53:01 +02:00
Juergen Hoeller a3e13c8ba8 Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/util/backoff/ExponentialBackOff.java
2023-09-29 15:01:43 +02:00
Sam Brannen 985eb5b8a1 Merge branch '6.0.x' 2023-09-29 13:52:44 +02:00
Stéphane Nicoll 9e144afc0d Merge pull request #31328 from vpavic
* pr/31328:
  Polish "Fix regression in JmsAccessor#setSessionAcknowledgeMode"
  Fix regression in JmsAccessor#setSessionAcknowledgeMode

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

See gh-31328
2023-09-29 08:42:38 +02:00
Stéphane Nicoll ce9ca700f3 Enable test in AbstractAspectJAdvisorFactoryTests
See gh-24190
2023-09-28 15:46:47 +02:00
Juergen Hoeller ef61b4eff3 SimpleAsyncTaskScheduler runs fixed-delay tasks on scheduler thread
Closes gh-31334
2023-09-28 14:34:01 +02:00
Juergen Hoeller 86b764d4d2 Expose public shouldHandle(ApplicationEvent) method
Closes gh-31295
2023-09-28 14:33:26 +02:00
Juergen Hoeller 38a0e17ede Prefer query(Class) method in javadoc example
See gh-26594
2023-09-28 14:33:20 +02:00
Stéphane Nicoll b9bbfb79a4 Merge branch '6.0.x' 2023-09-28 09:32:28 +02:00
Sam Brannen 515d8aae94 Merge branch '6.0.x' 2023-09-27 16:43:56 +02:00
Sam Brannen 47ed4e6c78 Merge branch '6.0.x' 2023-09-27 13:19:39 +02:00
Sam Brannen 45d8aadb0a Polishing 2023-09-27 10:19:51 +02:00
Stéphane Nicoll b5db730ca0 Merge pull request #31267 from kang-hl
* pr/31267:
  Update copyright year of changed file
  Optimize MessageSourceSupport

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

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

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

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

See gh-31282
2023-09-26 12:37:28 +02:00
rstoyanchev 2e2a62a23c Polishing 2023-09-26 11:34:40 +01:00
rstoyanchev af7fe013b6 MockMvcHttpConnector supports RequestPostProcessor's
Closes gh-31298
2023-09-26 11:34:40 +01:00
Stéphane Nicoll 0f6b018e97 Merge branch '6.0.x' 2023-09-26 12:30:05 +02:00
Sam Brannen 225c9062a1 Merge branch '6.0.x' 2023-09-25 20:19:11 +02:00
Sam Brannen 7aae97bcd4 Revise NO_VIOLATIONS_DETECTED in SpringExtension to clarify intent
See gh-31305
See gh-30962
See gh-30456
2023-09-25 16:48:58 +02:00
Stéphane Nicoll d36c4f75e3 Merge branch '6.0.x' 2023-09-25 15:27:20 +02:00
Stéphane Nicoll daa902bf20 Merge pull request #31305 from alidandach
* pr/31305:
  Use Objects.equals() for null-safe string comparison

Closes gh-31305
2023-09-25 08:33:05 +02:00
ali dandach 1d12c74042 Use Objects.equals() for null-safe string comparison
See gh-31305
2023-09-25 08:28:33 +02:00
Sam Brannen bc3d98565c Update copyright headers 2023-09-23 13:36:41 +02:00
Sam Brannen a88d5d1c62 Polishing 2023-09-23 13:36:30 +02:00
Sam Brannen d0a088f9dc Clean up warnings in tests 2023-09-23 13:30:05 +02:00
Sam Brannen ebd4f1b45b Merge branch '6.0.x' 2023-09-23 12:41:19 +02:00
Sam Brannen bc03088f69 Merge branch '6.0.x' 2023-09-22 18:18:11 +02:00
Sam Brannen 64b4a3cf0d Update KeyHolder in JdbcClient when using positional parameters
Prior to this commit, DefaultJdbcClient updated the supplied KeyHolder
when using named parameters but not for positional parameters.

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

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

This commit adds the missing hint on public methods.

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

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

Closes gh-30474
2023-09-22 09:44:12 +02:00
Brian Clozel 0aec9f12ce Upgrade to Gradle Enterprise 3.14 2023-09-22 09:43:44 +02:00
Brian Clozel d926769a5e Fix copyright headers
See gh-30137
2023-09-22 09:36:38 +02:00
Brian Clozel 1afb6f1861 Upgrade to Java 21 in CI image 2023-09-22 09:02:12 +02:00
rstoyanchev 6b35d43020 Polishing contribution
Closes gh-30113
2023-09-20 18:50:33 +01:00
Andreas Bergander 732f0a6a77 DefaultServletHttpRequestHandler supports DispatcherType.INCLUDE
See gh-30113
2023-09-20 18:50:32 +01:00
rstoyanchev cc296c5033 Polishing contribution
Closes gh-30137
2023-09-20 18:44:33 +01:00
Joakim Mohn a1c4fb3840 Lenient URI encoding handling in ForwardedHeaderTransformer
See gh-30137
2023-09-20 18:44:33 +01:00
rstoyanchev 0f7c406a86 Suppress handler mapping logging for introspector
Closes gh-30349
2023-09-20 18:44:33 +01:00
rstoyanchev 2530efd1c7 SseEmitter support for multiline String
Closes gh-30965
2023-09-20 18:44:33 +01:00
Sam Brannen 9350091163 Merge branch '6.0.x'
# Conflicts:
#	spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJPointcutAdvisor.java
#	spring-tx/src/test/java/org/springframework/transaction/annotation/AnnotationTransactionInterceptorTests.java
2023-09-20 17:06:35 +02:00
김희망 6caef9bb3c Refine ServerRequest.queryParamOrNull implementation
Closes gh-31264
2023-09-20 15:51:09 +02:00
Brian Clozel a97ff39088 Add reflection hint on Publisher for bean destroy support
Prior to this commit, `DisposableBeanAdapter` supported reactive bean
destroy methods by detected if `Publisher` is available on the
classpath. The AOT engine did not contribute a reflection hint for this
call.

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

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

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

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

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

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

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

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

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

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

Closes gh-31258
2023-09-19 15:12:53 +02:00
Stéphane Nicoll 05500373e2 Merge branch '6.0.x' 2023-09-18 17:02:26 +02:00
Sébastien Deleuze 4128f4d5c9 Print JVM restoration time in DefaultLifecycleProcessor
Closes gh-31252
2023-09-18 10:57:09 +02:00
Stéphane Nicoll 2fbcff8919 Prevent ValueLoaderEntryProcessor to be created for each get call
Closes gh-31250
2023-09-18 09:27:16 +02:00
Stéphane Nicoll f79bc7b14d Implement JCacheCache#putIfAbsent as atomic operation
This commit modifies putIfAbsent to use an EntryProcessor that
guarantees that the operation is atomic.

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

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

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

Closes gh-31244
2023-09-16 18:04:30 +02:00
Sam Brannen 293e6ddf85 Polishing 2023-09-16 15:25:16 +02:00
Sam Brannen b05e46d502 Update copyright headers 2023-09-16 15:23:10 +02:00
Sébastien Deleuze 20df52e543 Merge branch '6.0.x' 2023-09-15 18:16:26 +02:00
Brian Clozel 7ecbdc19a5 Merge branch '6.0.x' 2023-09-15 17:54:06 +02:00
Juergen Hoeller aa1360b154 Complete set of constructors with consistent javadoc
Closes gh-31234
2023-09-15 17:45:13 +02:00
Marten Deinum e42e89c04f Add constructors to take ObjectMapper
Prior to this commit in the message converters it was possible
to set a pre-configured ObjectMapper. However the constructor
would still create and configure an ObjectMapper.

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

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

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

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

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

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

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

Closes gh-26148
2023-09-13 19:59:50 +02:00
Sam Brannen 99a50e7cea Polishing 2023-09-13 19:52:17 +02:00
Sébastien Deleuze 68ba55bea9 Fix ModelInitializerKotlinTests
See gh-30894
2023-09-13 18:30:01 +02:00
Sébastien Deleuze bb85d9b5e4 Merge branch '6.0.x' 2023-09-13 18:07:59 +02:00
Sam Brannen a678be80ea Merge branch '6.0.x' 2023-09-13 17:51:02 +02:00
Juergen Hoeller 550f05c9dc Merge branch '6.0.x'
# Conflicts:
#	spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java
2023-09-13 17:28:54 +02:00
Sam Brannen 5bcbcb3049 Simplify SynthesizedMergedAnnotationInvocationHandler.invoke() 2023-09-13 17:14:03 +02:00
Sam Brannen fe7355d5b0 Polishing 2023-09-13 17:04:39 +02:00
Sam Brannen a271d5ec15 Use nullSafeHashCode() in SynthesizedMergedAnnotationInvocationHandler
In light of the refinements to ObjectUtils, this commit updates
SynthesizedMergedAnnotationInvocationHandler to use
ObjectUtils.nullSafeHashCode() and removes the now obsolete code in
SynthesizedMergedAnnotationInvocationHandler.

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

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

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

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

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

- Use instanceof pattern matching

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

- Add missing @⁠since tags

- Polish Javadoc

- Rename isNegativeNumber() to isNegativeNumberLiteral()

- Restructure InlineCollectionTests using @⁠Nested, etc.

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

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

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

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

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

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

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

Closes gh-31205
2023-09-11 21:17:14 +02:00
Sébastien Deleuze dfd631e662 Merge branch '6.0.x' 2023-09-11 18:10:13 +02:00
Juergen Hoeller 3099710087 Merge branch '6.0.x'
# Conflicts:
#	spring-r2dbc/src/main/java/org/springframework/r2dbc/connection/R2dbcTransactionManager.java
#	spring-r2dbc/src/test/java/org/springframework/r2dbc/connection/R2dbcTransactionManagerUnitTests.java
2023-09-11 17:40:11 +02:00
Sam Brannen a199654a62 Use MergedAnnotations API in AnnotationBeanNameGenerator where feasible
AnnotationBeanNameGenerator was written before the introduction of the
MergedAnnotations API and therefore heavily relies on the
AnnotationMetadata abstraction and various helper methods for ASM
compatibility.

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

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

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

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

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

See gh-31164

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Closes gh-31154
See gh-31104
2023-09-08 18:47:21 +02:00
Sébastien Deleuze 88ee8fc92f Upgrade to CRaC 1.4.0
Closes gh-31190
2023-09-08 17:53:08 +02:00
Sam Brannen 154aec7d75 Merge branch '6.0.x' 2023-09-08 17:22:16 +02:00
Sam Brannen a11b8039c5 Merge branch '6.0.x' 2023-09-08 16:31:11 +02:00
Sam Brannen f0b1133b12 Merge branch '6.0.x' 2023-09-08 16:12:29 +02:00
Stephane Nicoll 91f65e63b4 Merge pull request #30068 from enimiste
* pr/30068:
  Polish "Add return type check on GetterPointcut"
  Add return type check on GetterPointcut

Closes gh-30068
2023-09-08 15:37:07 +02:00
Stephane Nicoll 3e424e3ce7 Polish "Add return type check on GetterPointcut"
See gh-30068
2023-09-08 15:30:52 +02:00
Enimiste d1dfac4e5d Add return type check on GetterPointcut
See gh-30068
2023-09-08 15:20:53 +02:00
Sam Brannen c9e13575ca Use switch expression and constants in CallMetaDataProviderFactory 2023-09-08 14:05:03 +02:00
Sam Brannen 762d903aad Convert TableMetaData to a record
This simplifies the code and also improves diagnostics while debugging.
2023-09-08 14:04:47 +02:00
Sam Brannen 47d760845b Add missing @Nullable declaration 2023-09-08 14:00:52 +02:00
Sam Brannen ab5d46411a Introduce identifierNameToUse() in GenericCallMetaDataProvider 2023-09-08 13:59:46 +02:00
Sam Brannen 4df3eb4670 Polish Javadoc 2023-09-08 13:59:10 +02:00
Sam Brannen 5a87f555f8 Update copyright headers 2023-09-08 13:57:41 +02:00
Sébastien Deleuze 5fd356e44f Remove outdated @Suppress("DEPRECATION") annotations
See gh-31127
2023-09-08 13:18:16 +02:00
Sébastien Deleuze 6f38e90048 Merge branch '6.0.x' 2023-09-08 13:08:14 +02:00
rstoyanchev b0d4931d5d Merge branch '6.0.x' 2023-09-08 10:07:35 +01:00
Sébastien Deleuze 4c621826bd Merge branch '6.0.x' 2023-09-08 10:51:36 +02:00
rstoyanchev e0c4347cc6 Merge branch '6.0.x' 2023-09-08 09:18:24 +01:00
rstoyanchev 53133d949d Polishing contribution
Closes gh-29509
2023-09-08 08:28:26 +01:00
tianshuang a1ce5dac0b Execute preflight checks before interceptor chain
See gh-29509
2023-09-08 08:28:26 +01:00
Sébastien Deleuze da7ad71b7f Refine ReactorResourceFactory Javadoc
Provides more details about stop/restart
scenario.

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

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

See gh-31113
Closes gh-31121
2023-09-07 19:00:26 +02:00
Brian Clozel bc6954255b Merge branch '6.0.x' 2023-09-07 17:28:08 +02:00
Sam Brannen c3a0022c9e Polish DefaultClientResponseTests and suppress "unchecked" warnings 2023-09-07 17:09:31 +02:00
Brian Clozel b02e1bb935 Update CI pipeline for api docs publication
See gh-31049
2023-09-07 17:00:20 +02:00
Sam Brannen ac3a466607 Merge branch '6.0.x' 2023-09-07 16:50:50 +02:00
rstoyanchev fefbeeeb18 Merge branch '6.0.x' 2023-09-07 15:27:56 +01:00
Brian Clozel 244c069ea8 Polish
See gh-31173
2023-09-07 16:07:52 +02:00
Brian Clozel 3686c457bb Polish Aggregate Javadoc task
Closes gh-31173
2023-09-07 15:29:25 +02:00
Arjen Poutsma 7b5effecf3 Reference documentation for RestClient
In addition to providing reference documentation for the `RestClient`,
this commit also shortens the `RestTemplate` section.

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

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

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

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

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

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

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

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

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

- quoting schema and table names separately

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

- introducing integration tests against an in-memory H2 database

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

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

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

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

Closes gh-31160
2023-09-03 16:59:58 +02:00
Sam Brannen 7882d265c6 Polishing 2023-09-03 16:59:58 +02:00
Juergen Hoeller 759e3d4aa6 Adapt to PreparedStatementCreator for JdbcClient update operation
See gh-31122
2023-09-03 02:32:01 +02:00
Juergen Hoeller 9b50e7ded6 Merge branch '6.0.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
2023-09-03 01:27:18 +02:00
Juergen Hoeller 855fe39b7f Use PreparedStatementCreator for query/update with indexed params
Closes gh-31122
2023-09-03 00:44:11 +02:00
Juergen Hoeller 7595465c21 Lazily obtain Validator from original Supplier
Closes gh-31137
2023-09-03 00:42:52 +02:00
Juergen Hoeller d6e167d16e Raise log level to warn when enhancement cannot apply
Closes gh-31102
2023-09-03 00:42:38 +02:00
Sam Brannen 23a0903b5c Add missing comma and polishing 2023-09-02 19:34:20 +02:00
Sam Brannen a96aeb69c1 Merge branch '6.0.x' 2023-09-02 19:08:36 +02:00
Sébastien Deleuze 03650e7d58 Merge branch '6.0.x' 2023-09-01 12:52:59 +02:00
Sébastien Deleuze 0aa4dc11f1 Add missing graal-sdk dependency to spring-orm
See gh-29549
2023-09-01 12:47:47 +02:00
Sébastien Deleuze 81607238ce Use consistently @since 6.1 2023-09-01 12:33:21 +02:00
Sébastien Deleuze 63a20be502 Optimize Hibernate native footprint by making ByteBuddy unreachable
As a workaround before a proper solution the Spring team is trying to
find with the Hibernate team in a future version of Hibernate, this
commit introduces 2 GraalVM substitutions that should allow to remove
ByteBuddy reachability with Hibernate 6.3.

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

Closes gh-31150
2023-09-01 10:29:47 +02:00
Sam Brannen 093d6a1bec Merge branch '6.0.x' 2023-08-31 13:40:31 +02:00
Anton-Vasilev 1ee18e74fc Fix typo in RestClient Javadoc
Closes gh-31145
2023-08-31 09:43:06 +02:00
Brian Clozel 0d7c9b7c93 Attempt to reset Servlet response in DispatcherServlet
This is a follow-up change related to gh-31104.
This change reverts the changes previously made in
`ExceptionHandlerExceptionResolver` and instead attempts to reset the
response directly in `DispatcherServlet` in order to cover all types or
exception handling.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

See gh-31089
Closes gh-21108
2023-08-27 18:06:08 +02:00
Stephane Nicoll e239753a1b Merge branch '6.0.x' 2023-08-27 18:03:59 +02:00
Sam Brannen ff104b6de0 Look up @Component stereotype names using @AliasFor semantics
Although gh-20615 introduced the use of @AliasFor for @Component(value) in the built-in
stereotype annotations (@Service, @Controller, @Repository, @Configuration, and
@RestController), prior to this commit the framework did not actually rely on @AliasFor
support when looking up a component name via stereotype annotations. Rather, the
framework had custom annotation parsing logic in
AnnotationBeanNameGenerator#determineBeanNameFromAnnotation() which effectively ignored
explicit annotation attribute overrides configured via @AliasFor.

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

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

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

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

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

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

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

Closes gh-27154
2023-08-26 17:09:39 +02:00
Stephane Nicoll f9cffcce05 Polish "Avoid calling executeBatch() with an empty batch"
See gh-27154
2023-08-26 17:05:39 +02:00
Li0n13 2d7bf83d8d Avoid calling executeBatch() with an empty batch
See gh-27154
2023-08-26 17:05:20 +02:00
Stephane Nicoll a6b0c75cae Merge branch '6.0.x' 2023-08-26 16:41:21 +02:00
Sam Brannen e0c3b1ae1d Merge branch '6.0.x' 2023-08-26 15:28:50 +02:00
Sam Brannen dac481da43 Test CollectionUtils.unmodifiableMultiValueMap only once
No need to test that feature as a parameterized test.
2023-08-26 14:56:17 +02:00
Sam Brannen 31a07e6fbf User AssertJ assertions 2023-08-26 14:56:16 +02:00
Sam Brannen ef01a078d3 Polishing 2023-08-26 14:55:15 +02:00
Sam Brannen 44167ecea4 Polish BackOff support 2023-08-26 14:44:46 +02:00
Stephane Nicoll 962f4d20b4 Merge pull request #27071 from garyrussell
* pr/27071:
  Polish "Add maxAttempts to ExponentialBackOff"
  Add maxAttempts to ExponentialBackOff

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

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

See gh-27071
2023-08-26 12:45:32 +02:00
Stephane Nicoll 48878619d2 Merge branch '6.0.x' 2023-08-26 10:18:04 +02:00
Stephane Nicoll 16cb296b35 Merge pull request #27335 from marschall
* pr/27335:
  Optimize for single TransactionSynchronization

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

See gh-27335
2023-08-26 09:52:17 +02:00
Sam Brannen e737e6d9ba Update copyright headers 2023-08-25 17:07:17 +02:00
Sam Brannen 78d8fac05b Polishing 2023-08-25 17:06:57 +02:00
Sam Brannen 3efbbc5994 Merge branch '6.0.x' 2023-08-25 16:56:52 +02:00
Brian Clozel fe2ef2ea6e Upgrade Java versions in CI build 2023-08-25 16:25:24 +02:00
Brian Clozel 35fc2df948 Instrument RestClient for Observability
This commit instruments the new `RestClient` HTTP client for
observability. Since this client is sharing its HTTP infrastructure with
`RestTemplate` and operates on the same request/response types, this
instrumentation reuses the Observation convention and context.
This choice makes sense since one can build a new `RestClient` instance
using a `RestTemplate` instance, effectively reusing the underlying
configuration.

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

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

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

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

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

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

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

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

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

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

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

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

See gh-24311
2023-08-23 18:53:32 +02:00
Stephane Nicoll 471e4d2b20 Merge pull request #24311 from valfirst
* pr/24311:
  Polish "Add support for converting String to Pattern"
  Add support for converting String to Pattern

Closes gh-24311
2023-08-23 18:13:54 +02:00
Stephane Nicoll a20a74817e Polish "Add support for converting String to Pattern"
See gh-24311
2023-08-23 18:13:41 +02:00
Valery Yatsynovich 06f6b45248 Add support for converting String to Pattern
See gh-24311
2023-08-23 18:13:41 +02:00
Sébastien Deleuze bb14dfa747 Merge branch '6.0.x' 2023-08-23 18:11:14 +02:00
Stephane Nicoll 8695fadbc0 Merge pull request #23692 from ttddyy
* pr/23692:
  Polish "Add a composite for TaskDecorator"
  Add a composite for TaskDecorator

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

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

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

See gh-30709
2023-08-22 18:51:39 +02:00
Stephane Nicoll d529eee889 Merge branch '6.0.x' 2023-08-22 17:02:00 +02:00
Stephane Nicoll 26485b0e7d Merge branch '6.0.x' 2023-08-22 16:57:37 +02:00
Stephane Nicoll 18813de69f Merge pull request #1822 from x-x-z
* pr/1822:
  Polish "Add Basic Authorization for UrlResource"
  Add Basic Authorization for UrlResource

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

Closes gh-31076
2023-08-22 15:55:53 +02:00
Stephane Nicoll 2b76c4d847 Polish "Wrap ternary operator within parentheses"
See gh-31076
2023-08-22 15:40:16 +02:00
70825 6712c044b1 Wrap ternary operator within parentheses
See gh-31076
2023-08-22 15:15:05 +02:00
Sam Brannen a55b50b512 Simplify implementation of AnnotationMetadata.getMetaAnnotationTypes()
Since an annotation cannot be extended in Java, there is no need to use
the INHERITED_ANNOTATIONS SearchStrategy to search for meta-annotations
on an annotation.
2023-08-22 14:58:19 +02:00
Sam Brannen 2935ff8f97 Fix Javadoc for AnnotationMetadata.getMetaAnnotationTypes() 2023-08-22 14:50:58 +02:00
Sam Brannen aedd909ef6 Test status quo for component name lookups for Jakarta annotations 2023-08-22 11:49:08 +02:00
Sam Brannen d8523cb033 Polishing 2023-08-22 11:49:08 +02:00
Sam Brannen 5e171d3cf5 Polish reference documentation for JdbcClient 2023-08-21 16:51:14 +02:00
Sam Brannen 5f893cadc5 Merge branch '6.0.x' 2023-08-21 16:03:52 +02:00
Toshiaki Maki 8f7d61650d Add @Nullable to value in param() methods in JdbcClient
Closes gh-31084
2023-08-21 15:50:38 +02:00
Juergen Hoeller c2bdc23b5e Merge branch '6.0.x' 2023-08-21 15:45:22 +02:00
Juergen Hoeller 26da0e49e4 Show example for CaffeineCacheManager async cache setup
See gh-28250
2023-08-21 15:39:02 +02:00
Sam Brannen 583d92e69a Merge branch '6.0.x' 2023-08-21 15:19:27 +02:00
Sam Brannen 758dddce3b Merge branch '6.0.x' 2023-08-21 14:18:38 +02:00
Juergen Hoeller 430cc2edc0 Merge branch '6.0.x' 2023-08-21 12:38:43 +02:00
Sam Brannen 1e3099759e Polishing 2023-08-20 19:32:07 +02:00
Harry Yang 0e0c298dcf Optimize InlineMap and InlineList in SpEL
- Make InlineList#constant and InlineMap#constant final.

- Add more assertions for InlineMap tests.

Closes gh-30251
2023-08-20 17:52:27 +02:00
Sam Brannen baf367831f Add @AliasFor tip to Javadoc for @TestPropertySource 2023-08-19 15:40:31 +02:00
Sam Brannen 8f71bea553 Avoid unnecessary synchronization in SequencedProperties 2023-08-19 15:32:37 +02:00
Sam Brannen 94d9a71bb5 Polishing 2023-08-19 15:21:55 +02:00
Sébastien Deleuze 11abd8b04f Merge branch '6.0.x' 2023-08-18 17:25:50 +02:00
Sam Brannen 74130d007b Ensure direct @PropertySource annotations override meta-annotations
Prior to this commit, there was an issue with the semantics of property
source overrides. Specifically, a @PropertySource annotation present as
a meta-annotation on a @Configuration class was registered with higher
precedence than a @PropertySource annotation declared closer to (or
directly on) the @Configuration class. Consequently, there was no way
for a "local" @PropertySource annotation to override properties
registered via @PropertySource as a meta-annotation.

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

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

Closes gh-31074
2023-08-18 16:43:44 +02:00
Sam Brannen 285c92bb03 Store reversedMetaDistance Comparator in static field 2023-08-18 16:33:51 +02:00
Sam Brannen ee6998ba52 Polishing 2023-08-18 16:21:50 +02:00
Stephane Nicoll 9583d18896 Merge branch '6.0.x' 2023-08-18 15:39:49 +02:00
Sébastien Deleuze 334b1548b7 Merge branch '6.0.x'
Adapt gh-31045 fix to the main branch, and throw a
WebExchangeBindException instead of a ServerWebInputException.
2023-08-18 15:11:16 +02:00
Sam Brannen 3dcac0cf80 Clean up / Suppress warnings 2023-08-18 12:46:17 +02:00
Sam Brannen ca118ca4a0 Introduce overloaded methods in JdbcTestUtils that accept JdbcClient
Closes gh-31066
2023-08-18 12:20:57 +02:00
Sam Brannen e0fb777325 Introduce var-args params() method in JdbcClient's StatementSpec
Closes gh-31070
2023-08-18 12:00:28 +02:00
Sam Brannen 48e94f535c Polish JdbcClient 2023-08-18 12:00:28 +02:00
Sam Brannen 77067d0e6b Revise JdbcTestUtils method signatures to accept JdbcOperations
Closes gh-31065
2023-08-18 12:00:28 +02:00
Juergen Hoeller 1a137c2e61 Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/util/StringUtils.java
2023-08-18 11:27:03 +02:00
Sam Brannen f43f1e12f1 Merge branch '6.0.x' 2023-08-17 17:59:30 +02:00
Arjen Poutsma 34477b4f03 Schedule FreeMarker template lookup on bounded elastic scheduler
This commit makes sure that FreeMarker template lookups, which
potentially block, are scheduled on the bounded elastic scheduler.

Closes gh-30903
2023-08-17 16:42:44 +02:00
Juergen Hoeller d41f546c43 Merge branch '6.0.x' 2023-08-17 10:24:34 +02:00
Juergen Hoeller e685ff0416 Always accept existing explicit definition for same class name
See gh-25952
2023-08-16 18:46:32 +02:00
Juergen Hoeller 4bfbf7d3c8 Merge branch '6.0.x' 2023-08-16 17:56:18 +02:00
Sam Brannen 279e6eb423 Document best practices for inlined properties in @TestPropertySource 2023-08-16 17:27:18 +02:00
Juergen Hoeller eb65939341 Add examples for new bind/map methods on DatabaseClient
See gh-27282
See gh-26021
2023-08-16 17:02:41 +02:00
Juergen Hoeller 3f79b267b1 Merge branch '6.0.x' 2023-08-16 16:55:01 +02:00
Sébastien Deleuze 5641d87ce8 Merge branch '6.0.x' 2023-08-16 16:06:55 +02:00
Sam Brannen 24dd484471 Polish internal SequencedProperties implementation 2023-08-16 14:11:02 +02:00
Sam Brannen b43972bb54 Preserve property ordering for text blocks in @TestPropertySource
See gh-31053
2023-08-16 13:48:25 +02:00
Brian Clozel 17109b2402 Upgrade to Reactor 2023.0.0-M2
Closes gh-31014
2023-08-16 13:02:05 +02:00
Brian Clozel dbfece6c31 Upgrade to Micrometer 1.12.0-M2
Closes gh-30997
2023-08-16 13:01:54 +02:00
Juergen Hoeller 86a101ac2b Merge branch '6.0.x' 2023-08-16 12:48:43 +02:00
Sam Brannen 1f544f113a Support resource patterns in @TestPropertySource locations
Inspired by the recently added support for resource patterns in
@PropertySource locations, this commit adds the same support for
resource locations in @TestPropertySource.

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

... the following:

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

... or:

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

... can now be replaced by:

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

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

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

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

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

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

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

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

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

Some tests have been added as well.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Closes gh-31042
2023-08-12 18:09:37 +02:00
Sam Brannen c52bfc0586 Update test names to reflect status quo
AnnotationMetadataReadingVisitor was replaced by
SimpleAnnotationMetadata in Spring Framework 5.2.
2023-08-12 18:09:37 +02:00
Sam Brannen a33b14338f Polishing annotation processing internals 2023-08-12 15:41:48 +02:00
Sam Brannen 2ede74fa9c Merge branch '6.0.x' 2023-08-12 15:14:26 +02:00
Juergen Hoeller 86ca6fee16 Merge branch '6.0.x' 2023-08-12 14:52:03 +02:00
Juergen Hoeller 9ede1d07a0 Revise multiple beans resolution for custom collection types
Closes gh-30022
2023-08-12 12:48:14 +02:00
Juergen Hoeller c65b0a199e Merge branch '6.0.x'
# Conflicts:
#	spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapter.java
2023-08-12 11:35:24 +02:00
Sébastien Deleuze 1e73439955 Support Kotlin value class properties in SpEL
This commit adds support for inlined Kotlin value
class properties in SpEL by leveraging Kotlin
reflection instead of Java reflection broken
by the mangled method name.

Closes gh-30468
2023-08-11 16:54:34 +02:00
Sébastien Deleuze 566621f7e3 Merge branch '6.0.x' 2023-08-10 19:13:19 +02:00
Juergen Hoeller f516431260 Merge branch '6.0.x' 2023-08-09 23:54:30 +02:00
Juergen Hoeller b4c61f20e7 Mention JdbcClient in package documentation
Closes gh-31017
2023-08-09 23:18:55 +02:00
Sébastien Deleuze 0c477f14cc Polishing
See gh-28638
2023-08-09 11:14:42 +02:00
Sébastien Deleuze c38f053905 Add Kotlin value classes tests with primitive types
This commit adds more Kotlin value classes tests with
primitive types to ensure testing unwrapped use case.

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

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

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

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

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

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

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

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

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

Closes gh-30982
2023-08-05 13:47:46 +03:00
Sam Brannen 59b78cc513 Polishing 2023-08-05 10:49:39 +03:00
Sam Brannen 14911fb32f Merge branch '6.0.x' 2023-08-05 10:28:32 +03:00
rstoyanchev 5115684baf Revise docs for server use of @HttpExchange
Closes gh-30980
2023-08-04 18:21:42 +03:00
rstoyanchev 6630b16771 Polishing
See gh-30980
2023-08-04 18:21:42 +03:00
Olga MaciaszekSharma d1d5b54f12 Support @HttpExchange for server-side handling
See gh-30980
2023-08-04 18:21:42 +03:00
Brian Clozel 646fd3edcc Avoid thread pinning in SseEmitter write operations
This commit changes the `synchronized` usage into a `ReentrantLock`, in
order to guard write operations with a construct that does not pin
virtual threads to the current platform thread on JDK21.

Closes gh-30996
2023-08-04 14:59:15 +02:00
Sam Brannen 9908967954 Merge branch '6.0.x' 2023-08-04 15:55:59 +03:00
Sam Brannen 5fd3456f1e Merge branch '6.0.x' 2023-08-04 15:42:25 +03:00
Sam Brannen 3758e5155c Merge branch '6.0.x' 2023-08-04 15:35:16 +03:00
Sam Brannen 376f13f8ef Update copyright headers 2023-08-04 15:02:41 +03:00
Sam Brannen 04cce0bafd Support custom properties file formats in @TestPropertySource
Spring Framework 4.3 introduced the `PropertySourceFactory` SPI for use
with `@PropertySource` on `@Configuration` classes; however, prior to
this commit there was no mechanism to support custom properties file
formats in `@TestPropertySource` for integration tests.

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

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

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

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

Closes gh-30981
2023-08-04 14:57:22 +03:00
Sam Brannen b80872b762 Polishing 2023-08-04 13:52:14 +03:00
Sébastien Deleuze 8feb8198fe Merge branch '6.0.x' 2023-08-04 11:30:29 +02:00
Brian Clozel c97def0b98 Merge branch '6.0.x' 2023-08-04 10:32:00 +02:00
Juergen Hoeller 4e863c5a75 Merge branch '6.0.x' 2023-08-04 02:40:17 +02:00
Juergen Hoeller a6ff95a69c Restore restrictive getTypeForFactoryBeanFromAttributes check
See gh-29799
See gh-30987
2023-08-04 00:56:01 +02:00
Juergen Hoeller f7c3e6480a Merge branch '6.0.x'
# Conflicts:
#	spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
2023-08-04 00:49:20 +02:00
Juergen Hoeller d868f58e6e Merge branch '6.0.x'
# Conflicts:
#	spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java
2023-08-03 18:11:08 +02:00
Juergen Hoeller 84b3335e71 Apply array editor to collection of same element type as well
Closes gh-24845
2023-08-03 17:55:54 +02:00
Juergen Hoeller c3e18bc173 Retain metadata during bean creation even with cacheBeanMetadata=false
Closes gh-23795
Closes gh-25749
2023-08-03 17:55:47 +02:00
Sébastien Deleuze c942c04aa0 Support resource bundle custom file extensions
This commit allows to configure custom file
extensions in ReloadableResourceBundleMessageSource
thanks to a new setFileExtensions setter.

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

Closes gh-18990
2023-08-03 14:29:29 +02:00
rstoyanchev ad80b94e14 Allow BindParam on a field
See gh-30947
2023-08-03 15:11:08 +03:00
rstoyanchev 8513ec7440 Update documentation for data binding improvements
Closes gh-30952
2023-08-02 17:21:33 +03:00
Rossen Stoyanchev 667eb42a63 Polishing
See gh-30952
2023-08-01 07:50:06 +03:00
Sam Brannen bd23798323 Polish Javadoc for PropertySourceDescriptor 2023-08-03 14:33:53 +03:00
Sam Brannen 961084dfe0 Merge branch '6.0.x' 2023-08-03 11:27:37 +03:00
Sam Brannen 3e5aa8d734 Fail on error by default during test AOT processing
Prior to this commit, if an error was encountered during build-time AOT
processing, the error was logged at WARN/DEBUG level, and processing
continued.

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

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

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

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

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

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

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

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

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

Closes gh-19877
2023-07-19 21:56:44 +02:00
Sam Brannen 9571aa1c68 Stop using Constants utility in IsolationLevelDataSourceAdapter
See gh-30851
2023-07-19 18:05:41 +03:00
Sam Brannen 97810c84a2 Stop using Constants utility in AbstractPlatformTransactionManager
See gh-30851
2023-07-19 17:29:36 +03:00
Sam Brannen d0076f5c14 Stop using Constants utility in DefaultTransactionDefinition
See gh-30851
2023-07-19 16:35:15 +03:00
Sam Brannen c110644107 Polish TransactionSupportTests 2023-07-19 14:33:40 +03:00
Sam Brannen 05956d4028 Change MvcSimpleAsyncTaskExecutor.taskExecutorWarning to primitive boolean 2023-07-19 13:21:57 +03:00
Sam Brannen b2ca36f098 Stop using Constants utility in JmsAccessor
See gh-30851
2023-07-19 12:16:26 +03:00
Sam Brannen 15253f3448 Polish JmsAccessor[Tests] 2023-07-19 12:16:14 +03:00
Sam Brannen 4e00c988c1 Stop using Constants utility in JmsActivationSpecConfig
See gh-30851
2023-07-19 11:48:28 +03:00
Brian Clozel c88c9620b3 Upgrade to Java 21 EA 31 in CI build 2023-07-19 09:51:28 +02:00
Juergen Hoeller 2ac55659c8 Merge branch '6.0.x' 2023-07-19 01:26:05 +02:00
Juergen Hoeller 25ea1f4c0f Merge branch '6.0.x'
# Conflicts:
#	spring-context/src/main/java/org/springframework/scheduling/support/CronSequenceGenerator.java
2023-07-19 00:37:06 +02:00
Juergen Hoeller 33862d98ea Merge branch '6.0.x' 2023-07-18 22:03:03 +02:00
Juergen Hoeller c504ac5a47 Merge branch '6.0.x' 2023-07-18 12:57:18 +02:00
rstoyanchev 73c06347be Update WebMvc docs on use of AsyncTaskExecutor
Closes gh-30905
2023-07-18 10:42:27 +01:00
rstoyanchev 4becce1c2b Consolidate default WebMvc executor log warnings
Closes gh-30902
2023-07-18 10:22:45 +01:00
rstoyanchev 8a283e39ff Update DefaultHandlerExceptionResolver logging
Reduce logging for NoResourceFoundException and NoHandlerFoundException.

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

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

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

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

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

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

Closes gh-29278
2023-07-12 16:40:22 +02:00
Juergen Hoeller c1932dd307 Support for MultiValueMap elements in bean property paths
Closes gh-26297
2023-07-12 16:23:39 +02:00
Sébastien Deleuze 490ff0af5e Refine the log message printed after restoration
Closes gh-30876
2023-07-12 15:20:33 +02:00
Sam Brannen 16b9640af2 Merge branch '6.0.x' 2023-07-12 11:50:11 +02:00
Sam Brannen 2e3fbac9a0 Merge branch '6.0.x' 2023-07-12 10:36:21 +02:00
Sam Brannen 18c11e84f3 Merge branch '6.0.x' 2023-07-12 10:34:43 +02:00
Brian Clozel a2da97bc4c Upgrade to Micrometer 1.12.0-M1
Closes gh-30872
2023-07-12 09:17:09 +02:00
Brian Clozel 2e809903ec Upgrade to Reactor 2023.0.0-M1
Closes gh-30856
2023-07-12 08:56:28 +02:00
Brian Clozel 6075629015 Merge branch '6.0.x' 2023-07-12 08:55:53 +02:00
Juergen Hoeller c20a2e4763 Support for indexing into any Collection/Iterable
Closes gh-907
2023-07-11 23:07:51 +02:00
Juergen Hoeller e048b093b5 ContextClosedEvent triggers early cancelling of scheduled tasks
Closes gh-24629
See gh-27090
2023-07-11 22:11:13 +02:00
rstoyanchev 57ed5bf34b Polishing contribution
Closes gh-30869
2023-07-11 19:13:22 +01:00
Olga MaciaszekSharma 8b77ed164d Add RestClientAdapter
See gh-30869
2023-07-11 19:13:22 +01:00
Sébastien Deleuze 3a8c40fd2f Merge branch '6.0.x' 2023-07-11 19:58:44 +02:00
Juergen Hoeller 3a481a7d7f Merge branch '6.0.x' 2023-07-11 18:02:25 +02:00
rstoyanchev 74972fb751 Add updateModel to BindingContext
The method includes logic that is currently in
ViewResolutionResultHandler but fits well in BindingContext and also
includes the call to saveModel method from the InitBinderBindingContext
subclass, which was called too early until now from
RequestMappingHandlerAdapter before the model has been fully updated.

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

Closes gh-30821
2023-07-11 16:34:03 +01:00
Sam Brannen 15b6626a4c Merge branch '6.0.x' 2023-07-11 16:36:32 +02:00
rstoyanchev c61d011076 Support RestClient in MockRestServiceServer
Closes gh-30821
2023-07-11 14:46:02 +01:00
Sam Brannen 8448f597b1 Merge branch '6.0.x' 2023-07-11 15:41:51 +02:00
Sébastien Deleuze 950c43b4e7 Merge branch '6.0.x' 2023-07-11 14:07:34 +02:00
rstoyanchev 39e74d89e1 Merge branch '6.0.x' 2023-07-11 11:17:41 +01:00
Sam Brannen dc4fcef884 Merge branch '6.0.x'
# Conflicts:
#	framework-platform/framework-platform.gradle
2023-07-11 11:08:59 +02:00
Arjen Poutsma d04d7b2e57 Add request binding to functional endpoints
This commit introduces form binding to ServerRequest in both WebMVC.fn
and WebFlux.fn's, in the form of a bind(Class) method.

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

Closes gh-30117
2023-07-11 07:42:04 +01:00
rstoyanchev 3209cf5c7a Add Reactor classpath checks in argument resolvers
HTTP interface client argument resolvers for RequestBody and
RequestPart now handle reactive input conditionally.

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

See gh-30117
2023-07-10 10:36:16 +01:00
rstoyanchev 3be4c0a893 Replace Void with void on exchange method
See gh-30117
2023-07-10 09:10:14 +01:00
Olga MaciaszekSharma 268f3c853e Add RestTemplate support for HTTP interface client
See gh-30117
2023-07-06 19:07:40 +02:00
Rossen Stoyanchev bf82ed7186 Add HttpExchangeAdapter
See gh-30117
2023-06-23 11:49:29 +01:00
Eric Haag 1b27a7baab Remove explicit cross project task dependency
Previously, the runtimeHintsTest task configuration made a cross
project task reference to obtain the jar path of spring-core-test
to use in the -javaagent argument.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Closes gh-21139
2023-06-22 16:08:48 +02:00
Sam Brannen 254fb39567 Merge branch '6.0.x' 2023-06-22 16:01:22 +02:00
Sam Brannen 40596433f1 Merge branch '6.0.x' 2023-06-22 15:28:34 +02:00
Johnny Lim 3be1216897 Polish
This commit polishes a bit.

Closes gh-30691
2023-06-22 15:12:58 +02:00
Sam Brannen b8a713fde3 Merge branch '6.0.x' 2023-06-22 15:12:25 +02:00
Sam Brannen 06b6c4bcf9 Update copyright headers 2023-06-22 14:56:09 +02:00
Sam Brannen cd4ab23fa9 Merge branch '6.0.x' 2023-06-22 14:55:43 +02:00
Sam Brannen 5598dd2c34 Merge branch '6.0.x' 2023-06-22 13:54:04 +02:00
Sam Brannen f12d81f791 Merge branch '6.0.x' 2023-06-22 11:36:10 +02:00
Sam Brannen 49547fc710 Merge branch '6.0.x'
# Conflicts:
#	build.gradle
2023-06-22 11:32:39 +02:00
Brian Clozel ea8fdd17c8 Upgrade to JDK21 EA build 27 2023-06-22 08:43:03 +02:00
Juergen Hoeller a6566bfd5f Merge branch '6.0.x' 2023-06-21 18:53:15 +02:00
Sam Brannen abefc0aba0 Merge branch '6.0.x' 2023-06-21 17:54:16 +02:00
Sam Brannen 03b304f05c Merge branch '6.0.x' 2023-06-21 17:37:04 +02:00
Juergen Hoeller 54e25e2fa6 Merge branch '6.0.x' 2023-06-21 17:18:55 +02:00
Sam Brannen 83447663b4 Merge branch '6.0.x' 2023-06-21 16:21:34 +02:00
Stephane Nicoll b581a79eed Merge branch '6.0.x' 2023-06-21 14:51:00 +02:00
Sam Brannen 6535614d78 Merge branch '6.0.x' 2023-06-21 14:22:11 +02:00
Juergen Hoeller fa82683ce2 Merge branch '6.0.x' 2023-06-21 13:16:47 +02:00
Juergen Hoeller 1a201cd180 Merge branch '6.0.x'
# Conflicts:
#	spring-jcl/src/main/java/org/apache/commons/logging/LogFactory.java
2023-06-21 09:51:11 +02:00
Maarten Coene 24457660e3 Ensure Spring LogFactory contains all public methods from Apache LogFactory (#30668) 2023-06-21 09:29:58 +02:00
Juergen Hoeller f1fb8cf03e Polishing 2023-06-20 22:53:12 +02:00
Juergen Hoeller 18c6aceee7 Consistent guard for Reactive Streams presence
Closes gh-30707
2023-06-20 22:51:23 +02:00
Sébastien Deleuze 24ddceea47 Merge branch '6.0.x' 2023-06-20 20:57:33 +02:00
Sébastien Deleuze 82ec28b369 Add a CoExchangeFilterFunction for WebClient
This commit introduces a Kotlin-specific implementation
of the ExchangeFilterFunction interface that allows for
using coroutines, similar to what CoWebFilter does on
server-side.

Closes gh-30650
2023-06-20 20:54:38 +02:00
rstoyanchev db19f6395d Polishing
Closes gh-29768
2023-06-20 17:18:40 +01:00
Atsushi Yoshikawa b677ff20fe AbstractMessageConverter delegates null headers
See gh-29768
2023-06-20 17:18:40 +01:00
rstoyanchev b98c1ec36a Apply default value in case of null after conversion
Closes gh-29550
2023-06-20 17:18:40 +01:00
Stephane Nicoll 37ff9792be Merge branch '6.0.x' 2023-06-20 17:42:40 +02:00
Sam Brannen 3344ab909b Merge branch '6.0.x' 2023-06-20 15:49:13 +02:00
Stephane Nicoll 828b39587f Merge branch '6.0.x' 2023-06-20 15:21:37 +02:00
Sam Brannen 0605172d4d Merge branch '6.0.x'
# Conflicts:
#	spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java
2023-06-20 13:29:06 +02:00
rstoyanchev 089d938e15 Set throwExceptionIfNoHandlerFound=true and deprecate
Closes gh-29491
2023-06-19 17:18:09 +01:00
rstoyanchev c00508d6cf Raise and handle NoResourceFoundException
See gh-29491
2023-06-19 17:18:08 +01:00
Stephane Nicoll 83b0f4f394 Merge branch '6.0.x' 2023-06-19 15:47:26 +02:00
Brian Clozel 09cb844421 Instrument Scheduled methods for observability
This commit enhances the `ScheduledAnnotationBeanPostProcessor` to
instrument `@Scheduled` methods declared on beans. This will create
`"tasks.scheduled.execution"` observations for each execution of a
scheduled method. This supports both blocking and reactive variants.

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

Closes gh-29883
2023-06-19 08:55:08 +02:00
Juergen Hoeller 842569c9e5 Detect invalid transaction configuration for transactional event listeners
Closes gh-30679
2023-06-17 16:13:59 +02:00
Sam Brannen 3568f6c61a Merge branch '6.0.x' 2023-06-17 13:36:57 +02:00
Juergen Hoeller 5bf213948c Merge branch '6.0.x'
# Conflicts:
#	spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java
2023-06-17 11:41:07 +02:00
Sam Brannen 92c2fb45c7 Merge branch '6.0.x' 2023-06-16 13:40:18 +02:00
Sébastien Deleuze cd9c0e03e7 Merge branch '6.0.x' 2023-06-16 11:35:31 +02:00
Sam Brannen 2dd34cf967 Clean up warnings in tests 2023-06-15 16:26:34 +02:00
Sam Brannen a2072de391 Update copyright headers 2023-06-15 16:21:13 +02:00
Sam Brannen 526d9eae7f Merge branch '6.0.x' 2023-06-15 16:20:19 +02:00
Sam Brannen 7681d12eb0 Merge branch '6.0.x'
# Conflicts:
#	gradle.properties
2023-06-15 16:15:17 +02:00
Brian Clozel b077ae9259 Configure local JDK toolchains in CI staging job 2023-06-15 14:01:06 +02:00
Juergen Hoeller 362e189aa5 Adapt UserController example to current ServerRequestObservationContext
See gh-30013
2023-06-14 22:48:40 +02:00
Juergen Hoeller 96ae03b48f Merge branch '6.0.x' 2023-06-14 22:27:55 +02:00
Juergen Hoeller c276e5b679 Consistent use of 6.1 as generational version number 2023-06-14 21:58:45 +02:00
Juergen Hoeller f00a8cb3a3 Remove ServerWebExchange dependency in ServerRequestObservationContext
Avoiding cycle between http.server and web.server packages.

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

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

See gh-30571
2023-06-14 17:58:08 +02:00
rstoyanchev dcba9475ba Allow custom ProblemDetail in ErrorResponse.Builder
Closes gh-30568
2023-06-14 16:48:35 +01:00
rstoyanchev 2e43412a82 Polishing in DefaultErrorResponseBuilder
Closes gh-30566
2023-06-14 16:48:35 +01:00
rstoyanchev 48861b67dd Add "title" message code to ErrorResponse.Builder
See gh-30566
2023-06-14 16:30:15 +01:00
rstoyanchev 61eaa9333b Polishing in ErrorResponse
See gh-30566
2023-06-14 16:30:15 +01:00
rstoyanchev 9c7b5cb3f5 Add ProblemDetail "type" message code
See gh-30566
2023-06-14 16:30:15 +01:00
Sam Brannen 53828cbfad Merge branch '6.0.x' 2023-06-14 14:39:06 +02:00
Arjen Poutsma e3c602c43a Polishing
Restore thread interrupted status in JettyClientHttpRequest
2023-06-14 14:09:25 +02:00
Arjen Poutsma 02e9209e5c Merge pull request #30433 from srivatsa-cfp:main
* gh-30433:
  Polishing external contribution
  Add non-null assertions in DefaultEntityResponseBuilder
2023-06-14 13:49:20 +02:00
Arjen Poutsma 8a29bfba3f Polishing external contribution 2023-06-14 13:44:50 +02:00
Vatsa 0c817f0441 Add non-null assertions in DefaultEntityResponseBuilder
This commit adds various non-null assertions to
DefaultEntityResponseBuilder, in Spring MVC.

Closes gh-30433
2023-06-14 13:44:50 +02:00
Juergen Hoeller 326e27eab2 Merge branch '6.0.x' 2023-06-14 12:57:59 +02:00
Arjen Poutsma 5547361d18 Polishing
Store status code as HttpStatusCode instead of Object.
2023-06-14 12:05:49 +02:00
Arjen Poutsma 805d643347 Merge branch '6.0.x' 2023-06-14 11:45:04 +02:00
Juergen Hoeller b20a71a0d3 Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/util/ObjectUtils.java
2023-06-14 11:19:56 +02:00
Juergen Hoeller 3de4e931c7 Javadoc notes on isSimpleValueType in BeanUtils vs ClassUtils
See gh-30664
2023-06-14 10:40:14 +02:00
Juergen Hoeller 93345de687 Consistent Locale exposure for Bean Validation message assertions
See gh-29825
See gh-30198
2023-06-14 10:39:19 +02:00
Juergen Hoeller bbf3c6ecac Upgrade to Jackson 2.15
Closes gh-30665
2023-06-14 10:39:11 +02:00
Juergen Hoeller ca4de8f191 Consistent simple value type check
Includes UUID treatment for data binding and bean dependency checks.

Closes gh-30664
2023-06-14 09:37:39 +02:00
Juergen Hoeller 858ea1a8c5 Merge branch '6.0.x' 2023-06-14 09:32:30 +02:00
Sébastien Deleuze dd50da314d Update reference documentation index
Add "JVM Checkpoint Restore" to the Integration section.

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

See gh-29825
2023-06-13 17:40:57 +01:00
Sam Brannen e7c3e1c516 Merge branch '6.0.x' 2023-06-13 17:14:03 +02:00
Sam Brannen a268203832 Merge branch '6.0.x' 2023-06-13 16:27:20 +02:00
Sébastien Deleuze 9536dd14ef Polish PreComputeFieldFeature 2023-06-13 14:25:56 +02:00
Sébastien Deleuze c565df96f5 Remove System.out calls in PreComputeFieldFeature
Closes gh-30571
2023-06-13 14:25:32 +02:00
Juergen Hoeller 4b4a8af893 Merge branch '6.0.x' 2023-06-13 12:41:35 +02:00
rstoyanchev 1e3161b161 Expose MethodParameter in MissingServletRequestParameterException
See gh-26219
2023-06-13 11:29:35 +01:00
rstoyanchev 6b50b7b72a Initialize propertyName in TypeMismatchException
See gh-26219
2023-06-13 11:29:35 +01:00
rstoyanchev 96895c7759 Polishing in MethodArgumentNotValidException
See gh-30198
2023-06-13 11:29:35 +01:00
rstoyanchev 96c494c6ad Update error format in MethodArgumentNotValidException
1. Remove list markers (those can be provided in message).
2. Use ", and " between errors for readability.
3. Remove single quotes around errors.
4. If MessageSource is provided, use resolved message as is since in
that case applications have full control over each message.

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

Closes gh-30278
2023-06-13 08:17:54 +02:00
rstoyanchev ccf68878c7 Merge branch '6.0.x' 2023-06-12 16:12:03 +01:00
Sam Brannen f7367ceae5 Merge branch '6.0.x' 2023-06-12 16:44:48 +02:00
Stephane Nicoll 61c9cbc3f5 Retain active profiles used during AOT processing
This commit makes sure that profiles that have been explicitly enabled
during AOT optimizations are automatically enabled when using those
optimizations.

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

Closes gh-30421
2023-06-12 16:33:35 +02:00
Sébastien Deleuze 446b90172b Merge branch '6.0.x' 2023-06-12 16:01:35 +02:00
Juergen Hoeller 6501176081 Merge branch '6.0.x' 2023-06-12 12:59:55 +02:00
Sébastien Deleuze ac35ffef9e Merge branch '6.0.x' 2023-06-12 12:48:42 +02:00
Rossen Stoyanchev 6b89cf94a3 Add method validation to WebFlux
See gh-29825
2023-06-12 11:37:55 +01:00
Rossen Stoyanchev bd054a4918 Add method validation to Spring MVC
See gh-29825
2023-06-12 11:37:55 +01:00
rstoyanchev cb04c3b335 Expose isReturnValue from MethodValidationException
See gh-29825
2023-06-12 11:37:55 +01:00
rstoyanchev 5c5d8e61ae Add BindingResultNameResolver option
See gh-29825
2023-06-12 11:37:55 +01:00
rstoyanchev 0fef380202 Add MethodValidator
See gh-29825
2023-06-12 11:37:55 +01:00
Rossen Stoyanchev cc8361cd93 Add MethodValidationResult
See gh-29825
2023-06-12 11:37:55 +01:00
rstoyanchev 8b53fecc06 Use List for violations in ParameterErrors
See gh-29825
2023-06-12 11:37:55 +01:00
Rossen Stoyanchev 425d5a94cb Adapt ConstraintViolation's from method validation
See gh-29825
2023-06-12 11:37:55 +01:00
rstoyanchev 38abee00e2 Rename MethodValidationTests and polishing
See gh-29825
2023-06-12 11:37:55 +01:00
rstoyanchev 082784e023 Extract delegate from MethodValidationInterceptor
See gh-29825
2023-06-12 11:37:55 +01:00
Juergen Hoeller 155a37d3a6 Merge branch '6.0.x' 2023-06-12 10:50:40 +02:00
Sam Brannen f8a3253d12 Polishing 2023-06-11 16:32:16 +02:00
Sam Brannen b4ba80b09e Merge branch '6.0.x'
# Conflicts:
#	spring-test/src/main/java/org/springframework/test/context/cache/DefaultCacheAwareContextLoaderDelegate.java
2023-06-11 15:56:23 +02:00
Sam Brannen f6045e8e11 Move context failure tracking to the ContextCache
In the previous commit which introduced the new context failure threshold
support in the TestContext framework, the context failure tracking was
tied to an instance of DefaultCacheAwareContextLoaderDelegate.
Consequently, the feature was only supported within a given test class.

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

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

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

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

See individual commits for details.

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

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

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

See gh-14182
2023-06-09 17:40:28 +02:00
Sébastien Deleuze ccb8db41f0 Merge branch '6.0.x' 2023-06-09 15:21:54 +02:00
Sébastien Deleuze 46fe7f5bea Merge branch '6.0.x' 2023-06-09 14:17:45 +02:00
Sam Brannen 54904de77d Merge branch '6.0.x' 2023-06-09 11:52:20 +02:00
Sam Brannen dbd32f8f11 Merge branch '6.0.x' 2023-06-09 10:30:16 +02:00
Juergen Hoeller ef2b47e202 Merge branch '6.0.x' 2023-06-08 17:46:19 +02:00
Sam Brannen 60e8dbf11d Polishing 2023-06-08 17:41:22 +02:00
Sébastien Deleuze 01414d0b3d Merge branch '6.0.x' 2023-06-08 17:33:50 +02:00
Arjen Poutsma ad5bf2fac8 Merge branch '6.0.x' 2023-06-08 16:40:44 +02:00
Sam Brannen a28ef22113 Merge branch '6.0.x' 2023-06-08 16:06:31 +02:00
Sam Brannen fe55b49c7d Consistently use mergedConfig as variable name for MergedContextConfiguration 2023-06-08 15:53:38 +02:00
Sam Brannen e32a92daa7 Polishing 2023-06-08 15:44:57 +02:00
Arjen Poutsma d7970e4ab8 Support JAXBElement in Jaxb2XmlEncoder
This commit introduces support for JAXBElements in the Jaxb2XmlEncoder.

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

Closes gh-30618
2023-06-08 15:27:06 +02:00
Arjen Poutsma f4ef057e9e Merge branch '6.0.x' 2023-06-08 14:42:24 +02:00
Sébastien Deleuze 448786bfd0 Upgrade to Kotlin 1.8.22
See gh-29754
2023-06-08 09:29:06 +02:00
Sam Brannen 0093d6e34d Polish contribution
See gh-30587
2023-06-07 19:13:05 +02:00
luohongtu 324c6057fd Remove duplicate code in RequestResponseBodyMethodProcessor
Closes gh-30587
2023-06-07 19:13:05 +02:00
Juergen Hoeller 759ab23c45 Release shared JMS Connection on Single/CachingConnectionFactory.stop()
See gh-30612
2023-06-07 18:40:56 +02:00
Juergen Hoeller 1b62b6dd89 Merge branch '6.0.x' 2023-06-07 17:23:09 +02:00
Juergen Hoeller b3597f3d99 Polishing 2023-06-07 17:11:46 +02:00
Juergen Hoeller 06bb6dbcff Release shared JMS Connection before stop completion callback
Closes gh-30612
2023-06-07 17:11:35 +02:00
Sam Brannen 73e9de7b5f Simplify Javadoc 2023-06-07 17:08:11 +02:00
Sam Brannen e535ef37c7 Merge branch '6.0.x' 2023-06-07 16:02:04 +02:00
Johnny Lim dd926af5a8 This PR adds Javadoc for RegisteredBean.resolveAutowiredArgument()
See gh-30401
Closes gh-30609
2023-06-07 16:01:48 +02:00
Johnny Lim a726b5109a This PR adds Javadoc for RegisteredBean.resolveAutowiredArgument()
See gh-30401
Closes gh-30609
2023-06-07 16:00:30 +02:00
Johnny Lim 7c817dd34b Remove LocalVariableTableParameterNameDiscoverer reference in doc
See gh-29559
Closes gh-30611
2023-06-07 15:49:56 +02:00
Sam Brannen c9165470f2 Update test
See gh-30610
2023-06-07 15:04:28 +02:00
Sam Brannen 61816d0076 Merge branch '6.0.x' 2023-06-07 14:59:14 +02:00
Sam Brannen aa2a067489 Merge branch '6.0.x' 2023-06-07 13:36:05 +02:00
Sam Brannen 714d380ec0 Merge branch '6.0.x' 2023-06-07 12:01:54 +02:00
Arjen Poutsma df7223f39c Remove APIs marked for removal
See gh-30604
2023-06-07 10:20:27 +02:00
Juergen Hoeller 7f6f47b97b Property-driven onRefresh checkpoint during application context bootstrap
Closes gh-30606
2023-06-06 19:18:34 +02:00
Sam Brannen b9e972c248 Polishing 2023-06-06 16:11:40 +02:00
Sébastien Deleuze 66a1be2d86 Enable KotlinScriptTemplateTests with Java 19
No support yet for Java 21.

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

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

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

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

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

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

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

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

Closes gh-23533
Closes gh-28515
2023-06-05 14:13:44 +02:00
Juergen Hoeller 53f891226e Merge branch '6.0.x'
# Conflicts:
#	spring-core/src/main/java/org/springframework/core/CollectionFactory.java
2023-06-05 13:59:37 +02:00
Juergen Hoeller 4fb4c95220 Merge branch '6.0.x' 2023-06-05 10:53:29 +02:00
Juergen Hoeller b8b88e638b Upgrade to Checkstyle 10.12 2023-06-04 18:54:30 +02:00
Juergen Hoeller 837327f530 Merge branch '6.0.x'
# Conflicts:
#	build.gradle
2023-06-04 18:43:46 +02:00
Juergen Hoeller e224c71119 Merge branch '6.0.x' 2023-06-04 17:25:35 +02:00
Sam Brannen 5bc80fc094 Disable SpEL selector support in WebSocket messaging by default
This commit disables support for evaluating SpEL expressions from
untrusted sources by default. Specifically, this applies to the
SpEL-based 'selector' header support in WebSocket messaging, which
includes the DefaultSubscriptionRegistry and the classes used to
configure the 'selector' header name (SimpleBrokerMessageHandler and
SimpleBrokerRegistration).

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

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

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

Closes gh-30550
2023-06-04 17:02:02 +02:00
Sam Brannen 75466fee8d Merge branch '6.0.x' 2023-06-04 16:40:23 +02:00
Sam Brannen bedf5f26fe Merge branch '6.0.x' 2023-06-04 16:27:23 +02:00
Juergen Hoeller 2689bab652 Merge branch '6.0.x' 2023-06-03 17:19:06 +02:00
Juergen Hoeller e82dd14f0f Merge branch '6.0.x'
# Conflicts:
#	spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java
2023-06-02 23:30:04 +02:00
Juergen Hoeller 1dba8f6add Polishing 2023-06-02 20:45:26 +02:00
Juergen Hoeller 25a1e8d414 Reset common caches before LifecycleProcessor-initiated checkpoint
See gh-29921
2023-06-02 20:42:37 +02:00
Juergen Hoeller 8c6287ef7b Expose parameter/field name for non-JavaBeans type conversion
Supports name-bound PropertyEditor registrations on data classes.
Includes consistent support for field-aware method parameters.

Closes gh-28284
2023-06-02 20:42:05 +02:00
Juergen Hoeller 322cbca0dc Support for async/reactive close methods (e.g. R2DBC)
Closes gh-26991
2023-06-02 20:40:55 +02:00
Sam Brannen 2685a35c3a Merge branch '6.0.x' 2023-06-01 15:02:42 +02:00
Stephane Nicoll 8606d9b581 Merge branch '6.0.x' 2023-05-31 12:27:02 +02:00
Arjen Poutsma 3d63cbf076 Introduce JettyClientHttpRequestFactory
This commit introduces an implementation of ClientHttpRequestFactory
based on Jetty's HttpClient.

Closes gh-30564
2023-05-31 10:36:57 +02:00
rstoyanchev 67f88482e6 Merge branch '6.0.x' 2023-05-30 17:36:08 +01:00
rstoyanchev b3f5d20ad8 Merge branch '6.0.x' 2023-05-30 17:18:01 +01:00
Arjen Poutsma 49d688f99c Mark ClientHttpResponse::getRawStatusCode for removal 2023-05-30 15:37:58 +02:00
Arjen Poutsma 033bebf8cd Remove buffering from ClientHttpRequest implementations
This commit ensures that ClientHttpRequest implementations implement
StreamingHttpOutputMessage, so that they do not expose an OutputStream,
but store a handle capable of writing to a stream instead.

Closes gh-30557
2023-05-30 15:37:58 +02:00
Sébastien Deleuze 1ce22bdcc1 Remove MethodArgumentNotValidException(Executable, BindingResult)
Closes gh-30559
2023-05-30 12:45:01 +02:00
Sébastien Deleuze 4e678479b9 Merge branch '6.0.x' 2023-05-30 12:44:47 +02:00
Brian Clozel f69db61147 Fix JDK21 EA build URL 2023-05-30 11:51:39 +02:00
Brian Clozel 655f5eb1e2 Upgrade to JDK21 EA 24 in CI build 2023-05-30 10:49:42 +02:00
Brian Clozel e45edff4a4 Merge branch '6.0.x' 2023-05-30 10:37:50 +02:00
Stephane Nicoll fc309ee314 Merge branch '6.0.x' 2023-05-30 09:15:55 +02:00
Sébastien Deleuze 8a5f655a5c Merge branch '6.0.x' 2023-05-26 19:15:03 +02:00
Simon Baslé 3f14ebc4cf Polish ReactiveTypeHandler when checking wildcard ndjson subtype
This commit polishes the previous change, ensuring that if the request
uses a wildcard subtype with an ndjson suffix then the wildcard isn't
present in the response's Content-Type.

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

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

See gh-30312
Closes gh-30546
2023-05-26 12:08:26 +02:00
Juergen Hoeller 7150c23e93 Merge branch '6.0.x' 2023-05-26 11:03:48 +02:00
Brian Clozel 009179fed7 Merge branch '6.0.x' 2023-05-25 20:18:10 +02:00
Brian Clozel 6dbd446fc8 Update CI pipeline 2023-05-25 19:17:29 +02:00
Juergen Hoeller a45d438f05 Enforce JPA bootstrap failure for incomplete Hibernate Validator setup
Closes gh-30549
2023-05-25 18:50:57 +02:00
Juergen Hoeller cabc41bcd6 Merge branch '6.0.x' 2023-05-25 18:46:50 +02:00
Simon Baslé 5977bb05ca Port BeanPropertyRowMapper and DataClassRowMapper for r2dbc
This commit ports and adapts spring-jdbc's `BeanPropertyRowMapper` and
`DataClassRowMapper` to spring-r2dbc, allowing to `map` rows or
outParameters to object instances, data classes or records.

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

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

Closes gh-26817
2023-05-25 16:00:34 +02:00
Sam Brannen 5f13b2b35b Merge branch '6.0.x' 2023-05-25 14:03:01 +02:00
Sam Brannen 01abd521e2 Merge branch '6.0.x' 2023-05-25 13:48:15 +02:00
Sam Brannen f91fae5dfb Avoid deprecation warnings for imports 2023-05-25 13:30:54 +02:00
Sam Brannen 7169577f9c Merge branch '6.0.x' 2023-05-24 16:57:30 +02:00
Sam Brannen 72152ff1f3 Merge branch '6.0.x' 2023-05-24 14:02:51 +02:00
Juergen Hoeller 1d6246d700 Merge branch '6.0.x' 2023-05-23 20:34:58 +02:00
Juergen Hoeller 5441796675 Polishing 2023-05-23 20:01:28 +02:00
Juergen Hoeller 876e417eb4 Javadoc for setVariables and registerFunction
See gh-30045
2023-05-23 20:01:02 +02:00
rstoyanchev e6c812e2ab Merge branch '6.0.x' 2023-05-23 15:13:04 +01:00
rstoyanchev 0e5e2f5d2e Merge branch '6.0.x' 2023-05-23 15:10:10 +01:00
rstoyanchev 5bca25fe44 Remove commented out check->antora task dependency
Instead of having antora run always, which happens regardless of
whether anything has changed, we'll have it invoked as part of the CI
build, and we'll have to run it locally ourselves when necessary.

See gh-30481
2023-05-23 14:55:39 +01:00
Sam Brannen ab253470f0 Update copyright headers 2023-05-23 15:12:32 +02:00
Sam Brannen 02f152c6e1 Merge branch '6.0.x' 2023-05-23 15:11:19 +02:00
Sam Brannen 791802fdf7 Merge branch '6.0.x' 2023-05-23 12:41:26 +02:00
Sam Brannen f4f8066877 Merge branch '6.0.x' 2023-05-23 11:36:40 +02:00
Sam Brannen d95ecbe0fd Merge branch '6.0.x'
# Conflicts:
#	spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java
2023-05-23 11:29:10 +02:00
Sébastien Deleuze cba77c6909 Merge branch '6.0.x' 2023-05-23 11:21:03 +02:00
Sébastien Deleuze b4eb352e1d Merge branch '6.0.x' 2023-05-23 09:11:07 +02:00
rstoyanchev 5fc937d558 Remove asciidoctor build plugins after move to antora 2023-05-23 07:19:52 +01:00
rstoyanchev f926deda89 Fix link to code in documentation
See gh-30013
2023-05-23 07:18:16 +01:00
Sébastien Deleuze c3e28728ce Upgrade to Kotlin Serialization 1.5
Closes gh-30515
2023-05-22 18:07:32 +02:00
Sébastien Deleuze f956d399ae Upgrade to Kotlin Coroutines 1.7
Leverages Kotlin/kotlinx.coroutines#3487.

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

Closes gh-29754
2023-05-22 15:43:37 +02:00
Stephane Nicoll 5e07141846 Merge branch '6.0.x' 2023-05-22 15:30:47 +02:00
Brian Clozel 40543e0a58 Polish SnakeYAML 2.0 upgrade
See gh-30048
2023-05-22 14:52:59 +02:00
Andrey Somov 097758baf3 Upgrade to SnakeYAML 2.0
This commit raises the SnakeYAML baseline version to 2.0.
While most Spring applications are not affected by CVE-2022-1471,
upgrading this version should prevent automated tools from raising this
as a security issue. Such tools usually do not understand that YAML
parsing in Spring is about reading configuration, not parsing untrusted
content.

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

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

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

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

Fixes gh-30013
2023-05-22 11:03:02 +02:00
greg.lee e5ee369e70 Introduce method in MockHttpServletRequestBuilder to set remote address
Co-authored-by: Sam Brannen <sam@sambrannen.com>
Closes gh-30497
2023-05-16 17:30:48 +02:00
Simon Baslé f5bc084ce2 Merge branch '6.0.x' (javadoc changes) 2023-05-16 15:05:42 +02:00
Sam Brannen d86cfc949d Polishing 2023-05-15 16:07:15 +02:00
Sam Brannen 1d708510df Merge branch '6.0.x' 2023-05-15 15:23:16 +02:00
Sam Brannen 1275b10d9c Merge branch '6.0.x' 2023-05-15 15:09:56 +02:00
Sébastien Deleuze 1f3dd3e2ee Merge branch '6.0.x' 2023-05-15 11:49:31 +02:00
Sam Brannen c227fbfdf2 Reorganize helper methods to align with first usage principle 2023-05-13 19:29:48 +02:00
Sam Brannen f3f3dc693a Fix logic for validating @RecordApplicationEvents config
Prior to this commit, the SpringExtension looked up the
TestInstance.Lifecycle and ExecutionMode using
TestContextAnnotationUtils; however, using TestContextAnnotationUtils is
problematic since the TestInstance.Lifecycle and ExecutionMode can be
configured globally via configuration parameters instead of locally via
the @TestInstance and @Execution annotations.

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

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

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

See gh-29921
2023-05-12 09:29:35 +02:00
Stephane Nicoll ffa431da7b Merge branch '6.0.x' 2023-05-12 08:59:57 +02:00
Brian Clozel a91effcd86 Ignore some FreeMarker tests for JDK21
This reverts commit 07a5d8c91 and instead disables the relevant
FreeMarker tests for JDK21+ runs.
2023-05-11 18:00:23 +02:00
Brian Clozel 07a5d8c91c Fix FreeMarker tests for JDK21 build
Prior to this commit, some FreeMarker tests would fail when involving
property lookup in a template file, where this bean property is linked
with a method implemented as a default method on an interface.

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

This commit changes the template expression to using the default method
directly.
2023-05-11 17:10:26 +02:00
Stephane Nicoll 0bd0578ff9 Merge branch '6.0.x' 2023-05-11 16:36:38 +02:00
Brian Clozel 2f3a73a59e Merge branch '6.0.x' 2023-05-11 15:28:30 +02:00
Juergen Hoeller 1e74d793a2 Merge branch '6.0.x' 2023-05-10 18:51:40 +02:00
rstoyanchev 3d96e3f8c8 Merge branch '6.0.x' 2023-05-10 17:39:56 +01:00
Sam Brannen d8215a62f6 Merge branch '6.0.x' 2023-05-10 17:40:42 +02:00
Juergen Hoeller 841124af75 Merge branch '6.0.x' 2023-05-10 17:19:39 +02:00
Simon Baslé dbc42f56b3 Merge branch '6.0.x' 2023-05-10 15:18:57 +02:00
Sam Brannen 96fbcb26c9 Merge branch '6.0.x' 2023-05-10 14:36:09 +02:00
Sam Brannen 6a6dd599a1 Remove duplicate Checkstyle suppressions 2023-05-10 14:31:24 +02:00
Sam Brannen 5e52259fb3 Suppress warnings in tests 2023-05-10 14:27:43 +02:00
Sam Brannen e51c71bcd6 Delete unused code 2023-05-10 14:26:41 +02:00
Stephane Nicoll 4d5e235166 Merge branch '6.0.x' 2023-05-10 13:55:36 +02:00
rstoyanchev 5236d17ac4 Re-enable flaky tests after bd66c70b
See gh-29287
2023-05-10 11:44:32 +01:00
rstoyanchev d9f659171b Merge branch '6.0.x' 2023-05-10 11:43:38 +01:00
Stephane Nicoll 993a69d3a9 Deprecate spring context indexer
This commit deprecates the context indexer as our efforts on the AOT
engine cover the indexer in a much broader fashion.

Closes gh-30431
2023-05-10 09:13:57 +02:00
rstoyanchev 944305b9f1 Merge branch '6.0.x' 2023-05-09 19:59:11 +01:00
Stephane Nicoll 6eb63f778e Merge branch '6.0.x' 2023-05-09 16:27:23 +02:00
Stephane Nicoll eb240016ed Merge branch '6.0.x' 2023-05-09 14:52:49 +02:00
Arjen Poutsma b674906e3a Document @ResponseStatus behavior
This commit documents that the ResponseStatus annotation does not
override the status set through other means.

Closes gh-30305
See gh-18019
2023-05-09 14:08:04 +02:00
rstoyanchev bc7ba8cf2b Merge branch '6.0.x'
Closes gh-30435
2023-05-09 12:16:13 +01:00
Brian Clozel b4649137fc Merge branch '6.0.x' 2023-05-09 09:34:33 +02:00
Arjen Poutsma c8b920a05d Fix SimpleAsyncTaskExecutor virtual thread path
This commit makes sure that the SimpleAsyncTaskExecutor only creates a
virtual thread when the virtualThreadDelegate is set, and not an
additional kernel thread as well.

See gh-30241
2023-05-08 16:59:35 +02:00
Brian Clozel c564725f46 Upgrade to Java 21 EA build 21 2023-05-08 15:42:35 +02:00
Brian Clozel e599fec685 Make JDK21 available as toolchain in main build
See gh-30339
See gh-30241
2023-05-08 15:27:30 +02:00
Juergen Hoeller 657fe1fa43 Merge branch '6.0.x' 2023-05-08 14:52:26 +02:00
Juergen Hoeller 697d5e6247 Configuration options for virtual threads (on JDK 21)
VirtualThreadDelegate built on JDK 21 for multi-release jar.
Includes dedicated VirtualThreadTaskExecutor as lean option.
Includes setVirtualThreads flag on SimpleAsyncTaskExecutor.
Includes additional default methods on AsyncTaskExecutor.

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

Closes gh-27914
2023-05-08 11:21:29 +02:00
rstoyanchev 73d30dd875 Polishing contribution
Closes gh-30403
2023-05-05 20:53:52 +01:00
Olga MaciaszekSharma 033548a760 Remove default blockTimeout on interface clients
See gh-30403
2023-05-05 20:53:52 +01:00
Sébastien Deleuze e416dfdbc0 Merge branch '6.0.x' 2023-05-05 18:20:43 +02:00
rstoyanchev 592a3074e1 Merge branch '6.0.x'
Closes gh-30430
2023-05-05 16:57:08 +01:00
Simon Baslé b39e93d0d1 Add test support to record async events, with Junit5 caveat
This commit modifies the way the `@RecordApplicationEvents` annotation
works in tests, allowing for capture of events from threads other than
the main test thread (async events) and for the assertion of captured
event from a separate thread (e.g. when using `Awaitility`).

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

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

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

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

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

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

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

See gh-30318
Closes gh-30352
2023-05-05 16:13:06 +02:00
Stephane Nicoll f2c0b30641 Merge branch '6.0.x' 2023-05-05 15:04:15 +02:00
Rob Winch 601de66c03 nohttp exclude **/.gradle/** 2023-05-04 17:47:37 +01:00
rstoyanchev 91ea2d4c27 Merge branch '6.0.x'
Closes gh-30414
2023-05-04 15:46:54 +01:00
Sébastien Deleuze b7884ddd02 Disable flaky ReactorNetty2StompBrokerRelayIntegrationTests
See gh-29287
2023-05-04 16:37:17 +02:00
Sébastien Deleuze 9fec516560 Skip CRaC support with native images
Skip CRaC support with native images to avoid compiling related
infrastructure to the native image and to fix tests via
gh-30422.

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

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

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

Closes gh-30422
2023-05-04 15:31:31 +02:00
Stephane Nicoll 69cde11a51 Merge branch '6.0.x' 2023-05-04 12:23:46 +02:00
Juergen Hoeller 7d2047cdbd Prevent JVM shutdown before checkpoint
See gh-30242
2023-05-03 18:16:32 +02:00
Juergen Hoeller c76116b970 Keep CracResourceAdapter strongly reachable
See gh-30242
2023-05-03 17:50:36 +02:00
Juergen Hoeller 8d604350e4 Support for Project CRaC in DefaultLifecycleProcessor
Includes stopForRestart/restartAfterStop functionality.

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

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

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

Closes gh-29481
Closes gh-28522
2023-04-30 23:03:39 +02:00
Sam Brannen dfd74495bd Merge branch '6.0.x' 2023-04-28 16:09:15 +02:00
Sébastien Deleuze 90ffa95b6a Merge branch '6.0.x' 2023-04-28 10:00:59 +02:00
Stephane Nicoll 825f160369 Merge branch '6.0.x' 2023-04-26 16:55:10 +02:00
Stephane Nicoll 834e694e94 Merge branch '6.0.x' 2023-04-26 14:39:58 +02:00
Sam Brannen ce3e9b0c29 Polishing 2023-04-26 11:21:34 +02:00
Sam Brannen 1c7ceaa2ca Improve Javadoc for AbstractEnvironment and Profiles 2023-04-26 11:09:38 +02:00
Sam Brannen 7e0620a143 Use new Environment.matchesProfiles() method 2023-04-26 11:09:38 +02:00
Sam Brannen fb039a3e0c Merge branch '6.0.x' 2023-04-26 10:37:35 +02:00
Sam Brannen 05e4234525 Merge branch '6.0.x' 2023-04-25 19:52:06 +02:00
Sam Brannen e19472568f Merge branch '6.0.x' 2023-04-25 18:11:35 +02:00
Sam Brannen 845488af8d Improve toString() for Profiles.of() implementation
Prior to this commit, the toString() implementation in ProfilesParser
(which is the internal implementation of Profiles.of()) concatenated
profile expressions with " or ".

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

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

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

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

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

Closes gh-30374
2023-04-25 16:49:34 +02:00
Sam Brannen b924b7b4c6 Merge branch '6.0.x' 2023-04-25 15:15:45 +02:00
Sam Brannen b368fc03ea Merge branch '6.0.x' 2023-04-25 14:09:30 +02:00
Sam Brannen 982a094646 Rename determineResource() to resolveResource()
See gh-30369
2023-04-25 11:35:00 +02:00
Sam Brannen dfe320f172 Reorganize methods in ReloadableResourceBundleMessageSource
See gh-30369
2023-04-25 11:08:56 +02:00
Sam Brannen 2537c7c735 Polish Javadoc in ReloadableResourceBundleMessageSource
See gh-30369
2023-04-25 11:08:56 +02:00
Arjen Poutsma 54853ee239 Support setCharacterEncoding(null) in MockHttpServletResponse
Closes gh-30341
2023-04-25 10:53:44 +02:00
Brian Clozel b408cee29f Merge branch '6.0.x' 2023-04-25 10:26:40 +02:00
Simon Baslé e63d89973a Add ReloadableResourceBundleMessageSource Resource selection hook
This commit enables sub-classes to better customize resource selection
and resource loading in `ReloadableResourceBundleMessageSource`, without
a need to duplicate the caching logic of `refreshProperties`.

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

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

Closes gh-30361

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

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

Closes gh-30355
2023-04-20 16:44:58 +02:00
Sam Brannen c16dab236a Merge branch '6.0.x' 2023-04-20 16:21:16 +02:00
Stephane Nicoll 202c46035a Merge branch '6.0.x' 2023-04-20 15:49:01 +02:00
Stephane Nicoll ea83d66fb5 Merge branch '6.0.x' 2023-04-20 15:43:19 +02:00
Arjen Poutsma 9f85e397d4 Support XmlSeeAlso in Jaxb2XmlDecoder
This commit adds support for the @XmlSeeAlso annotation in the
Jaxb2XmlDecoder. This includes

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

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

Subsequent commits will remove additional deprecated APIs.

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

Closes gh-30341
2023-04-19 15:17:31 +02:00
Toshiaki Maki 5f98afc180 Introduce functional factory methods in Validator
This commit introduces `of` method in `Validator` to provide a way to
create a validator for the specific type `<T>` using `BiConsumer<T, Errors>`
and define the validator in a functional way.
This also eliminates the boilerplate for implementing the `supports` method.
2023-04-19 13:54:51 +02:00
Arjen Poutsma 7492c0ea03 Merge branch '6.0.x' 2023-04-18 15:35:36 +02:00
Sam Brannen 65a430bb42 Upgrade to Checkstyle 10.9.3 again
Commit ed4404f350 inadvertently switched back to 10.9.1.
2023-04-18 14:09:43 +02:00
Stephane Nicoll bd62f47afa Merge pull request #30340 from jstansel
* pr/30340:
  Fix link to releases feed

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

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

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

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

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

See gh-30339
2023-04-14 10:27:52 +02:00
Brian Clozel bd55b647c7 Switch to 6.1.0-SNAPSHOT version 2023-04-14 10:17:09 +02:00
Spring Builds 19c7527376 Next development version (v6.0.9-SNAPSHOT) 2023-04-13 08:30:07 +00:00
1736 changed files with 69397 additions and 21141 deletions
+6 -6
View File
@@ -123,13 +123,13 @@ define the source file coding standards we use along with some IDEA editor setti
### Reference Docs
The reference documentation is in the [framework-docs/src/docs/asciidoc](framework-docs/src/docs/asciidoc) directory, in
[Asciidoctor](https://asciidoctor.org/) format. For trivial changes, you may be able to browse,
edit source files, and submit directly from GitHub.
The reference documentation is authored in [Asciidoctor](https://asciidoctor.org/) format
using [Antora](https://docs.antora.org/antora/latest/). The source files for the documentation
reside in the [framework-docs/modules/ROOT](framework-docs/modules/ROOT) directory. For
trivial changes, you may be able to browse, edit source files, and submit directly from GitHub.
When making changes locally, execute `./gradlew :framework-docs:asciidoctor` and then browse the result under
`framework-docs/build/docs/ref-docs/html5/index.html`.
When making changes locally, execute `./gradlew antora` and then browse the results under
`framework-docs/build/site/index.html`.
Asciidoctor also supports live editing. For more details see
[AsciiDoc Tooling](https://docs.asciidoctor.org/asciidoctor/latest/tooling/).
+3 -3
View File
@@ -2,7 +2,7 @@
This is the home of the Spring Framework: the foundation for all [Spring projects](https://spring.io/projects). Collectively the Spring Framework and the family of Spring projects are often referred to simply as "Spring".
Spring provides everything required beyond the Java programming language for creating enterprise applications for a wide range of scenarios and architectures. Please read the [Overview](https://docs.spring.io/spring/docs/current/spring-framework-reference/overview.html#spring-introduction) section as reference for a more complete introduction.
Spring provides everything required beyond the Java programming language for creating enterprise applications for a wide range of scenarios and architectures. Please read the [Overview](https://docs.spring.io/spring-framework/reference/overview.html) section of the reference documentation for a more complete introduction.
## Code of Conduct
@@ -14,7 +14,7 @@ For access to artifacts or a distribution zip, see the [Spring Framework Artifac
## Documentation
The Spring Framework maintains reference documentation ([published](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/) and [source](framework-docs/src/docs/asciidoc)), GitHub [wiki pages](https://github.com/spring-projects/spring-framework/wiki), and an
The Spring Framework maintains reference documentation ([published](https://docs.spring.io/spring-framework/reference/) and [source](framework-docs/modules/ROOT)), GitHub [wiki pages](https://github.com/spring-projects/spring-framework/wiki), and an
[API reference](https://docs.spring.io/spring-framework/docs/current/javadoc-api/). There are also [guides and tutorials](https://spring.io/guides) across Spring projects.
## Micro-Benchmarks
@@ -31,7 +31,7 @@ Information regarding CI builds can be found in the [Spring Framework Concourse
## Stay in Touch
Follow [@SpringCentral](https://twitter.com/springcentral), [@SpringFramework](https://twitter.com/springframework), and its [team members](https://twitter.com/springframework/lists/team/members) on Twitter. In-depth articles can be found at [The Spring Blog](https://spring.io/blog/), and releases are announced via our [news feed](https://spring.io/blog/category/news).
Follow [@SpringCentral](https://twitter.com/springcentral), [@SpringFramework](https://twitter.com/springframework), and its [team members](https://twitter.com/springframework/lists/team/members) on Twitter. In-depth articles can be found at [The Spring Blog](https://spring.io/blog/), and releases are announced via our [releases feed](https://spring.io/blog/category/releases).
## License
+25 -73
View File
@@ -1,22 +1,24 @@
plugins {
id 'io.spring.nohttp' version '0.0.11'
id 'io.freefair.aspectj' version '8.0.1' apply false
id 'io.freefair.aspectj' version '8.4' apply false
// kotlinVersion is managed in gradle.properties
id 'org.jetbrains.kotlin.plugin.serialization' version "${kotlinVersion}" apply false
id 'org.jetbrains.dokka' version '1.8.10'
id 'org.jetbrains.dokka' version '1.8.20'
id 'org.unbroken-dome.xjc' version '2.0.0' apply false
id 'com.github.ben-manes.versions' version '0.49.0'
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
id 'de.undercouch.download' version '5.4.0'
id 'me.champeau.jmh' version '0.7.1' apply false
id 'me.champeau.jmh' version '0.7.2' apply false
id 'me.champeau.mrjar' version '0.1.1'
}
ext {
moduleProjects = subprojects.findAll { it.name.startsWith("spring-") }
javaProjects = subprojects - project(":framework-bom") - project(":framework-platform")
javaProjects = subprojects.findAll { !it.name.startsWith("framework-") }
}
configure(allprojects) { project ->
apply plugin: "org.springframework.build.localdev"
group = "org.springframework"
repositories {
mavenCentral()
maven {
@@ -41,16 +43,7 @@ configure(allprojects) { project ->
}
}
configure([rootProject] + javaProjects) { project ->
group = "org.springframework"
apply plugin: "java"
apply plugin: "java-test-fixtures"
apply plugin: "checkstyle"
apply plugin: 'org.springframework.build.conventions'
apply from: "${rootDir}/gradle/toolchains.gradle"
apply from: "${rootDir}/gradle/ide.gradle"
configure(allprojects - project(":framework-platform")) {
configurations {
dependencyManagement {
canBeConsumed = false
@@ -59,36 +52,19 @@ configure([rootProject] + javaProjects) { project ->
}
matching { it.name.endsWith("Classpath") }.all { it.extendsFrom(dependencyManagement) }
}
test {
useJUnitPlatform()
include(["**/*Tests.class", "**/*Test.class"])
systemProperty("java.awt.headless", "true")
systemProperty("testGroups", project.properties.get("testGroups"))
systemProperty("io.netty.leakDetection.level", "paranoid")
systemProperty("io.netty5.leakDetectionLevel", "paranoid")
systemProperty("io.netty5.leakDetection.targetRecords", "32")
systemProperty("io.netty5.buffer.lifecycleTracingEnabled", "true")
systemProperty("io.netty5.buffer.leakDetectionEnabled", "true")
jvmArgs(["--add-opens=java.base/java.lang=ALL-UNNAMED",
"--add-opens=java.base/java.util=ALL-UNNAMED"])
}
checkstyle {
toolVersion = "10.12.5"
configDirectory.set(rootProject.file("src/checkstyle"))
}
tasks.named("checkstyleMain").configure {
maxHeapSize = "1g"
}
tasks.named("checkstyleTest").configure {
maxHeapSize = "1g"
}
dependencies {
dependencyManagement(enforcedPlatform(dependencies.project(path: ":framework-platform")))
}
}
configure([rootProject] + javaProjects) { project ->
apply plugin: "java"
apply plugin: "java-test-fixtures"
apply plugin: 'org.springframework.build.conventions'
apply from: "${rootDir}/gradle/toolchains.gradle"
apply from: "${rootDir}/gradle/ide.gradle"
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-api")
testImplementation("org.junit.jupiter:junit-jupiter-params")
testImplementation("org.junit.platform:junit-platform-suite-api")
@@ -106,7 +82,6 @@ configure([rootProject] + javaProjects) { project ->
// JSR-305 only used for non-required meta-annotations
compileOnly("com.google.code.findbugs:jsr305")
testCompileOnly("com.google.code.findbugs:jsr305")
checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:0.0.39")
}
ext.javadocLinks = [
@@ -118,23 +93,23 @@ configure([rootProject] + javaProjects) { project ->
"https://docs.jboss.org/hibernate/orm/5.6/javadocs/",
"https://eclipse.dev/aspectj/doc/released/aspectj5rt-api",
"https://www.quartz-scheduler.org/api/2.3.0/",
"https://www.javadoc.io/doc/com.fasterxml.jackson.core/jackson-core/2.14.1/",
"https://www.javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind/2.14.1/",
"https://www.javadoc.io/doc/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.14.1/",
"https://fasterxml.github.io/jackson-core/javadoc/2.14/",
"https://fasterxml.github.io/jackson-databind/javadoc/2.14/",
"https://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.14/",
"https://hc.apache.org/httpcomponents-client-5.2.x/current/httpclient5/apidocs/",
"https://projectreactor.io/docs/test/release/api/",
"https://junit.org/junit4/javadoc/4.13.2/",
// TODO Uncomment link to JUnit 5 docs once we execute Gradle with Java 18+.
// See https://github.com/spring-projects/spring-framework/issues/27497
//
// "https://junit.org/junit5/docs/5.9.3/api/",
// "https://junit.org/junit5/docs/5.10.1/api/",
"https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/",
"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/",
//"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/",
"https://r2dbc.io/spec/1.0.0.RELEASE/api/",
// Previously there could be a split-package issue between JSR250 and JSR305 javax.annotation packages,
// but since 6.0 JSR 250 annotations such as @Resource and @PostConstruct have been replaced by their
// JakartaEE equivalents in the jakarta.annotation package.
"https://www.javadoc.io/doc/com.google.code.findbugs/jsr305/3.0.2/"
//"https://www.javadoc.io/doc/com.google.code.findbugs/jsr305/3.0.2/"
] as String[]
}
@@ -144,28 +119,5 @@ configure(moduleProjects) { project ->
configure(rootProject) {
description = "Spring Framework"
apply plugin: "io.spring.nohttp"
apply plugin: 'org.springframework.build.api-diff'
nohttp {
source.exclude "**/test-output/**"
source.exclude "**/.gradle/**"
allowlistFile = project.file("src/nohttp/allowlist.lines")
def rootPath = file(rootDir).toPath()
def projectDirs = allprojects.collect { it.projectDir } + "${rootDir}/buildSrc"
projectDirs.forEach { dir ->
[ 'bin', 'build', 'out', '.settings' ]
.collect { rootPath.relativize(new File(dir, it).toPath()) }
.forEach { source.exclude "$it/**" }
[ '.classpath', '.project' ]
.collect { rootPath.relativize(new File(dir, it).toPath()) }
.forEach { source.exclude "$it" }
}
}
tasks.named("checkstyleNohttp").configure {
maxHeapSize = "1g"
}
}
+10 -2
View File
@@ -1,5 +1,6 @@
plugins {
id 'java-gradle-plugin'
id 'checkstyle'
}
repositories {
@@ -17,10 +18,13 @@ ext {
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
implementation("org.jetbrains.kotlin:kotlin-compiler-embeddable:${kotlinVersion}")
checkstyle "io.spring.javaformat:spring-javaformat-checkstyle:${javaFormatVersion}"
implementation "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}"
implementation "org.jetbrains.kotlin:kotlin-compiler-embeddable:${kotlinVersion}"
implementation "me.champeau.gradle:japicmp-gradle-plugin:0.3.0"
implementation "org.gradle:test-retry-gradle-plugin:1.4.1"
implementation "io.spring.javaformat:spring-javaformat-gradle-plugin:${javaFormatVersion}"
implementation "io.spring.nohttp:nohttp-gradle:0.0.11"
}
gradlePlugin {
@@ -33,6 +37,10 @@ gradlePlugin {
id = "org.springframework.build.conventions"
implementationClass = "org.springframework.build.ConventionsPlugin"
}
localDevPlugin {
id = "org.springframework.build.localdev"
implementationClass = "org.springframework.build.dev.LocalDevelopmentPlugin"
}
optionalDependenciesPlugin {
id = "org.springframework.build.optional-dependencies"
implementationClass = "org.springframework.build.optional.OptionalDependenciesPlugin"
+27
View File
@@ -0,0 +1,27 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" "https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="com.puppycrawl.tools.checkstyle.Checker">
<!-- Root Checks -->
<module name="io.spring.javaformat.checkstyle.check.SpringHeaderCheck">
<property name="fileExtensions" value="java"/>
<property name="headerType" value="apache2"/>
<property name="headerCopyrightPattern" value="20\d\d-20\d\d"/>
<property name="packageInfoHeaderType" value="none"/>
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck"/>
<!-- TreeWalker Checks -->
<module name="com.puppycrawl.tools.checkstyle.TreeWalker">
<!-- Imports -->
<module name="com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck">
<property name="processJavadoc" value="true"/>
</module>
<!-- Modifiers -->
<module name="com.puppycrawl.tools.checkstyle.checks.modifier.ModifierOrderCheck"/>
</module>
</module>
+1
View File
@@ -1 +1,2 @@
org.gradle.caching=true
javaFormatVersion=0.0.39
@@ -0,0 +1,79 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.build;
import java.io.File;
import java.nio.file.Path;
import java.util.List;
import io.spring.javaformat.gradle.SpringJavaFormatPlugin;
import io.spring.nohttp.gradle.NoHttpExtension;
import io.spring.nohttp.gradle.NoHttpPlugin;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.plugins.quality.Checkstyle;
import org.gradle.api.plugins.quality.CheckstyleExtension;
import org.gradle.api.plugins.quality.CheckstylePlugin;
/**
* {@link Plugin} that applies conventions for checkstyle.
*
* @author Brian Clozel
*/
public class CheckstyleConventions {
/**
* Applies the Spring Java Format and Checkstyle plugins with the project conventions.
* @param project the current project
*/
public void apply(Project project) {
project.getPlugins().withType(JavaBasePlugin.class, (java) -> {
if (project.getRootProject() == project) {
configureNoHttpPlugin(project);
}
project.getPlugins().apply(CheckstylePlugin.class);
project.getTasks().withType(Checkstyle.class).forEach(checkstyle -> checkstyle.getMaxHeapSize().set("1g"));
CheckstyleExtension checkstyle = project.getExtensions().getByType(CheckstyleExtension.class);
checkstyle.setToolVersion("10.12.5");
checkstyle.getConfigDirectory().set(project.getRootProject().file("src/checkstyle"));
String version = SpringJavaFormatPlugin.class.getPackage().getImplementationVersion();
DependencySet checkstyleDependencies = project.getConfigurations().getByName("checkstyle").getDependencies();
checkstyleDependencies
.add(project.getDependencies().create("io.spring.javaformat:spring-javaformat-checkstyle:" + version));
});
}
private static void configureNoHttpPlugin(Project project) {
project.getPlugins().apply(NoHttpPlugin.class);
NoHttpExtension noHttp = project.getExtensions().getByType(NoHttpExtension.class);
noHttp.setAllowlistFile(project.file("src/nohttp/allowlist.lines"));
noHttp.getSource().exclude("**/test-output/**", "**/.settings/**",
"**/.classpath", "**/.project", "**/.gradle/**");
List<String> buildFolders = List.of("bin", "build", "out");
project.allprojects(subproject -> {
Path rootPath = project.getRootDir().toPath();
Path projectPath = rootPath.relativize(subproject.getProjectDir().toPath());
for (String buildFolder : buildFolders) {
Path innerBuildDir = projectPath.resolve(buildFolder);
noHttp.getSource().exclude(innerBuildDir + File.separator + "**");
}
});
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,10 +25,8 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinBasePlugin;
* Plugin to apply conventions to projects that are part of Spring Framework's build.
* Conventions are applied in response to various plugins being applied.
*
* When the {@link JavaBasePlugin} is applied, the conventions in {@link TestConventions}
* are applied.
* When the {@link JavaBasePlugin} is applied, the conventions in {@link JavaConventions}
* are applied.
* <p>When the {@link JavaBasePlugin} is applied, the conventions in {@link CheckstyleConventions},
* {@link TestConventions} and {@link JavaConventions} are applied.
* When the {@link KotlinBasePlugin} is applied, the conventions in {@link KotlinConventions}
* are applied.
*
@@ -38,8 +36,10 @@ public class ConventionsPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
new CheckstyleConventions().apply(project);
new JavaConventions().apply(project);
new KotlinConventions().apply(project);
new TestConventions().apply(project);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,10 @@ import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.jvm.toolchain.JavaLanguageVersion;
import org.gradle.jvm.toolchain.JvmVendorSpec;
/**
* {@link Plugin} that applies conventions for compiling Java sources in Spring Framework.
@@ -68,6 +71,10 @@ public class JavaConventions {
* @param project the current project
*/
private void applyJavaCompileConventions(Project project) {
project.getExtensions().getByType(JavaPluginExtension.class).toolchain(toolchain -> {
toolchain.getVendor().set(JvmVendorSpec.BELLSOFT);
toolchain.getLanguageVersion().set(JavaLanguageVersion.of(17));
});
project.getTasks().withType(JavaCompile.class)
.matching(compileTask -> compileTask.getName().equals(JavaPlugin.COMPILE_JAVA_TASK_NAME))
.forEach(compileTask -> {
@@ -16,6 +16,8 @@
package org.springframework.build;
import java.util.Map;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.tasks.testing.Test;
@@ -41,11 +43,36 @@ class TestConventions {
private void configureTestConventions(Project project) {
project.getTasks().withType(Test.class,
test -> project.getPlugins().withType(TestRetryPlugin.class, testRetryPlugin -> {
TestRetryTaskExtension testRetry = test.getExtensions().getByType(TestRetryTaskExtension.class);
testRetry.getFailOnPassedAfterRetry().set(true);
testRetry.getMaxRetries().set(isCi() ? 3 : 0);
}));
test -> {
configureTests(project, test);
configureTestRetryPlugin(project, test);
});
}
private void configureTests(Project project, Test test) {
test.useJUnitPlatform();
test.include("**/*Tests.class", "**/*Test.class");
test.setSystemProperties(Map.of(
"java.awt.headless", "true",
"io.netty.leakDetection.level", "paranoid",
"io.netty5.leakDetectionLevel", "paranoid",
"io.netty5.leakDetection.targetRecords", "32",
"io.netty5.buffer.lifecycleTracingEnabled", "true"
));
if (project.hasProperty("testGroups")) {
test.systemProperty("testGroups", project.getProperties().get("testGroups"));
}
test.jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED",
"--add-opens=java.base/java.util=ALL-UNNAMED",
"-Djava.locale.providers=COMPAT");
}
private void configureTestRetryPlugin(Project project, Test test) {
project.getPlugins().withType(TestRetryPlugin.class, testRetryPlugin -> {
TestRetryTaskExtension testRetry = test.getExtensions().getByType(TestRetryTaskExtension.class);
testRetry.getFailOnPassedAfterRetry().set(true);
testRetry.getMaxRetries().set(isCi() ? 3 : 0);
});
}
private boolean isCi() {
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.build.api;
import java.io.File;
@@ -138,4 +139,4 @@ public class ApiDiffPlugin implements Plugin<Project> {
return project.file(outDir.resolve(project.getName() + ".html").toString());
}
}
}
@@ -0,0 +1,49 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.build.dev;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaBasePlugin;
/**
* {@link Plugin} that skips documentation tasks when the {@code "-PskipDocs"} property is defined.
*
* @author Brian Clozel
*/
public class LocalDevelopmentPlugin implements Plugin<Project> {
private static final String SKIP_DOCS_PROPERTY = "skipDocs";
@Override
public void apply(Project target) {
if (target.hasProperty(SKIP_DOCS_PROPERTY)) {
skipDocumentationTasks(target);
target.subprojects(this::skipDocumentationTasks);
}
}
private void skipDocumentationTasks(Project project) {
project.afterEvaluate(p -> {
p.getTasks().matching(task -> {
return JavaBasePlugin.DOCUMENTATION_GROUP.equals(task.getGroup())
|| "distribution".equals(task.getGroup());
})
.forEach(task -> task.setEnabled(false));
});
}
}
@@ -0,0 +1,48 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.build.hint;
import java.util.Collections;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.Input;
import org.gradle.process.CommandLineArgumentProvider;
/**
* Argument provider for registering the runtime hints agent with a Java process.
*/
public interface RuntimeHintsAgentArgumentProvider extends CommandLineArgumentProvider {
@Classpath
ConfigurableFileCollection getAgentJar();
@Input
SetProperty<String> getIncludedPackages();
@Input
SetProperty<String> getExcludedPackages();
@Override
default Iterable<String> asArguments() {
StringBuilder packages = new StringBuilder();
getIncludedPackages().get().forEach(packageName -> packages.append('+').append(packageName).append(','));
getExcludedPackages().get().forEach(packageName -> packages.append('-').append(packageName).append(','));
return Collections.singleton("-javaagent:" + getAgentJar().getSingleFile() + "=" + packages);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,38 +16,15 @@
package org.springframework.build.hint;
import java.util.Collections;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.SetProperty;
/**
* Entry point to the DSL extension for the {@link RuntimeHintsAgentPlugin} Gradle plugin.
* @author Brian Clozel
*/
public class RuntimeHintsAgentExtension {
public interface RuntimeHintsAgentExtension {
private final SetProperty<String> includedPackages;
SetProperty<String> getIncludedPackages();
private final SetProperty<String> excludedPackages;
public RuntimeHintsAgentExtension(ObjectFactory objectFactory) {
this.includedPackages = objectFactory.setProperty(String.class).convention(Collections.singleton("org.springframework"));
this.excludedPackages = objectFactory.setProperty(String.class).convention(Collections.emptySet());
}
public SetProperty<String> getIncludedPackages() {
return this.includedPackages;
}
public SetProperty<String> getExcludedPackages() {
return this.excludedPackages;
}
String asJavaAgentArgument() {
StringBuilder builder = new StringBuilder();
this.includedPackages.get().forEach(packageName -> builder.append('+').append(packageName).append(','));
this.excludedPackages.get().forEach(packageName -> builder.append('-').append(packageName).append(','));
return builder.toString();
}
SetProperty<String> getExcludedPackages();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,41 +16,79 @@
package org.springframework.build.hint;
import org.gradle.api.JavaVersion;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.attributes.Bundling;
import org.gradle.api.attributes.Category;
import org.gradle.api.attributes.LibraryElements;
import org.gradle.api.attributes.Usage;
import org.gradle.api.attributes.java.TargetJvmVersion;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.tasks.bundling.Jar;
import org.gradle.api.tasks.testing.Test;
import java.util.Collections;
/**
* {@link Plugin} that configures the {@code RuntimeHints} Java agent to test tasks.
*
* @author Brian Clozel
* @author Sebastien Deleuze
*/
public class RuntimeHintsAgentPlugin implements Plugin<Project> {
public static final String RUNTIMEHINTS_TEST_TASK = "runtimeHintsTest";
private static final String EXTENSION_NAME = "runtimeHintsAgent";
private static final String CONFIGURATION_NAME = "testRuntimeHintsAgentJar";
@Override
public void apply(Project project) {
project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
RuntimeHintsAgentExtension agentExtension = project.getExtensions().create(EXTENSION_NAME,
RuntimeHintsAgentExtension.class, project.getObjects());
RuntimeHintsAgentExtension agentExtension = createRuntimeHintsAgentExtension(project);
Test agentTest = project.getTasks().create(RUNTIMEHINTS_TEST_TASK, Test.class, test -> {
test.useJUnitPlatform(options -> {
options.includeTags("RuntimeHintsTests");
});
test.include("**/*Tests.class", "**/*Test.class");
test.systemProperty("java.awt.headless", "true");
});
project.afterEvaluate(p -> {
Jar jar = project.getRootProject().project("spring-core-test").getTasks().withType(Jar.class).named("jar").get();
agentTest.jvmArgs("-javaagent:" + jar.getArchiveFile().get().getAsFile() + "=" + agentExtension.asJavaAgentArgument());
test.systemProperty("org.graalvm.nativeimage.imagecode", "runtime");
test.getJvmArgumentProviders().add(createRuntimeHintsAgentArgumentProvider(project, agentExtension));
});
project.getTasks().getByName("check", task -> task.dependsOn(agentTest));
project.getDependencies().add(CONFIGURATION_NAME, project.project(":spring-core-test"));
});
}
private static RuntimeHintsAgentExtension createRuntimeHintsAgentExtension(Project project) {
RuntimeHintsAgentExtension agentExtension = project.getExtensions().create(EXTENSION_NAME, RuntimeHintsAgentExtension.class);
agentExtension.getIncludedPackages().convention(Collections.singleton("org.springframework"));
agentExtension.getExcludedPackages().convention(Collections.emptySet());
return agentExtension;
}
private static RuntimeHintsAgentArgumentProvider createRuntimeHintsAgentArgumentProvider(
Project project, RuntimeHintsAgentExtension agentExtension) {
RuntimeHintsAgentArgumentProvider agentArgumentProvider = project.getObjects().newInstance(RuntimeHintsAgentArgumentProvider.class);
agentArgumentProvider.getAgentJar().from(createRuntimeHintsAgentConfiguration(project));
agentArgumentProvider.getIncludedPackages().set(agentExtension.getIncludedPackages());
agentArgumentProvider.getExcludedPackages().set(agentExtension.getExcludedPackages());
return agentArgumentProvider;
}
private static Configuration createRuntimeHintsAgentConfiguration(Project project) {
return project.getConfigurations().create(CONFIGURATION_NAME, configuration -> {
configuration.setCanBeConsumed(false);
configuration.setTransitive(false); // Only the built artifact is required
configuration.attributes(attributes -> {
attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, project.getObjects().named(Bundling.class, Bundling.EXTERNAL));
attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.getObjects().named(Category.class, Category.LIBRARY));
attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.getObjects().named(LibraryElements.class, LibraryElements.JAR));
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, Integer.valueOf(JavaVersion.current().getMajorVersion()));
attributes.attribute(Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, Usage.JAVA_RUNTIME));
});
});
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@ package org.springframework.build.optional;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.tasks.SourceSetContainer;
@@ -40,10 +40,10 @@ public class OptionalDependenciesPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
Configuration optional = project.getConfigurations().create("optional");
Configuration optional = project.getConfigurations().create(OPTIONAL_CONFIGURATION_NAME);
optional.setCanBeConsumed(false);
optional.setCanBeResolved(false);
project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> {
project.getPlugins().withType(JavaBasePlugin.class, (javaBasePlugin) -> {
SourceSetContainer sourceSets = project.getExtensions().getByType(JavaPluginExtension.class)
.getSourceSets();
sourceSets.all((sourceSet) -> {
@@ -53,4 +53,4 @@ public class OptionalDependenciesPlugin implements Plugin<Project> {
});
}
}
}
@@ -1,3 +1,19 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.build.shadow;
import java.io.File;
+2 -1
View File
@@ -6,6 +6,7 @@ RUN ./setup.sh
ENV JAVA_HOME /opt/openjdk/java17
ENV JDK17 /opt/openjdk/java17
ENV JDK20 /opt/openjdk/java20
ENV JDK21 /opt/openjdk/java21
ENV JDK22 /opt/openjdk/java22
ENV PATH $JAVA_HOME/bin:$PATH
+6 -3
View File
@@ -3,10 +3,13 @@ set -e
case "$1" in
java17)
echo "https://github.com/bell-sw/Liberica/releases/download/17.0.9+11/bellsoft-jdk17.0.9+11-linux-amd64.tar.gz"
echo "https://download.bell-sw.com/java/17.0.9+11/bellsoft-jdk17.0.9+11-linux-amd64.tar.gz"
;;
java20)
echo "https://github.com/bell-sw/Liberica/releases/download/20.0.1+10/bellsoft-jdk20.0.1+10-linux-amd64.tar.gz"
java21)
echo "https://download.bell-sw.com/java/21.0.1+12/bellsoft-jdk21.0.1+12-linux-amd64.tar.gz"
;;
java22)
echo "https://download.java.net/java/early_access/jdk22/19/GPL/openjdk-22-ea+19_linux-x64_bin.tar.gz"
;;
*)
echo $"Unknown java version"
+1 -1
View File
@@ -20,7 +20,7 @@ curl https://raw.githubusercontent.com/spring-io/concourse-java-scripts/v0.0.4/c
mkdir -p /opt/openjdk
pushd /opt/openjdk > /dev/null
for jdk in java17 java20
for jdk in java17 java21 java22
do
JDK_URL=$( /get-jdk-url.sh $jdk )
mkdir $jdk
+2 -2
View File
@@ -3,8 +3,8 @@ github-repo-name: "spring-projects/spring-framework"
sonatype-staging-profile: "org.springframework"
docker-hub-organization: "springci"
artifactory-server: "https://repo.spring.io"
branch: "6.0.x"
milestone: "6.0.x"
branch: "main"
milestone: "6.1.x"
build-name: "spring-framework"
pipeline-name: "spring-framework"
concourse-url: "https://ci.spring.io"
+47 -17
View File
@@ -45,7 +45,7 @@ resource_types:
source:
<<: *docker-resource-source
repository: concourse/registry-image-resource
tag: 1.5.0
tag: 1.8.0
- name: artifactory-resource
type: registry-image
source:
@@ -57,7 +57,7 @@ resource_types:
source:
<<: *docker-resource-source
repository: concourse/github-release-resource
tag: 1.5.5
tag: 1.8.0
- name: github-status-resource
type: registry-image
source:
@@ -113,14 +113,22 @@ resources:
access_token: ((github-ci-status-token))
branch: ((branch))
context: build
- name: repo-status-jdk20-build
- name: repo-status-jdk21-build
type: github-status-resource
icon: eye-check-outline
source:
repository: ((github-repo-name))
access_token: ((github-ci-status-token))
branch: ((branch))
context: jdk20-build
context: jdk21-build
- name: repo-status-jdk22-build
type: github-status-resource
icon: eye-check-outline
source:
repository: ((github-repo-name))
access_token: ((github-ci-status-token))
branch: ((branch))
context: jdk22-build
- name: slack-alert
type: slack-notification
icon: slack
@@ -198,26 +206,22 @@ jobs:
threads: 8
artifact_set:
- include:
- "/**/framework-docs-*.zip"
- "/**/framework-api-*.zip"
properties:
"zip.name": "spring-framework"
"zip.displayname": "Spring Framework"
"zip.deployed": "false"
- include:
- "/**/framework-docs-*-docs.zip"
- "/**/framework-api-*-docs.zip"
properties:
"zip.type": "docs"
- include:
- "/**/framework-docs-*-dist.zip"
properties:
"zip.type": "dist"
- include:
- "/**/framework-docs-*-schema.zip"
- "/**/framework-api-*-schema.zip"
properties:
"zip.type": "schema"
get_params:
threads: 8
- name: jdk20-build
- name: jdk21-build
serial: true
public: true
plan:
@@ -225,7 +229,7 @@ jobs:
- get: git-repo
- get: every-morning
trigger: true
- put: repo-status-jdk20-build
- put: repo-status-jdk21-build
params: { state: "pending", commit: "git-repo" }
- do:
- task: check-project
@@ -234,16 +238,42 @@ jobs:
privileged: true
timeout: ((task-timeout))
params:
TEST_TOOLCHAIN: 20
TEST_TOOLCHAIN: 21
<<: *build-project-task-params
on_failure:
do:
- put: repo-status-jdk20-build
- put: repo-status-jdk21-build
params: { state: "failure", commit: "git-repo" }
- put: slack-alert
params:
<<: *slack-fail-params
- put: repo-status-jdk20-build
- put: repo-status-jdk21-build
params: { state: "success", commit: "git-repo" }
- name: jdk22-build
serial: true
public: true
plan:
- get: ci-image
- get: git-repo
- put: repo-status-jdk22-build
params: { state: "pending", commit: "git-repo" }
- do:
- task: check-project
image: ci-image
file: git-repo/ci/tasks/check-project.yml
privileged: true
timeout: ((task-timeout))
params:
TEST_TOOLCHAIN: 22
<<: *build-project-task-params
on_failure:
do:
- put: repo-status-jdk22-build
params: { state: "failure", commit: "git-repo" }
- put: slack-alert
params:
<<: *slack-fail-params
- put: repo-status-jdk22-build
params: { state: "success", commit: "git-repo" }
- name: stage-milestone
serial: true
@@ -396,7 +426,7 @@ jobs:
groups:
- name: "builds"
jobs: ["build", "jdk20-build"]
jobs: ["build", "jdk21-build", "jdk22-build"]
- name: "releases"
jobs: ["stage-milestone", "stage-rc", "stage-release", "promote-milestone", "promote-rc", "promote-release", "create-github-release"]
- name: "ci-images"
+2 -1
View File
@@ -4,5 +4,6 @@ set -e
source $(dirname $0)/common.sh
pushd git-repo > /dev/null
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false --no-daemon --max-workers=4 check
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK21 \
--no-daemon --max-workers=4 check
popd > /dev/null
+2 -1
View File
@@ -5,5 +5,6 @@ source $(dirname $0)/common.sh
repository=$(pwd)/distribution-repository
pushd git-repo > /dev/null
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false --no-daemon --max-workers=4 -PdeploymentRepository=${repository} build publishAllPublicationsToDeploymentRepository
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK21,JDK22 \
--no-daemon --max-workers=4 -PdeploymentRepository=${repository} build publishAllPublicationsToDeploymentRepository
popd > /dev/null
+1 -1
View File
@@ -4,6 +4,6 @@ set -e
source $(dirname $0)/common.sh
pushd git-repo > /dev/null
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK20 \
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK21 \
-PmainToolchain=${MAIN_TOOLCHAIN} -PtestToolchain=${TEST_TOOLCHAIN} --no-daemon --max-workers=4 check antora
popd > /dev/null
+2 -1
View File
@@ -35,7 +35,8 @@ git add gradle.properties > /dev/null
git commit -m"Release v$stageVersion" > /dev/null
git tag -a "v$stageVersion" -m"Release v$stageVersion" > /dev/null
./gradlew --no-daemon --max-workers=4 -PdeploymentRepository=${repository} build publishAllPublicationsToDeploymentRepository
./gradlew --no-daemon --max-workers=4 -PdeploymentRepository=${repository} -Porg.gradle.java.installations.fromEnv=JDK17,JDK21 \
build publishAllPublicationsToDeploymentRepository
git reset --hard HEAD^ > /dev/null
if [[ $nextVersion != $snapshotVersion ]]; then
+1 -1
View File
@@ -4,7 +4,7 @@ image_resource:
type: registry-image
source:
repository: springio/concourse-release-scripts
tag: '0.4.0-SNAPSHOT'
tag: '0.4.0'
username: ((docker-hub-username))
password: ((docker-hub-password))
inputs:
+119
View File
@@ -0,0 +1,119 @@
plugins {
id 'java-platform'
id 'io.freefair.aggregate-javadoc' version '8.3'
}
description = "Spring Framework API Docs"
apply from: "${rootDir}/gradle/publications.gradle"
repositories {
maven {
url "https://repo.spring.io/release"
}
}
dependencies {
moduleProjects.each { moduleProject ->
javadoc moduleProject
}
}
javadoc {
title = "${rootProject.description} ${version} API"
options {
encoding = "UTF-8"
memberLevel = JavadocMemberLevel.PROTECTED
author = true
header = rootProject.description
use = true
overview = "$rootProject.rootDir/framework-docs/src/docs/api/overview.html"
destinationDir = file("${project.buildDir}/docs/javadoc-api")
splitIndex = true
links(rootProject.ext.javadocLinks)
addBooleanOption('Xdoclint:syntax,reference', true) // only check syntax and reference with doclint
addBooleanOption('Werror', true) // fail build on Javadoc warnings
}
maxMemory = "1024m"
doFirst {
classpath += files(
// ensure the javadoc process can resolve types compiled from .aj sources
project(":spring-aspects").sourceSets.main.output
)
classpath += files(moduleProjects.collect { it.sourceSets.main.compileClasspath })
}
}
/**
* Produce KDoc for all Spring Framework modules in "build/docs/kdoc"
*/
rootProject.tasks.dokkaHtmlMultiModule.configure {
dependsOn {
tasks.named("javadoc")
}
moduleName.set("spring-framework")
outputDirectory.set(project.file("$buildDir/docs/kdoc-api"))
includes.from("$rootProject.rootDir/framework-docs/src/docs/api/dokka-overview.md")
}
/**
* Zip all Java docs (javadoc & kdoc) into a single archive
*/
tasks.register('docsZip', Zip) {
dependsOn = ['javadoc', rootProject.tasks.dokkaHtmlMultiModule]
group = "distribution"
description = "Builds -${archiveClassifier} archive containing api and reference " +
"for deployment at https://docs.spring.io/spring-framework/docs/."
archiveBaseName.set("spring-framework")
archiveClassifier.set("docs")
from("src/dist") {
include "changelog.txt"
}
from(javadoc) {
into "javadoc-api"
}
from(rootProject.tasks.dokkaHtmlMultiModule.outputDirectory) {
into "kdoc-api"
}
}
/**
* Zip all Spring Framework schemas into a single archive
*/
tasks.register('schemaZip', Zip) {
group = "distribution"
archiveBaseName.set("spring-framework")
archiveClassifier.set("schema")
description = "Builds -${archiveClassifier} archive containing all " +
"XSDs for deployment at https://springframework.org/schema."
duplicatesStrategy DuplicatesStrategy.EXCLUDE
moduleProjects.each { module ->
def Properties schemas = new Properties();
module.sourceSets.main.resources.find {
(it.path.endsWith("META-INF/spring.schemas") || it.path.endsWith("META-INF\\spring.schemas"))
}?.withInputStream { schemas.load(it) }
for (def key : schemas.keySet()) {
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
assert shortName != key
File xsdFile = module.sourceSets.main.resources.find {
(it.path.endsWith(schemas.get(key)) || it.path.endsWith(schemas.get(key).replaceAll('\\/', '\\\\')))
}
assert xsdFile != null
into(shortName) {
from xsdFile.path
}
}
}
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact docsZip
artifact schemaZip
}
}
}
+4 -166
View File
@@ -6,9 +6,9 @@ plugins {
description = "Spring Framework Docs"
apply from: "${rootDir}/gradle/ide.gradle"
apply from: "${rootDir}/gradle/publications.gradle"
antora {
version = '3.2.0-alpha.2'
playbook = 'cached-antora-playbook.yml'
@@ -34,23 +34,16 @@ antora {
]
}
tasks.named("generateAntoraYml") {
asciidocAttributes = project.provider( {
return ["spring-version": project.version ]
} )
}
tasks.create("generateAntoraResources") {
tasks.register("generateAntoraResources") {
dependsOn 'generateAntoraYml'
}
// Commented out for now:
// https://github.com/spring-projects/spring-framework/issues/30481
// tasks.named("check") {
// dependsOn 'antora'
// }
jar {
enabled = false
}
@@ -67,166 +60,11 @@ repositories {
dependencies {
api(project(":spring-context"))
api(project(":spring-jms"))
api(project(":spring-web"))
api("jakarta.jms:jakarta.jms-api")
api("jakarta.servlet:jakarta.servlet-api")
implementation(project(":spring-core-test"))
implementation("org.assertj:assertj-core")
}
/**
* Produce Javadoc for all Spring Framework modules in "build/docs/javadoc"
*/
task api(type: Javadoc) {
group = "Documentation"
description = "Generates aggregated Javadoc API documentation."
title = "${rootProject.description} ${version} API"
dependsOn {
moduleProjects.collect {
it.tasks.getByName("jar")
}
}
doFirst {
classpath = files(
// ensure the javadoc process can resolve types compiled from .aj sources
project(":spring-aspects").sourceSets.main.output
)
classpath += files(moduleProjects.collect { it.sourceSets.main.compileClasspath })
}
options {
encoding = "UTF-8"
memberLevel = JavadocMemberLevel.PROTECTED
author = true
header = rootProject.description
use = true
overview = "framework-docs/src/docs/api/overview.html"
splitIndex = true
links(project.ext.javadocLinks)
addBooleanOption('Xdoclint:syntax,reference', true) // only check syntax and reference with doclint
addBooleanOption('Werror', true) // fail build on Javadoc warnings
}
source moduleProjects.collect { project ->
project.sourceSets.main.allJava
}
maxMemory = "1024m"
destinationDir = file("$buildDir/docs/javadoc")
}
/**
* Produce KDoc for all Spring Framework modules in "build/docs/kdoc"
*/
rootProject.tasks.dokkaHtmlMultiModule.configure {
dependsOn {
tasks.getByName("api")
}
moduleName.set("spring-framework")
outputDirectory.set(project.file("$buildDir/docs/kdoc"))
}
/**
* Zip all Java docs (javadoc & kdoc) into a single archive
*/
task docsZip(type: Zip, dependsOn: ['api', rootProject.tasks.dokkaHtmlMultiModule]) {
group = "Distribution"
description = "Builds -${archiveClassifier} archive containing api and reference " +
"for deployment at https://docs.spring.io/spring-framework/docs/."
archiveBaseName.set("spring-framework")
archiveClassifier.set("docs")
from("src/dist") {
include "changelog.txt"
}
from (api) {
into "javadoc-api"
}
from (rootProject.tasks.dokkaHtmlMultiModule.outputDirectory) {
into "kdoc-api"
}
}
/**
* Zip all Spring Framework schemas into a single archive
*/
task schemaZip(type: Zip) {
group = "Distribution"
archiveBaseName.set("spring-framework")
archiveClassifier.set("schema")
description = "Builds -${archiveClassifier} archive containing all " +
"XSDs for deployment at https://springframework.org/schema."
duplicatesStrategy DuplicatesStrategy.EXCLUDE
moduleProjects.each { module ->
def Properties schemas = new Properties();
module.sourceSets.main.resources.find {
(it.path.endsWith("META-INF/spring.schemas") || it.path.endsWith("META-INF\\spring.schemas"))
}?.withInputStream { schemas.load(it) }
for (def key : schemas.keySet()) {
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
assert shortName != key
File xsdFile = module.sourceSets.main.resources.find {
(it.path.endsWith(schemas.get(key)) || it.path.endsWith(schemas.get(key).replaceAll('\\/','\\\\')))
}
assert xsdFile != null
into (shortName) {
from xsdFile.path
}
}
}
}
/**
* Create a distribution zip with everything:
* docs, schemas, jars, source jars, javadoc jars
*/
task distZip(type: Zip, dependsOn: [docsZip, schemaZip]) {
group = "Distribution"
archiveBaseName.set("spring-framework")
archiveClassifier.set("dist")
description = "Builds -${archiveClassifier} archive, containing all jars and docs, " +
"suitable for community download page."
ext.baseDir = "spring-framework-${project.version}";
from("src/docs/dist") {
include "readme.txt"
include "license.txt"
include "notice.txt"
into "${baseDir}"
expand(copyright: new Date().format("yyyy"), version: project.version)
}
from(zipTree(docsZip.archiveFile)) {
into "${baseDir}/docs"
}
from(zipTree(schemaZip.archiveFile)) {
into "${baseDir}/schema"
}
moduleProjects.each { module ->
into ("${baseDir}/libs") {
from module.jar
if (module.tasks.findByPath("sourcesJar")) {
from module.sourcesJar
}
if (module.tasks.findByPath("javadocJar")) {
from module.javadocJar
}
}
}
}
distZip.mustRunAfter moduleProjects.check
publishing {
publications {
mavenJava(MavenPublication) {
artifact docsZip
artifact schemaZip
artifact distZip
}
}
}
+7
View File
@@ -122,6 +122,7 @@
**** 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[]
@@ -130,6 +131,7 @@
**** xref:testing/testcontext-framework/ctx-management/web.adoc[]
**** xref:testing/testcontext-framework/ctx-management/web-mocks.adoc[]
**** xref:testing/testcontext-framework/ctx-management/caching.adoc[]
**** xref:testing/testcontext-framework/ctx-management/failure-threshold.adoc[]
**** xref:testing/testcontext-framework/ctx-management/hierarchies.adoc[]
*** xref:testing/testcontext-framework/fixture-di.adoc[]
*** xref:testing/testcontext-framework/web-scoped-beans.adoc[]
@@ -165,6 +167,7 @@
***** 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[]
@@ -179,6 +182,7 @@
***** 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[]
@@ -266,6 +270,7 @@
***** xref:web/webmvc/mvc-controller/ann-methods/jackson.adoc[]
**** xref:web/webmvc/mvc-controller/ann-modelattrib-methods.adoc[]
**** xref:web/webmvc/mvc-controller/ann-initbinder.adoc[]
**** xref:web/webmvc/mvc-controller/ann-validation.adoc[]
**** xref:web/webmvc/mvc-controller/ann-exceptionhandler.adoc[]
**** xref:web/webmvc/mvc-controller/ann-advice.adoc[]
*** xref:web/webmvc-functional.adoc[]
@@ -360,6 +365,7 @@
***** xref:web/webflux/controller/ann-methods/jackson.adoc[]
**** xref:web/webflux/controller/ann-modelattrib-methods.adoc[]
**** xref:web/webflux/controller/ann-initbinder.adoc[]
**** xref:web/webflux/controller/ann-validation.adoc[]
**** xref:web/webflux/controller/ann-exceptions.adoc[]
**** xref:web/webflux/controller/ann-advice.adoc[]
*** xref:web/webflux-functional.adoc[]
@@ -414,6 +420,7 @@
*** xref:integration/cache/plug.adoc[]
*** xref:integration/cache/specific-config.adoc[]
** xref:integration/observability.adoc[]
** xref:integration/checkpoint-restore.adoc[]
** xref:integration/appendix.adoc[]
* xref:languages.adoc[]
** xref:languages/kotlin.adoc[]
@@ -39,11 +39,6 @@ resolvable otherwise. See
{api-spring-framework}++/core/env/AbstractEnvironment.html#IGNORE_GETENV_PROPERTY_NAME++[`AbstractEnvironment`]
for details.
| `spring.index.ignore`
| Instructs Spring to ignore the components index located in
`META-INF/spring.components`. See xref:core/beans/classpath-scanning.adoc#beans-scanning-index[Generating an Index of Candidate Components]
.
| `spring.jdbc.getParameterType.ignore`
| Instructs Spring to ignore `java.sql.ParameterMetaData.getParameterType` completely.
See the note in xref:data-access/jdbc/advanced.adoc#jdbc-batch-list[Batch Operations with a List of Objects].
@@ -60,19 +55,27 @@ for details.
{api-spring-framework}++/objenesis/SpringObjenesis.html#IGNORE_OBJENESIS_PROPERTY_NAME++[`SpringObjenesis`]
for details.
| `spring.test.aot.processing.failOnError`
| A boolean flag that controls whether errors encountered during AOT processing in the
_Spring TestContext Framework_ should result in an exception that fails the overall process.
See xref:testing/testcontext-framework/aot.adoc[Ahead of Time Support for Tests].
| `spring.test.constructor.autowire.mode`
| The default _test constructor autowire mode_ to use if `@TestConstructor` is not present
on a test class. See xref:testing/annotations/integration-junit-jupiter.adoc#integration-testing-annotations-testconstructor[Changing the default test constructor autowire mode]
.
on a test class. See xref:testing/annotations/integration-junit-jupiter.adoc#integration-testing-annotations-testconstructor[Changing the default test constructor autowire mode].
| `spring.test.context.cache.maxSize`
| The maximum size of the context cache in the _Spring TestContext Framework_. See
xref:testing/testcontext-framework/ctx-management/caching.adoc[Context Caching].
| `spring.test.context.failure.threshold`
| The failure threshold for errors encountered while attempting to load an `ApplicationContext`
in the _Spring TestContext Framework_. See
xref:testing/testcontext-framework/ctx-management/failure-threshold.adoc[Context Failure Threshold].
| `spring.test.enclosing.configuration`
| The default _enclosing configuration inheritance mode_ to use if
`@NestedTestConfiguration` is not present on a test class. See
xref:testing/annotations/integration-junit-jupiter.adoc#integration-testing-annotations-nestedtestconfiguration[Changing the default enclosing configuration inheritance mode]
.
xref:testing/annotations/integration-junit-jupiter.adoc#integration-testing-annotations-nestedtestconfiguration[Changing the default enclosing configuration inheritance mode].
|===
@@ -728,11 +728,6 @@ of determining parameter names, an exception will be thrown.
`StandardReflectionParameterNameDiscoverer` :: Uses the standard `java.lang.reflect.Parameter`
API to determine parameter names. Requires that code be compiled with the `-parameters`
flag for `javac`. Recommended approach on Java 8+.
`LocalVariableTableParameterNameDiscoverer` :: Analyzes the local variable table available
in the byte code of the advice class to determine parameter names from debug information.
Requires that code be compiled with debug symbols (`-g:vars` at a minimum). Deprecated
as of Spring Framework 6.0 for removal in Spring Framework 6.1 in favor of compiling
code with `-parameters`. Not supported in a GraalVM native image.
`AspectJAdviceParameterNameDiscoverer` :: Deduces parameter names from the pointcut
expression, `returning`, and `throwing` clauses. See the
{api-spring-framework}/aop/aspectj/AspectJAdviceParameterNameDiscoverer.html[javadoc]
@@ -31,7 +31,7 @@ However, it would be even more confusing if Spring used its own terminology.
the "advised object". Since Spring AOP is implemented by using runtime proxies, this
object is always a proxied object.
* AOP proxy: An object created by the AOP framework in order to implement the aspect
contracts (advise method executions and so on). In the Spring Framework, an AOP proxy
contracts (advice method executions and so on). In the Spring Framework, an AOP proxy
is a JDK dynamic proxy or a CGLIB proxy.
* Weaving: linking aspects with other application types or objects to create an
advised object. This can be done at compile time (using the AspectJ compiler, for
@@ -256,6 +256,13 @@ Java::
If you are registering bean definitions programmatically, consider using `RootBeanBefinition` as it allows to specify a `ResolvableType` that handles generics.
[[aot.bestpractices.constructors]]
=== Avoid Multiple Constructors
The container is able to choose the most appropriate constructor to use based on several candidates.
However, this is not a best practice and flagging the preferred constructor with `@Autowired` if necessary is preferred.
In case you are working on a code base that you can't modify, you can set the {api-spring-framework}/beans/factory/support/AbstractBeanDefinition.html#PREFERRED_CONSTRUCTORS_ATTRIBUTE[`preferredConstructors` attribute] on the related bean definition to indicate which constructor should be used.
[[aot.bestpractices.factory-bean]]
=== FactoryBean
@@ -27,7 +27,7 @@ use these features.
== `@Component` and Further Stereotype Annotations
The `@Repository` annotation is a marker for any class that fulfills the role or
stereotype of a repository (also known as Data Access Object or DAO). Among the uses
_stereotype_ of a repository (also known as Data Access Object or DAO). Among the uses
of this marker is the automatic translation of exceptions, as described in
xref:data-access/orm/general.adoc#orm-exception-translation[Exception Translation].
@@ -39,7 +39,7 @@ layers, respectively). Therefore, you can annotate your component classes with
`@Component`, but, by annotating them with `@Repository`, `@Service`, or `@Controller`
instead, your classes are more properly suited for processing by tools or associating
with aspects. For example, these stereotype annotations make ideal targets for
pointcuts. `@Repository`, `@Service`, and `@Controller` can also
pointcuts. `@Repository`, `@Service`, and `@Controller` may also
carry additional semantics in future releases of the Spring Framework. Thus, if you are
choosing between using `@Component` or `@Service` for your service layer, `@Service` is
clearly the better choice. Similarly, as stated earlier, `@Repository` is already
@@ -664,15 +664,36 @@ analogous to how the container selects between multiple `@Autowired` constructor
== Naming Autodetected Components
When a component is autodetected as part of the scanning process, its bean name is
generated by the `BeanNameGenerator` strategy known to that scanner. By default, any
Spring stereotype annotation (`@Component`, `@Repository`, `@Service`, and
`@Controller`) that contains a name `value` thereby provides that name to the
corresponding bean definition.
generated by the `BeanNameGenerator` strategy known to that scanner.
If such an annotation contains no name `value` or for any other detected component
(such as those discovered by custom filters), the default bean name generator returns
the uncapitalized non-qualified class name. For example, if the following component
classes were detected, the names would be `myMovieLister` and `movieFinderImpl`:
By default, the `AnnotationBeanNameGenerator` is used. For Spring
xref:core/beans/classpath-scanning.adoc#beans-stereotype-annotations[stereotype annotations],
if you supply a name via the annotation's `value` attribute that name will be used as
the name in the corresponding bean definition. This convention also applies when the
following JSR-250 and JSR-330 annotations are used instead of Spring stereotype
annotations: `@jakarta.annotation.ManagedBean`, `@javax.annotation.ManagedBean`,
`@jakarta.inject.Named`, and `@javax.inject.Named`.
As of Spring Framework 6.1, the name of the annotation attribute that is used to specify
the bean name is no longer required to be `value`. Custom stereotype annotations can
declare an attribute with a different name (such as `name`) and annotate that attribute
with `@AliasFor(annotation = Component.class, attribute = "value")`. See the source code
declaration of `ControllerAdvice#name()` for a concrete example.
[WARNING]
====
As of Spring Framework 6.1, support for convention-based stereotype names is deprecated
and will be removed in a future version of the framework. Consequently, custom stereotype
annotations must use `@AliasFor` to declare an explicit alias for the `value` attribute
in `@Component`. See the source code declaration of `Repository#value()` and
`ControllerAdvice#name()` for concrete examples.
====
If an explicit bean name cannot be derived from such an annotation or for any other
detected component (such as those discovered by custom filters), the default bean name
generator returns the uncapitalized non-qualified class name. For example, if the
following component classes were detected, the names would be `myMovieLister` and
`movieFinderImpl`.
[tabs]
======
@@ -989,68 +1010,4 @@ metadata is provided per-instance rather than per-class.
[[beans-scanning-index]]
== Generating an Index of Candidate Components
While classpath scanning is very fast, it is possible to improve the startup performance
of large applications by creating a static list of candidates at compilation time. In this
mode, all modules that are targets of component scanning must use this mechanism.
NOTE: Your existing `@ComponentScan` or `<context:component-scan/>` directives must remain
unchanged to request the context to scan candidates in certain packages. When the
`ApplicationContext` detects such an index, it automatically uses it rather than scanning
the classpath.
To generate the index, add an additional dependency to each module that contains
components that are targets for component scan directives. The following example shows
how to do so with Maven:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-indexer</artifactId>
<version>{spring-version}</version>
<optional>true</optional>
</dependency>
</dependencies>
----
With Gradle 4.5 and earlier, the dependency should be declared in the `compileOnly`
configuration, as shown in the following example:
[source,groovy,indent=0,subs="verbatim,quotes,attributes"]
----
dependencies {
compileOnly "org.springframework:spring-context-indexer:{spring-version}"
}
----
With Gradle 4.6 and later, the dependency should be declared in the `annotationProcessor`
configuration, as shown in the following example:
[source,groovy,indent=0,subs="verbatim,quotes,attributes"]
----
dependencies {
annotationProcessor "org.springframework:spring-context-indexer:{spring-version}"
}
----
The `spring-context-indexer` artifact generates a `META-INF/spring.components` file that
is included in the jar file.
NOTE: When working with this mode in your IDE, the `spring-context-indexer` must be
registered as an annotation processor to make sure the index is up-to-date when
candidate components are updated.
TIP: The index is enabled automatically when a `META-INF/spring.components` file is found
on the classpath. If an index is partially available for some libraries (or use cases)
but could not be built for the whole application, you can fall back to a regular classpath
arrangement (as though no index were present at all) by setting `spring.index.ignore` to
`true`, either as a JVM system property or via the
xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism.
@@ -478,20 +478,21 @@ Kotlin::
----
======
Notice that `ApplicationListener` is generically parameterized with the type of your
custom event (`BlockedListEvent` in the preceding example). This means that the
`onApplicationEvent()` method can remain type-safe, avoiding any need for downcasting.
You can register as many event listeners as you wish, but note that, by default, event
listeners receive events synchronously. 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, see the javadoc for Spring's
{api-spring-framework}/context/event/ApplicationEventMulticaster.html[`ApplicationEventMulticaster`] interface
and {api-spring-framework}/context/event/SimpleApplicationEventMulticaster.html[`SimpleApplicationEventMulticaster`]
implementation for configuration options which can be applied to a custom
"applicationEventMulticaster" bean definition.
Notice that `ApplicationListener` is generically parameterized with the type of your custom event (`BlockedListEvent` in the preceding example).
This means that the `onApplicationEvent()` method can remain type-safe, avoiding any need for downcasting.
You can register as many event listeners as you wish, but note that, by default, event listeners receive events synchronously.
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,
see the javadoc for Spring's {api-spring-framework}/context/event/ApplicationEventMulticaster.html[`ApplicationEventMulticaster`] interface
and {api-spring-framework}/context/event/SimpleApplicationEventMulticaster.html[`SimpleApplicationEventMulticaster`] implementation
for configuration options which can be applied to a custom "applicationEventMulticaster" bean definition.
In these cases, ThreadLocals and logging context are not propagated for the event processing.
See xref:integration/observability.adoc#observability.application-events[the `@EventListener` Observability section]
for more information on Observability concerns.
The following example shows the bean definitions used to register and configure each of
the classes above:
@@ -747,6 +748,9 @@ Be aware of the following limitations when using asynchronous events:
value. If you need to publish another event as the result of the processing, inject an
{api-spring-framework}/context/ApplicationEventPublisher.html[`ApplicationEventPublisher`]
to publish the event manually.
* ThreadLocals and logging context are not propagated by default for the event processing.
See xref:integration/observability.adoc#observability.application-events[the `@EventListener` Observability section]
for more information on Observability concerns.
[[context-functionality-events-order]]
@@ -772,11 +772,9 @@ resolved to the corresponding value. If not, then `default/path` is used
as a default. If no default is specified and a property cannot be resolved, an
`IllegalArgumentException` is thrown.
NOTE: The `@PropertySource` annotation is repeatable, according to Java 8 conventions.
However, all such `@PropertySource` annotations need to be declared at the same
level, either directly on the configuration class or as meta-annotations within the
same custom annotation. Mixing direct annotations and meta-annotations is not
recommended, since direct annotations effectively override meta-annotations.
NOTE: `@PropertySource` can be used as a repeatable annotation. `@PropertySource`
may also be used as a meta-annotation to create custom composed annotations with
attribute overrides.
@@ -59,7 +59,7 @@ The preceding `AppConfig` class is equivalent to the following Spring `<beans/>`
****
When `@Bean` methods are declared within classes that are not annotated with
`@Configuration`, they are referred to as being processed in a "`lite`" mode. Bean methods
declared in a `@Component` or even in a plain old class are considered to be "`lite`",
declared on a bean that is not annotated with `@Configuration` are considered to be "`lite`",
with a different primary purpose of the containing class and a `@Bean` method
being a sort of bonus there. For example, service components may expose management views
to the container through an additional `@Bean` method on each applicable component class.
@@ -46,7 +46,9 @@ The expression language supports the following functionality:
* Inline maps
* Ternary operator
* Variables
* User-defined functions
* User-defined functions added to the context
* reflective invocation of `Method`
* various cases of `MethodHandle`
* Collection projection
* Collection selection
* Templated expressions
@@ -15,7 +15,7 @@ topics:
* xref:core/expressions/language-ref/types.adoc[Types]
* xref:core/expressions/language-ref/constructors.adoc[Constructors]
* xref:core/expressions/language-ref/variables.adoc[Variables]
* xref:core/expressions/language-ref/functions.adoc[Functions]
* xref:core/expressions/language-ref/functions.adoc[User-Defined Functions]
* xref:core/expressions/language-ref/bean-references.adoc[Bean References]
* xref:core/expressions/language-ref/operator-ternary.adoc[Ternary Operator (If-Then-Else)]
* xref:core/expressions/language-ref/operator-elvis.adoc[The Elvis Operator]
@@ -3,7 +3,8 @@
You can extend SpEL by registering user-defined functions that can be called within the
expression string. The function is registered through the `EvaluationContext`. The
following example shows how to register a user-defined function:
following example shows how to register a user-defined function to be invoked via reflection
(i.e. a `Method`):
[tabs]
======
@@ -94,5 +95,97 @@ Kotlin::
----
======
The use of `MethodHandle` is also supported. This enables potentially more efficient use
cases if the `MethodHandle` target and parameters have been fully bound prior to
registration, but partially bound handles are also supported.
Consider the `String#formatted(String, Object...)` instance method, which produces a
message according to a template and a variable number of arguments.
You can register and use the `formatted` method as a `MethodHandle`, as the following
example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
MethodHandle mh = MethodHandles.lookup().findVirtual(String.class, "formatted",
MethodType.methodType(String.class, Object[].class));
context.setVariable("message", mh);
String message = parser.parseExpression("#message('Simple message: <%s>', 'Hello World', 'ignored')")
.getValue(context, String.class);
//returns "Simple message: <Hello World>"
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
val mh = MethodHandles.lookup().findVirtual(String::class.java, "formatted",
MethodType.methodType(String::class.java, Array<Any>::class.java))
context.setVariable("message", mh)
val message = parser.parseExpression("#message('Simple message: <%s>', 'Hello World', 'ignored')")
.getValue(context, String::class.java)
----
======
As hinted above, binding a `MethodHandle` and registering the bound `MethodHandle` is also
supported. This is likely to be more performant if both the target and all the arguments
are bound. In that case no arguments are necessary in the SpEL expression, as the
following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
String template = "This is a %s message with %s words: <%s>";
Object varargs = new Object[] { "prerecorded", 3, "Oh Hello World!", "ignored" };
MethodHandle mh = MethodHandles.lookup().findVirtual(String.class, "formatted",
MethodType.methodType(String.class, Object[].class))
.bindTo(template)
.bindTo(varargs); //here we have to provide arguments in a single array binding
context.setVariable("message", mh);
String message = parser.parseExpression("#message()")
.getValue(context, String.class);
//returns "This is a prerecorded message with 3 words: <Oh Hello World!>"
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
val template = "This is a %s message with %s words: <%s>"
val varargs = arrayOf("prerecorded", 3, "Oh Hello World!", "ignored")
val mh = MethodHandles.lookup().findVirtual(String::class.java, "formatted",
MethodType.methodType(String::class.java, Array<Any>::class.java))
.bindTo(template)
.bindTo(varargs) //here we have to provide arguments in a single array binding
context.setVariable("message", mh)
val message = parser.parseExpression("#message()")
.getValue(context, String::class.java)
----
======
@@ -38,6 +38,10 @@ Kotlin::
----
======
NOTE: The SpEL Elvis operator also checks for _empty_ Strings in addition to `null` objects.
The original snippet is thus only close to emulating the semantics of the operator (it would need an
additional `!name.isEmpty()` check).
The following listing shows a more complex example:
[tabs]
@@ -53,7 +57,7 @@ Java::
String name = parser.parseExpression("name?:'Elvis Presley'").getValue(context, tesla, String.class);
System.out.println(name); // Nikola Tesla
tesla.setName(null);
tesla.setName("");
name = parser.parseExpression("name?:'Elvis Presley'").getValue(context, tesla, String.class);
System.out.println(name); // Elvis Presley
----
@@ -69,7 +73,7 @@ Kotlin::
var name = parser.parseExpression("name?:'Elvis Presley'").getValue(context, tesla, String::class.java)
println(name) // Nikola Tesla
tesla.setName(null)
tesla.setName("")
name = parser.parseExpression("name?:'Elvis Presley'").getValue(context, tesla, String::class.java)
println(name) // Elvis Presley
----
@@ -1,5 +1,50 @@
[[beans-binding]]
= Data Binding
Data binding is useful for binding user input to a target object where user input is a map
with property paths as keys, following xref:beans-beans-conventions[JavaBeans conventions].
`DataBinder` is the main class that supports this, and it provides two ways to bind user
input:
- xref:beans-constructor-binding[Constructor binding] - bind user input to a public data
constructor, looking up constructor argument values in the user input.
- xref:beans-beans[Property binding] - bind user input to setters, matching keys from the
user input to properties of the target object structure.
You can apply both constructor and property binding or only one.
[[beans-constructor-binding]]
== Constructor Binding
To use constructor binding:
1. Create a `DataBinder` with `null` as the target object.
2. Set `targetType` to the target class.
3. Call `construct`.
The target class should have a single public constructor or a single non-public constructor
with arguments. If there are multiple constructors, then a default constructor if present
is used.
By default, constructor parameter names are used to look up argument values, but you can
configure a `NameResolver`. Spring MVC and WebFlux both rely to allow customizing the name
of the value to bind through an `@BindParam` annotation on constructor parameters.
xref:beans-beans-conventions[Type conversion] is applied as needed to convert user input.
If the constructor parameter is an object, it is constructed recursively in the same
manner, but through a nested property path. That means constructor binding creates both
the target object and any objects it contains.
Binding and conversion errors are reflected in the `BindingResult` of the `DataBinder`.
If the target is created successfully, then `target` is set to the created instance
after the call to `construct`.
[[beans-beans]]
= Bean Manipulation and the `BeanWrapper`
== Property Binding with `BeanWrapper`
The `org.springframework.beans` package adheres to the JavaBeans standard.
A JavaBean is a class with a default no-argument constructor and that follows
@@ -26,7 +71,7 @@ perform actions on that bean, such as setting and retrieving properties.
[[beans-beans-conventions]]
== Setting and Getting Basic and Nested Properties
=== Setting and Getting Basic and Nested Properties
Setting and getting properties is done through the `setPropertyValue` and
`getPropertyValue` overloaded method variants of `BeanWrapper`. See their Javadoc for
@@ -192,7 +237,7 @@ Kotlin::
[[beans-beans-conversion]]
== Built-in `PropertyEditor` Implementations
== ``PropertyEditor``'s
Spring uses the concept of a `PropertyEditor` to effect the conversion between an
`Object` and a `String`. It can be handy
@@ -378,7 +423,7 @@ Kotlin::
[[beans-beans-conversion-customeditor-registration]]
=== Registering Additional Custom `PropertyEditor` Implementations
=== Custom ``PropertyEditor``'s
When setting bean properties as string values, a Spring IoC container ultimately uses
standard JavaBeans `PropertyEditor` implementations to convert these strings to the complex type of the
@@ -521,7 +566,7 @@ Finally, the following example shows how to use `CustomEditorConfigurer` to regi
----
[[beans-beans-conversion-customeditor-registration-per]]
==== Using `PropertyEditorRegistrar`
=== `PropertyEditorRegistrar`
Another mechanism for registering property editors with the Spring container is to
create and use a `PropertyEditorRegistrar`. This interface is particularly useful when
@@ -123,15 +123,12 @@ Validator, is expected to be present in the classpath and is automatically detec
[[validation-beanvalidation-spring-inject]]
=== Injecting a Validator
=== Inject Jakarta Validator
`LocalValidatorFactoryBean` implements both `jakarta.validation.ValidatorFactory` and
`jakarta.validation.Validator`, as well as Spring's `org.springframework.validation.Validator`.
You can inject a reference to either of these interfaces into beans that need to invoke
validation logic.
You can inject a reference to `jakarta.validation.Validator` if you prefer to work with the Bean
Validation API directly, as the following example shows:
`jakarta.validation.Validator`, so you can inject a reference to the latter to
apply validation logic if you prefer to work with the Bean Validation API directly,
as the following example shows:
[tabs]
======
@@ -160,8 +157,15 @@ Kotlin::
----
======
You can inject a reference to `org.springframework.validation.Validator` if your bean
requires the Spring Validation API, as the following example shows:
[[validation-beanvalidation-spring-inject-adapter]]
=== Inject Spring Validator
In addition to implementing `jakarta.validation.Validator`, `LocalValidatorFactoryBean`
also adapts to `org.springframework.validation.Validator`, so you can inject a reference
to the latter if your bean requires the Spring Validation API.
For example:
[tabs]
======
@@ -190,9 +194,15 @@ Kotlin::
----
======
When used as `org.springframework.validation.Validator`, `LocalValidatorFactoryBean`
invokes the underlying `jakarta.validation.Validator`, and then adapts
``ContraintViolation``s to ``FieldError``s, and registers them with the `Errors` object
passed into the `validate` method.
[[validation-beanvalidation-spring-constraints]]
=== Configuring Custom Constraints
=== Configure Custom Constraints
Each bean validation constraint consists of two parts:
@@ -272,11 +282,10 @@ As the preceding example shows, a `ConstraintValidator` implementation can have
[[validation-beanvalidation-spring-method]]
=== Spring-driven Method Validation
== Spring-driven Method Validation
You can integrate the method validation feature supported by Bean Validation 1.1 (and, as
a custom extension, also by Hibernate Validator 4.3) into a Spring context through a
`MethodValidationPostProcessor` bean definition:
You can integrate the method validation feature of Bean Validation into a
Spring context through a `MethodValidationPostProcessor` bean definition:
[tabs]
======
@@ -305,11 +314,11 @@ XML::
----
======
To be eligible for Spring-driven method validation, all target classes need to be annotated
To be eligible for Spring-driven method validation, target classes need to be annotated
with Spring's `@Validated` annotation, which can optionally also declare the validation
groups to use. See
{api-spring-framework}/validation/beanvalidation/MethodValidationPostProcessor.html[`MethodValidationPostProcessor`]
for setup details with the Hibernate Validator and Bean Validation 1.1 providers.
for setup details with the Hibernate Validator and Bean Validation providers.
[TIP]
====
@@ -320,8 +329,142 @@ xref:core/aop/proxying.adoc#aop-understanding-aop-proxies[Understanding AOP Prox
to always use methods and accessors on proxied classes; direct field access will not work.
====
Spring MVC and WebFlux have built-in support for the same underlying method validation but without
the need for AOP. Therefore, do check the rest of this section, and also see the Spring MVC
xref:web/webmvc/mvc-controller/ann-validation.adoc[Validation] and
xref:web/webmvc/mvc-ann-rest-exceptions.adoc[Error Responses] sections, and the WebFlux
xref:web/webflux/controller/ann-validation.adoc[Validation] and
xref:web/webflux/ann-rest-exceptions.adoc[Error Responses] sections.
[[validation-beanvalidation-spring-method-exceptions]]
=== Method Validation Exceptions
By default, `jakarta.validation.ConstraintViolationException` is raised with the set of
``ConstraintViolation``s returned by `jakarata.validation.Validator`. As an alternative,
you can have `MethodValidationException` raised instead with ``ConstraintViolation``s
adapted to `MessageSourceResolvable` errors. To enable set the following flag:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
@Configuration
public class AppConfig {
@Bean
public MethodValidationPostProcessor validationPostProcessor() {
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
processor.setAdaptConstraintViolations(true);
return processor;
}
}
----
XML::
+
[source,xml,indent=0,subs="verbatim,quotes",role="secondary"]
----
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
<property name="adaptConstraintViolations" value="true"/>
</bean>
----
======
`MethodValidationException` contains a list of ``ParameterValidationResult``s which
group errors by method parameter, and each exposes a `MethodParameter`, the argument
value, and a list of `MessageSourceResolvable` errors adapted from
``ConstraintViolation``s. For `@Valid` method parameters with cascaded violations on
fields and properties, the `ParameterValidationResult` is `ParameterErrors` which
implements `org.springframework.validation.Errors` and exposes validation errors as
``FieldError``s.
[[validation-beanvalidation-spring-method-i18n]]
=== Customizing Validation Errors
The adapted `MessageSourceResolvable` errors can be turned into error messages to
display to users through the configured `MessageSource` with locale and language specific
resource bundles. This section provides an example for illustration.
Given the following class declarations:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
record Person(@Size(min = 1, max = 10) String name) {
}
@Validated
public class MyService {
void addStudent(@Valid Person person, @Max(2) int degrees) {
// ...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@JvmRecord
internal data class Person(@Size(min = 1, max = 10) val name: String)
@Validated
class MyService {
fun addStudent(person: @Valid Person?, degrees: @Max(2) Int) {
// ...
}
}
----
======
A `ConstraintViolation` on `Person.name()` is adapted to a `FieldErrro` with the following:
- Error codes `"Size.student.name"`, `"Size.name"`, `"Size.java.lang.String"`, and `"Size"`
- Message arguments `"name"`, `10`, and `1` (the field name and the constraint attributes)
- Default message "size must be between 1 and 10"
To customize the default message, you can add properties to
xref:core/beans/context-introduction.adoc#context-functionality-messagesource[MessageSource]
resource bundles using any of the above errors codes and message arguments. Note also that the
message argument `"name"` is itself a `MessagreSourceResolvable` with error codes
`"student.name"` and `"name"` and can customized too. For example:
Properties::
+
[source,properties,indent=0,subs="verbatim,quotes",role="secondary"]
----
Size.student.name=Please, provide a {0} that is between {2} and {1} characters long
student.name=username
----
A `ConstraintViolation` on the `degrees` method parameter is adapted to a
`MessageSourceResolvable` with the following:
- Error codes `"Max.myService#addStudent.degrees"`, `"Max.degrees"`, `"Max.int"`, `"Max"`
- Message arguments "degrees2 and 2 (the field name and the constraint attribute)
- Default message "must be less than or equal to 2"
To customize the above default message, you can add a property such as:
Properties::
+
[source,properties,indent=0,subs="verbatim,quotes",role="secondary"]
----
Max.degrees=You cannot provide more than {1} {0}
----
[[validation-beanvalidation-spring-other]]
=== Additional Configuration Options
@@ -195,6 +195,12 @@ of Spring Web MVC, you can use the `<spring:bind/>` tag to inspect the error mes
you can also inspect the `Errors` object yourself. More information about the
methods it offers can be found in the {api-spring-framework}/validation/Errors.html[javadoc].
Validators may also get locally invoked for the immediate validation of a given object,
not involving a binding process. As of 6.1, this has been simplified through a new
`Validator.validateObject(Object)` method which is available by default now, returning
a simple ´Errors` representation which can be inspected: typically calling `hasErrors()`
or the new `failOnError` method for turning the error summary message into an exception
(e.g. `validator.validateObject(myObject).failOnError(IllegalArgumentException::new)`).
@@ -2,30 +2,26 @@
= Choosing an Approach for JDBC Database Access
You can choose among several approaches to form the basis for your JDBC database access.
In addition to three flavors of `JdbcTemplate`, a new `SimpleJdbcInsert` and
`SimpleJdbcCall` approach optimizes database metadata, and the RDBMS Object style takes a
more object-oriented approach similar to that of JDO Query design. Once you start using
one of these approaches, you can still mix and match to include a feature from a
different approach. All approaches require a JDBC 2.0-compliant driver, and some
advanced features require a JDBC 3.0 driver.
In addition to three flavors of `JdbcTemplate`, a `SimpleJdbcInsert` and `SimpleJdbcCall`
approach optimizes database metadata, and the RDBMS Object style results in a more
object-oriented approach. Once you start using one of these approaches, you can still mix
and match to include a feature from a different approach.
* `JdbcTemplate` is the classic and most popular Spring JDBC approach. This
"`lowest-level`" approach and all others use a JdbcTemplate under the covers.
"`lowest-level`" approach and all others use a `JdbcTemplate` under the covers.
* `NamedParameterJdbcTemplate` wraps a `JdbcTemplate` to provide named parameters
instead of the traditional JDBC `?` placeholders. This approach provides better
documentation and ease of use when you have multiple parameters for an SQL statement.
* `SimpleJdbcInsert` and `SimpleJdbcCall` optimize database metadata to limit the amount
of necessary configuration. This approach simplifies coding so that you need to
provide only the name of the table or procedure and provide a map of parameters matching
the column names. This works only if the database provides adequate metadata. If the
database does not provide this metadata, you have to provide explicit
configuration of the parameters.
of necessary configuration. This approach simplifies coding so that you only need to
provide the name of the table or procedure and a map of parameters matching the column
names. This works only if the database provides adequate metadata. If the database does
not provide this metadata, you have to provide explicit configuration of the parameters.
* RDBMS objects — including `MappingSqlQuery`, `SqlUpdate`, and `StoredProcedure` —
require you to create reusable and thread-safe objects during initialization of your
data-access layer. This approach is modeled after JDO Query, wherein you define your
query string, declare parameters, and compile the query. Once you do that,
`execute(...)`, `update(...)`, and `findObject(...)` methods can be called multiple
times with various parameter values.
data-access layer. This approach allows you to define your query string, declare
parameters, and compile the query. Once you do that, `execute(...)`, `update(...)`, and
`findObject(...)` methods can be called multiple times with various parameter values.
@@ -6,6 +6,7 @@ including error handling. It includes the following topics:
* xref:data-access/jdbc/core.adoc#jdbc-JdbcTemplate[Using `JdbcTemplate`]
* xref:data-access/jdbc/core.adoc#jdbc-NamedParameterJdbcTemplate[Using `NamedParameterJdbcTemplate`]
* xref:data-access/jdbc/core.adoc#jdbc-JdbcClient[Unified JDBC Query/Update Operations: `JdbcClient`]
* xref:data-access/jdbc/core.adoc#jdbc-SQLExceptionTranslator[Using `SQLExceptionTranslator`]
* xref:data-access/jdbc/core.adoc#jdbc-statements-executing[Running Statements]
* xref:data-access/jdbc/core.adoc#jdbc-statements-querying[Running Queries]
@@ -701,6 +702,120 @@ See also xref:data-access/jdbc/core.adoc#jdbc-JdbcTemplate-idioms[`JdbcTemplate`
for guidelines on using the `NamedParameterJdbcTemplate` class in the context of an application.
[[jdbc-JdbcClient]]
== Unified JDBC Query/Update Operations: `JdbcClient`
As of 6.1, the named parameter statements of `NamedParameterJdbcTemplate` and the positional
parameter statements of a regular `JdbcTemplate` are available through a unified client API
with a fluent interaction model.
For example, with positional parameters:
[source,java,indent=0,subs="verbatim,quotes"]
----
private JdbcClient jdbcClient = JdbcClient.create(dataSource);
public int countOfActorsByFirstName(String firstName) {
return this.jdbcClient.sql("select count(*) from t_actor where first_name = ?")
.param(firstName);
.query(Integer.class).single();
}
----
For example, with named parameters:
[source,java,indent=0,subs="verbatim,quotes"]
----
private JdbcClient jdbcClient = JdbcClient.create(dataSource);
public int countOfActorsByFirstName(String firstName) {
return this.jdbcClient.sql("select count(*) from t_actor where first_name = :firstName")
.param("firstName", firstName);
.query(Integer.class).single();
}
----
`RowMapper` capabilities are available as well, with flexible result resolution:
[source,java,indent=0,subs="verbatim,quotes"]
----
List<Actor> actors = this.jdbcClient.sql("select first_name, last_name from t_actor")
.query((rs, rowNum) -> new Actor(rs.getString("first_name"), rs.getString("last_name")))
.list();
----
Instead of a custom `RowMapper`, you may also specify a class to map to.
For example, assuming that `Actor` has `firstName` and `lastName` properties
as a record class, a custom constructor, bean properties, or plain fields:
[source,java,indent=0,subs="verbatim,quotes"]
----
List<Actor> actors = this.jdbcClient.sql("select first_name, last_name from t_actor")
.query(Actor.class)
.list();
----
With a required single object result:
[source,java,indent=0,subs="verbatim,quotes"]
----
Actor actor = this.jdbcClient.sql("select first_name, last_name from t_actor where id = ?",
.param(1212L);
.query(Actor.class)
.single();
----
With a `java.util.Optional` result:
[source,java,indent=0,subs="verbatim,quotes"]
----
Optional<Actor> actor = this.jdbcClient.sql("select first_name, last_name from t_actor where id = ?",
.param(1212L);
.query(Actor.class)
.optional();
----
And for an update statement:
[source,java,indent=0,subs="verbatim,quotes"]
----
this.jdbcClient.sql("insert into t_actor (first_name, last_name) values (?, ?)")
.param("Leonor").param("Watling");
.update();
----
Or an update statement with named parameters:
[source,java,indent=0,subs="verbatim,quotes"]
----
this.jdbcClient.sql("insert into t_actor (first_name, last_name) values (:firstName, :lastName)")
.param("firstName", "Leonor").param("lastName", "Watling");
.update();
----
Instead of individual named parameters, you may also specify a parameter source object
for example, a record class, a class with bean properties, or a plain field holder which
provides `firstName` and `lastName` properties, such as the `Actor` class from above:
[source,java,indent=0,subs="verbatim,quotes"]
----
this.jdbcClient.sql("insert into t_actor (first_name, last_name) values (:firstName, :lastName)")
.paramSource(new Actor("Leonor", "Watling");
.update();
----
The automatic `Actor` class mapping for parameters as well as the query results above is
provided through implicit `SimplePropertySqlParameterSource` and `SimplePropertyRowMapper`
strategies which are also available for direct use. They can serve as a common replacement
for `BeanPropertySqlParameterSource` and `BeanPropertyRowMapper`/`DataClassRowMapper`,
also with `JdbcTemplate` and `NamedParameterJdbcTemplate` themselves.
NOTE: `JdbcClient` is a flexible but simplified facade for JDBC query/update statements.
Advanced capabilities such as batch inserts and stored procedure calls typically require
extra customization: consider Spring's `SimpleJdbcInsert` and `SimpleJdbcCall` classes or
plain direct `JdbcTemplate` usage for any such capabilities not available in `JdbcClient`.
[[jdbc-SQLExceptionTranslator]]
== Using `SQLExceptionTranslator`
@@ -709,7 +824,7 @@ between ``SQLException``s and Spring's own `org.springframework.dao.DataAccessEx
which is agnostic in regard to data access strategy. Implementations can be generic (for
example, using SQLState codes for JDBC) or proprietary (for example, using Oracle error
codes) for greater precision. This exception translation mechanism is used behind the
the common `JdbcTemplate` and `JdbcTransactionManager` entry points which do not
common `JdbcTemplate` and `JdbcTransactionManager` entry points which do not
propagate `SQLException` but rather `DataAccessException`.
NOTE: As of 6.0, the default exception translator is `SQLExceptionSubclassTranslator`,
@@ -20,9 +20,10 @@ xref:data-access/jdbc/connections.adoc[Controlling Database Connections] and xre
* `object`: The `org.springframework.jdbc.object` package contains classes that represent
RDBMS queries, updates, and stored procedures as thread-safe, reusable objects. See
xref:data-access/jdbc/object.adoc[Modeling JDBC Operations as Java Objects]. This approach is modeled by JDO, although objects returned by queries
are naturally disconnected from the database. This higher-level of JDBC abstraction
depends on the lower-level abstraction in the `org.springframework.jdbc.core` package.
xref:data-access/jdbc/object.adoc[Modeling JDBC Operations as Java Objects]. This style
results in a more object-oriented approach, although objects returned by queries are
naturally disconnected from the database. This higher-level of JDBC abstraction depends
on the lower-level abstraction in the `org.springframework.jdbc.core` package.
* `support`: The `org.springframework.jdbc.support` package provides `SQLException`
translation functionality and some utility classes. Exceptions thrown during JDBC processing
@@ -254,6 +254,25 @@ Kotlin::
----
======
Alternatively, there is a shortcut for mapping to a single value:
[source,java]
----
Flux<String> names = client.sql("SELECT name FROM person")
.mapValue(String.class)
.all();
----
Or you may map to a result object with bean properties or record components:
[source,java]
----
// assuming a name property on Person
Flux<Person> persons = client.sql("SELECT name FROM person")
.mapProperties(Person.class)
.all();
----
[[r2dbc-DatabaseClient-mapping-null]]
.What about `null`?
****
@@ -324,6 +343,27 @@ The following example shows parameter binding for a query:
.bind("age", 34);
----
Alternatively, you may pass in a map of names and values:
[source,java]
----
Map<String, Object> params = new LinkedHashMap<>();
params.put("id", "joe");
params.put("name", "Joe");
params.put("age", 34);
db.sql("INSERT INTO person (id, name, age) VALUES(:id, :name, :age)")
.bindValues(params);
----
Or you may pass in a parameter object with bean properties or record components:
[source,java]
----
// assuming id, name, age properties on Person
db.sql("INSERT INTO person (id, name, age) VALUES(:id, :name, :age)")
.bindProperties(new Person("joe", "Joe", 34);
----
.R2DBC Native Bind Markers
****
R2DBC uses database-native bind markers that depend on the actual database vendor.
@@ -57,10 +57,14 @@ attribute of the annotation to `true`.
[NOTE]
====
`@TransactionalEventListener` only works with thread-bound transactions managed by
`PlatformTransactionManager`. A reactive transaction managed by `ReactiveTransactionManager`
uses the Reactor context instead of thread-local attributes, so from the perspective of
an event listener, there is no compatible active transaction that it can participate in.
As of 6.1, `@TransactionalEventListener` can work with thread-bound transactions managed by
`PlatformTransactionManager` as well as reactive transactions managed by `ReactiveTransactionManager`.
For the former, listeners are guaranteed to see the current thread-bound transaction.
Since the latter uses the Reactor context instead of thread-local variables, the transaction
context needs to be included in the published event instance as the event source.
See the
{api-spring-framework}/transaction/reactive/TransactionalEventPublisher.html[`TransactionalEventPublisher`]
javadoc for details.
====
+1 -1
View File
@@ -16,7 +16,7 @@ STOMP Messaging.
xref:web-reactive.adoc[Web Reactive] :: Spring WebFlux, WebClient,
WebSocket, RSocket.
xref:integration.adoc[Integration] :: REST Clients, JMS, JCA, JMX,
Email, Tasks, Scheduling, Caching, Observability.
Email, Tasks, Scheduling, Caching, Observability, JVM Checkpoint Restore.
xref:languages.adoc[Languages] :: Kotlin, Groovy, Dynamic Languages.
xref:testing/appendix.adoc[Appendix] :: Spring properties.
https://github.com/spring-projects/spring-framework/wiki[Wiki] :: What's New,
@@ -208,6 +208,76 @@ NOTE: This is an optional feature, and your favorite cache library may not suppo
All `CacheManager` implementations provided by the core framework support it. See the
documentation of your cache provider for more details.
[[cache-annotations-cacheable-reactive]]
=== Caching with CompletableFuture and Reactive Return Types
As of 6.1, cache annotations take `CompletableFuture` and reactive return types
into account, automatically adapting the cache interaction accordingly.
For a method returning a `CompletableFuture`, the object produced by that future
will be cached whenever it is complete, and the cache lookup for a cache hit will
be retrieved via a `CompletableFuture`:
[source,java,indent=0,subs="verbatim,quotes"]
----
@Cacheable("books")
public CompletableFuture<Book> findBook(ISBN isbn) {...}
----
For a method returning a Reactor `Mono`, the object emitted by that Reactive Streams
publisher will be cached whenever it is available, and the cache lookup for a cache
hit will be retrieved as a `Mono` (backed by a `CompletableFuture`):
[source,java,indent=0,subs="verbatim,quotes"]
----
@Cacheable("books")
public Mono<Book> findBook(ISBN isbn) {...}
----
For a method returning a Reactor `Flux`, the objects emitted by that Reactive Streams
publisher will be collected into a `List` and cached whenever that list is complete,
and the cache lookup for a cache hit will be retrieved as a `Flux` (backed by a
`CompletableFuture` for the cached `List` value):
[source,java,indent=0,subs="verbatim,quotes"]
----
@Cacheable("books")
public Flux<Book> findBooks(String author) {...}
----
Such `CompletableFuture` and reactive adaptation also works for synchronized caching,
computing the value only once in case of a concurrent cache miss:
[source,java,indent=0,subs="verbatim,quotes"]
----
@Cacheable(cacheNames="foos", sync=true) <1>
public CompletableFuture<Foo> executeExpensiveOperation(String id) {...}
----
<1> Using the `sync` attribute.
NOTE: In order for such an arrangement to work at runtime, the configured cache
needs to be capable of `CompletableFuture`-based retrieval. The Spring-provided
`ConcurrentMapCacheManager` automatically adapts to that retrieval style, and
`CaffeineCacheManager` natively supports it when its asynchronous cache mode is
enabled: set `setAsyncCacheMode(true)` on your `CaffeineCacheManager` instance.
[source,java,indent=0,subs="verbatim,quotes"]
----
@Bean
CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCacheSpecification(...);
cacheManager.setAsyncCacheMode(true);
return cacheManager;
}
----
Last but not least, be aware that annotation-driven caching is not appropriate
for sophisticated reactive interactions involving composition and back pressure.
If you choose to declare `@Cacheable` on specific reactive methods, consider the
impact of the rather coarse-granular cache interaction which simply stores the
emitted object for a `Mono` or even a pre-collected list of objects for a `Flux`.
[[cache-annotations-cacheable-condition]]
=== Conditional Caching
@@ -337,6 +407,9 @@ other), such declarations should be avoided. Note also that such conditions shou
on the result object (that is, the `#result` variable), as these are validated up-front to
confirm the exclusion.
As of 6.1, `@CachePut` takes `CompletableFuture` and reactive return types into account,
performing the put operation whenever the produced object is available.
[[cache-annotations-evict]]
== The `@CacheEvict` Annotation
@@ -379,6 +452,9 @@ trigger, the return values are ignored (as they do not interact with the cache).
not the case with `@Cacheable` which adds data to the cache or updates data in the cache
and, thus, requires a result.
As of 6.1, `@CacheEvict` takes `CompletableFuture` and reactive return types into account,
performing an after-invocation evict operation whenever processing has completed.
[[cache-annotations-caching]]
== The `@Caching` Annotation
@@ -0,0 +1,31 @@
[[checkpoint-restore]]
= JVM Checkpoint Restore
The Spring Framework integrates with checkpoint/restore as implemented by https://github.com/CRaC/docs[Project CRaC] in order to allow implementing systems capable to reduce the startup and warmup times of Spring-based Java applications with the JVM.
Using this feature requires:
* A checkpoint/restore enabled JVM (Linux only for now).
* The presence in the classpath of the https://github.com/CRaC/org.crac[`org.crac:crac`] library (version `1.4.0` and above are supported).
* Specifying the required `java` command line parameters like `-XX:CRaCCheckpointTo=PATH` or `-XX:CRaCRestoreFrom=PATH`.
WARNING: The files generated in the path specified by `-XX:CRaCCheckpointTo=PATH` when a checkpoint is requested contain a representation of the memory of the running JVM, which may contain secrets and other sensitive data. Using this feature should be done with the assumption that any value "seen" by the JVM, such as configuration properties coming from the environment, will be stored in those CRaC files. As a consequence, the security implications of where and how those files are generated, stored and accessed should be carefully assessed.
Conceptually, checkpoint and restore match with xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-processor[Spring `Lifecycle` contract] for individual beans.
== On demand checkpoint/restore of a running application
A checkpoint can be created on demand, for example using a command like `jcmd application.jar JDK.checkpoint`. Before the creation of the checkpoint, Spring Framework
stops all the running beans, giving them a chance to close resources if needed by implementing `Lifecycle.stop`. After restore, the same beans are restarted, with `Lifecycle.start` allowing to reopen resources when relevant. For libraries not depending on Spring, checkpoint/restore custom integration can be provided by implementing `org.crac.Resource` and registering the related instance.
WARNING: Leveraging checkpoint/restore of a running application typically requires additional lifecycle management to gracefully stop and start using resources like files or sockets and stop active threads.
NOTE: If the checkpoint is created on a warmed-up JVM, the restored JVM will be equally warmed-up, allowing potentially peak performance immediately. This method typically requires access to remote services, and thus requires some level of platform integration.
== Automatic checkpoint/restore at startup
When the `-Dspring.context.checkpoint=onRefresh` Java system property is set, a checkpoint is created automatically during the startup at `LifecycleProcessor.onRefresh` level. At this phase, all non-lazy initialized singletons are instantiated, `InitializingBean.afterPropertiesSet` callbacks have been invoked, but not `Lifecycle.start` ones and `ContextRefreshedEvent` has not yet been published.
WARNING: As mentioned above, and especially in use cases where the CRaC files are shipped as part of a deployable artifact (a container image for example), operate with the assumption that any sensitive data "seen" by the JVM ends up in the CRaC files, and assess carefully the related security implications.
NOTE: Here checkpoint/restore is a way to "fast-forward" the startup of the application to a phase where the application context is about to start, but does not allow to have a fully warmed-up JVM.
@@ -21,11 +21,20 @@ As outlined xref:integration/observability.adoc[at the beginning of this section
|===
|Observation name |Description
|xref:integration/observability.adoc#http-client[`"http.client.requests"`]
|xref:integration/observability.adoc#observability.http-client[`"http.client.requests"`]
|Time spent for HTTP client exchanges
|xref:integration/observability.adoc#http-server[`"http.server.requests"`]
|xref:integration/observability.adoc#observability.http-server[`"http.server.requests"`]
|Processing time for HTTP server exchanges at the Framework level
|xref:integration/observability.adoc#observability.jms.publish[`"jms.message.publish"`]
|Time spent sending a JMS message to a destination by a message producer.
|xref:integration/observability.adoc#observability.jms.process[`"jms.message.process"`]
|Processing time for a JMS message that was previously received by a message consumer.
|xref:integration/observability.adoc#observability.tasks-scheduled[`"tasks.scheduled.execution"`]
|Processing time for an execution of a `@Scheduled` task
|===
NOTE: Observations are using Micrometer's official naming convention, but Metrics names will be automatically converted
@@ -79,6 +88,99 @@ include-code::./ServerRequestObservationFilter[]
You can configure `ObservationFilter` instances on the `ObservationRegistry`.
[[observability.tasks-scheduled]]
== @Scheduled tasks instrumentation
An Observation is created for xref:integration/scheduling.adoc#scheduling-enable-annotation-support[each execution of an `@Scheduled` task].
Applications need to configure the `ObservationRegistry` on the `ScheduledTaskRegistrar` to enable the recording of observations.
This can be done by declaring a `SchedulingConfigurer` bean that sets the observation registry:
include-code::./ObservationSchedulingConfigurer[]
It is using the `org.springframework.scheduling.support.DefaultScheduledTaskObservationConvention` by default, backed by the `ScheduledTaskObservationContext`.
You can configure a custom implementation on the `ObservationRegistry` directly.
During the execution of the scheduled method, the current observation is restored in the `ThreadLocal` context or the Reactor context (if the scheduled method returns a `Mono` or `Flux` type).
By default, the following `KeyValues` are created:
.Low cardinality Keys
[cols="a,a"]
|===
|Name | Description
|`code.function` _(required)_|Name of Java `Method` that is scheduled for execution.
|`code.namespace` _(required)_|Canonical name of the class of the bean instance that holds the scheduled method.
|`error` _(required)_|Class name of the exception thrown during the execution, or `"none"` if no exception happened.
|`exception` _(deprecated)_|Duplicates the `error` key and might be removed in the future.
|`outcome` _(required)_|Outcome of the method execution. Can be `"SUCCESS"`, `"ERROR"` or `"UNKNOWN"` (if for example the operation was cancelled during execution).
|===
[[observability.jms]]
== JMS messaging instrumentation
Spring Framework uses the Jakarta JMS instrumentation provided by Micrometer if the `io.micrometer:micrometer-jakarta9` dependency is on the classpath.
The `io.micrometer.jakarta9.instrument.jms.JmsInstrumentation` instruments `jakarta.jms.Session` and records the relevant observations.
This instrumentation will create 2 types of observations:
* `"jms.message.publish"` when a JMS message is sent to the broker, typically with `JmsTemplate`.
* `"jms.message.process"` when a JMS message is processed by the application, typically with a `MessageListener` or a `@JmsListener` annotated method.
NOTE: currently there is no instrumentation for `"jms.message.receive"` observations as there is little value in measuring the time spent waiting for the reception of a message.
Such an integration would typically instrument `MessageConsumer#receive` method calls. But once those return, the processing time is not measured and the trace scope cannot be propagated to the application.
By default, both observations share the same set of possible `KeyValues`:
.Low cardinality Keys
[cols="a,a"]
|===
|Name | Description
|`error` |Class name of the exception thrown during the messaging operation (or "none").
|`exception` _(deprecated)_|Duplicates the `error` key and might be removed in the future.
|`messaging.destination.temporary` _(required)_|Whether the destination is a `TemporaryQueue` or `TemporaryTopic` (values: `"true"` or `"false"`).
|`messaging.operation` _(required)_|Name of JMS operation being performed (values: `"publish"` or `"process"`).
|===
.High cardinality Keys
[cols="a,a"]
|===
|Name | Description
|`messaging.message.conversation_id` |The correlation ID of the JMS message.
|`messaging.destination.name` |The name of destination the current message was sent to.
|`messaging.message.id` |Value used by the messaging system as an identifier for the message.
|===
[[observability.jms.publish]]
=== JMS message Publication instrumentation
`"jms.message.publish"` observations are recorded when a JMS message is sent to the broker.
They measure the time spent sending the message and propagate the tracing information with outgoing JMS message headers.
You will need to configure the `ObservationRegistry` on the `JmsTemplate` to enable observations:
include-code::./JmsTemplatePublish[]
It uses the `io.micrometer.jakarta9.instrument.jms.DefaultJmsPublishObservationConvention` by default, backed by the `io.micrometer.jakarta9.instrument.jms.JmsPublishObservationContext`.
[[observability.jms.process]]
=== JMS message Processing instrumentation
`"jms.message.process"` observations are recorded when a JMS message is processed by the application.
They measure the time spent processing the message and propagate the tracing context with incoming JMS message headers.
Most applications will use the xref:integration/jms/annotated.adoc#jms-annotated[`@JmsListener` annotated methods] mechanism to process incoming messages.
You will need to ensure that the `ObservationRegistry` is configured on the dedicated `JmsListenerContainerFactory`:
include-code::./JmsConfiguration[]
A xref:integration/jms/annotated.adoc#jms-annotated-support[default container factory is required to enable the annotation support],
but note that `@JmsListener` annotations can refer to specific container factory beans for specific purposes.
In all cases, Observations are only recorded if the observation registry is configured on the container factory.
Similar observations are recorded with `JmsTemplate` when messages are processed by a `MessageListener`.
Such listeners are set on a `MessageConsumer` within a session callback (see `JmsTemplate.execute(SessionCallback<T>)`).
This observation uses the `io.micrometer.jakarta9.instrument.jms.DefaultJmsProcessObservationConvention` by default, backed by the `io.micrometer.jakarta9.instrument.jms.JmsProcessObservationContext`.
[[observability.http-server]]
== HTTP Server instrumentation
@@ -99,7 +201,7 @@ include-code::./UserController[]
NOTE: Because the instrumentation is done at the Servlet Filter level, the observation scope only covers the filters ordered after this one as well as the handling of the request.
Typically, Servlet container error handling is performed at a lower level and won't have any active observation or span.
For this use case, a container-specific implementation is required, such as a `org.apache.catalina.Valve` for Tomcat; this is outside of the scope of this project.
For this use case, a container-specific implementation is required, such as a `org.apache.catalina.Valve` for Tomcat; this is outside the scope of this project.
By default, the following `KeyValues` are created:
@@ -107,7 +209,8 @@ By default, the following `KeyValues` are created:
[cols="a,a"]
|===
|Name | Description
|`exception` _(required)_|Name of the exception thrown during the exchange, or `KeyValue#NONE_VALUE`} if no exception happened.
|`error` _(required)_|Class name of the exception thrown during the exchange, or `"none"` if no exception happened.
|`exception` _(deprecated)_|Duplicates the `error` key and might be removed in the future.
|`method` _(required)_|Name of HTTP request method or `"none"` if not a well-known method.
|`outcome` _(required)_|Outcome of the HTTP server exchange.
|`status` _(required)_|HTTP response raw status code, or `"UNKNOWN"` if no response was created.
@@ -125,11 +228,15 @@ By default, the following `KeyValues` are created:
[[observability.http-server.reactive]]
=== Reactive applications
Applications need to configure the `org.springframework.web.filter.reactive.ServerHttpObservationFilter` reactive `WebFilter` in their application.
It uses the `org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention` by default, backed by the `ServerRequestObservationContext`.
Applications need to configure the `WebHttpHandlerBuilder` with a `MeterRegistry` to enable server instrumentation.
This can be done on the `WebHttpHandlerBuilder`, as follows:
This will only record an observation as an error if the `Exception` has not been handled by the web framework and has bubbled up to the `WebFilter`.
Typically, all exceptions handled by Spring WebFlux's `@ExceptionHandler` and xref:web/webflux/ann-rest-exceptions.adoc[`ProblemDetail` support] will not be recorded with the observation.
include-code::./HttpHandlerConfiguration[]
It is using the `org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention` by default, backed by the `ServerRequestObservationContext`.
This will only record an observation as an error if the `Exception` has not been handled by an application Controller.
Typically, all exceptions handled by Spring WebFlux's `@ExceptionHandler` and <<web.adoc#webflux-ann-rest-exceptions,`ProblemDetail` support>> will not be recorded with the observation.
You can, at any point during request processing, set the error field on the `ObservationContext` yourself:
include-code::./UserController[]
@@ -140,7 +247,8 @@ By default, the following `KeyValues` are created:
[cols="a,a"]
|===
|Name | Description
|`exception` _(required)_|Name of the exception thrown during the exchange, or `"none"` if no exception happened.
|`error` _(required)_|Class name of the exception thrown during the exchange, or `"none"` if no exception happened.
|`exception` _(deprecated)_|Duplicates the `error` key and might be removed in the future.
|`method` _(required)_|Name of HTTP request method or `"none"` if not a well-known method.
|`outcome` _(required)_|Outcome of the HTTP server exchange.
|`status` _(required)_|HTTP response raw status code, or `"UNKNOWN"` if no response was created.
@@ -179,7 +287,8 @@ Instrumentation uses the `org.springframework.http.client.observation.ClientRequ
|`client.name` _(required)_|Client name derived from the request URI host.
|`status` _(required)_|HTTP response raw status code, or `"IO_ERROR"` in case of `IOException`, or `"CLIENT_ERROR"` if no response was received.
|`outcome` _(required)_|Outcome of the HTTP client exchange.
|`exception` _(required)_|Name of the exception thrown during the exchange, or `"none"` if no exception happened.
|`error` _(required)_|Class name of the exception thrown during the exchange, or `"none"` if no exception happened.
|`exception` _(deprecated)_|Duplicates the `error` key and might be removed in the future.
|===
.High cardinality Keys
@@ -190,6 +299,33 @@ Instrumentation uses the `org.springframework.http.client.observation.ClientRequ
|===
[[observability.http-client.restclient]]
=== RestClient
Applications must configure an `ObservationRegistry` on the `RestClient.Builder` to enable the instrumentation; without that, observations are "no-ops".
Instrumentation uses the `org.springframework.http.client.observation.ClientRequestObservationConvention` by default, backed by the `ClientRequestObservationContext`.
.Low cardinality Keys
[cols="a,a"]
|===
|Name | Description
|`method` _(required)_|Name of HTTP request method or `"none"` if the request could not be created.
|`uri` _(required)_|URI template used for HTTP request, or `"none"` if none was provided. Only the path part of the URI is considered.
|`client.name` _(required)_|Client name derived from the request URI host.
|`status` _(required)_|HTTP response raw status code, or `"IO_ERROR"` in case of `IOException`, or `"CLIENT_ERROR"` if no response was received.
|`outcome` _(required)_|Outcome of the HTTP client exchange.
|`error` _(required)_|Class name of the exception thrown during the exchange, or `"none"` if no exception happened.
|`exception` _(deprecated)_|Duplicates the `error` key and might be removed in the future.
|===
.High cardinality Keys
[cols="a,a"]
|===
|Name | Description
|`http.url` _(required)_|HTTP request URI.
|===
[[observability.http-client.webclient]]
=== WebClient
@@ -208,7 +344,8 @@ Instrumentation uses the `org.springframework.web.reactive.function.client.Clien
|`client.name` _(required)_|Client name derived from the request URI host.
|`status` _(required)_|HTTP response raw status code, or `"IO_ERROR"` in case of `IOException`, or `"CLIENT_ERROR"` if no response was received.
|`outcome` _(required)_|Outcome of the HTTP client exchange.
|`exception` _(required)_|Name of the exception thrown during the exchange, or `"none"` if no exception happened.
|`error` _(required)_|Class name of the exception thrown during the exchange, or `"none"` if no exception happened.
|`exception` _(deprecated)_|Duplicates the `error` key and might be removed in the future.
|===
.High cardinality Keys
@@ -219,3 +356,28 @@ Instrumentation uses the `org.springframework.web.reactive.function.client.Clien
|===
[[observability.application-events]]
== Application Events and `@EventListener`
Spring Framework does not contribute Observations for xref:core/beans/context-introduction.adoc#context-functionality-events-annotation[`@EventListener` calls],
as they don't have the right semantics for such instrumentation.
By default, event publication and processing are done synchronously and on the same thread.
This means that during the execution of that task, the ThreadLocals and logging context will be the same as the event publisher.
If the application globally configures a custom `ApplicationEventMulticaster` with a strategy that schedules event processing on different threads, this is no longer true.
All `@EventListener` methods will be processed on a different thread, outside the main event publication thread.
In these cases, the https://micrometer.io/docs/contextPropagation[Micrometer Context Propagation library] can help propagate such values and better correlate the processing of the events.
The application can configure the chosen `TaskExecutor` to use a `ContextPropagatingTaskDecorator` that decorates tasks and propagates context.
For this to work, the `io.micrometer:context-propagation` library must be present on the classpath:
include-code::./ApplicationEventsConfiguration[]
Similarly, if that asynchronous choice is made locally for each `@EventListener` annotated method, by adding `@Async` to it,
you can choose a `TaskExecutor` that propagates context by referring to it by its qualifier.
Given the following `TaskExecutor` bean definition, configured with the dedicated task decorator:
include-code::./EventAsyncExecutionConfiguration[]
Annotating event listeners with `@Async` and the relevant qualifier will achieve similar context propagation results:
include-code::./EmailNotificationListener[]
File diff suppressed because it is too large Load Diff
@@ -66,6 +66,11 @@ The variants that Spring provides are as follows:
compatible runtime environment (such as a Jakarta EE application server),
replacing a CommonJ WorkManager for that purpose.
As of 6.1, `ThreadPoolTaskExecutor` provides a pause/resume capability and graceful
shutdown through Spring's lifecycle management. There is also a new "virtualThreads"
option on `SimpleAsyncTaskExecutor` which is aligned with JDK 21's Virtual Threads,
as well as a graceful shutdown capability for `SimpleAsyncTaskExecutor` as well.
[[scheduling-task-executor-usage]]
=== Using a `TaskExecutor`
@@ -244,6 +249,11 @@ to provide common bean-style configuration along the lines of `ThreadPoolTaskExe
These variants work perfectly fine for locally embedded thread pool setups in lenient
application server environments, as well -- in particular on Tomcat and Jetty.
As of 6.1, `ThreadPoolTaskScheduler` provides a pause/resume capability and graceful
shutdown through Spring's lifecycle management. There is also a new option called
`SimpleAsyncTaskScheduler` which is aligned with JDK 21's Virtual Threads, using a
single scheduler thread but firing up a new thread for every scheduled task execution.
[[scheduling-annotation-support]]
@@ -353,6 +363,17 @@ the amount of time to wait before the first execution of the method, as the foll
}
----
For one-time tasks, you can just specify an initial delay by indicating the amount
of time to wait before the intended execution of the method:
[source,java,indent=0,subs="verbatim,quotes"]
----
@Scheduled(initialDelay = 1000)
public void doSomething() {
// something that should run only once
}
----
If simple periodic scheduling is not expressive enough, you can provide a
xref:integration/scheduling.adoc#scheduling-cron-expression[cron expression].
The following example runs only on weekdays:
@@ -392,6 +413,120 @@ container and once through the `@Configurable` aspect), with the consequence of
`@Scheduled` method being invoked twice.
====
[[scheduling-annotation-support-scheduled-reactive]]
=== The `@Scheduled` annotation on Reactive methods or Kotlin suspending functions
As of Spring Framework 6.1, `@Scheduled` methods are also supported on several types
of reactive methods:
- methods with a `Publisher` return type (or any concrete implementation of `Publisher`)
like in the following example:
[source,java,indent=0,subs="verbatim,quotes"]
----
@Scheduled(fixedDelay = 500)
public Publisher<Void> reactiveSomething() {
// return an instance of Publisher
}
----
- methods with a return type that can be adapted to `Publisher` via the shared instance
of the `ReactiveAdapterRegistry`, provided the type supports _deferred subscription_ like
in the following example:
[source,java,indent=0,subs="verbatim,quotes"]
----
@Scheduled(fixedDelay = 500)
public Single<String> rxjavaNonPublisher() {
return Single.just("example");
}
----
[NOTE]
====
The `CompletableFuture` class is an example of a type that can typically be adapted
to `Publisher` but doesn't support deferred subscription. Its `ReactiveAdapter` in the
registry denotes that by having the `getDescriptor().isDeferred()` method return `false`.
====
- Kotlin suspending functions, like in the following example:
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Scheduled(fixedDelay = 500)
suspend fun something() {
// do something asynchronous
}
----
- methods that return a Kotlin `Flow` or `Deferred` instance, like in the following example:
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
@Scheduled(fixedDelay = 500)
fun something(): Flow<Void> {
flow {
// do something asynchronous
}
}
----
All these types of methods must be declared without any arguments. In the case of Kotlin
suspending functions, the `kotlinx.coroutines.reactor` bridge must also be present to allow
the framework to invoke a suspending function as a `Publisher`.
The Spring Framework will obtain a `Publisher` for the annotated method once and will
schedule a `Runnable` in which it subscribes to said `Publisher`. These inner regular
subscriptions occur according to the corresponding `cron`/fixedDelay`/`fixedRate` configuration.
If the `Publisher` emits `onNext` signal(s), these are ignored and discarded (the same way
return values from synchronous `@Scheduled` methods are ignored).
In the following example, the `Flux` emits `onNext("Hello"), onNext("World")` every 5
seconds, but these values are unused:
[source,java,indent=0,subs="verbatim,quotes"]
----
@Scheduled(initialDelay = 5000, fixedRate = 5000)
public Flux<String> reactiveSomething() {
return Flux.just("Hello", "World");
}
----
If the `Publisher` emits an `onError` signal, it is logged at `WARN` level and recovered.
Because of the asynchronous and lazy nature of `Publisher` instances, exceptions are
not thrown from the `Runnable` task: this means that the `ErrorHandler` contract is not
involved for reactive methods.
As a result, further scheduled subscription occurs despite the error.
In the following example, the `Mono` subscription fails twice in the first five seconds.
Then subscriptions start succeeding, printing a message to the standard output every five
seconds:
[source,java,indent=0,subs="verbatim,quotes"]
----
@Scheduled(initialDelay = 0, fixedRate = 5000)
public Mono<Void> reactiveSomething() {
AtomicInteger countdown = new AtomicInteger(2);
return Mono.defer(() -> {
if (countDown.get() == 0 || countDown.decrementAndGet() == 0) {
return Mono.fromRunnable(() -> System.out.println("Message"));
}
return Mono.error(new IllegalStateException("Cannot deliver message"));
})
}
----
[NOTE]
====
When destroying the annotated bean or closing the application context, Spring Framework cancels
scheduled tasks, which includes the next scheduled subscription to the `Publisher` as well
as any past subscription that is still currently active (e.g. for long-running publishers
or even infinite publishers).
====
[[scheduling-annotation-support-async]]
=== The `@Async` annotation
@@ -248,7 +248,7 @@ For example, declaring `List<Foo>` in Kotlin is conceptually equivalent to `java
`kotlin.collections.List` is declared as
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/[`interface List<out E> : kotlin.collections.Collection<E>`].
This needs to be taken in account by using the `out` Kotlin keyword on generic types when using Java classes,
This needs to be taken into account by using the `out` Kotlin keyword on generic types when using Java classes,
for example when writing a `org.springframework.core.convert.converter.Converter` from a Kotlin type to a Java type.
[source,kotlin,indent=0]
@@ -287,11 +287,14 @@ https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-featu
=== Constructor injection
As described in the xref:testing/testcontext-framework/support-classes.adoc#testcontext-junit-jupiter-di[dedicated section],
JUnit 5 allows constructor injection of beans which is pretty useful with Kotlin
JUnit Jupiter (JUnit 5) allows constructor injection of beans which is pretty useful with Kotlin
in order to use `val` instead of `lateinit var`. You can use
{api-spring-framework}/test/context/TestConstructor.html[`@TestConstructor(autowireMode = AutowireMode.ALL)`]
to enable autowiring for all parameters.
NOTE: You can also change the default behavior to `ALL` in a `junit-platform.properties`
file with a `spring.test.constructor.autowire.mode = all` property.
[source,kotlin,indent=0]
----
@SpringJUnitConfig(TestConfig::class)
@@ -308,11 +311,11 @@ class OrderServiceIntegrationTests(val orderService: OrderService,
=== `PER_CLASS` Lifecycle
Kotlin lets you specify meaningful test function names between backticks (```).
As of JUnit 5, Kotlin test classes can use the `@TestInstance(TestInstance.Lifecycle.PER_CLASS)`
With JUnit Jupiter (JUnit 5), Kotlin test classes can use the `@TestInstance(TestInstance.Lifecycle.PER_CLASS)`
annotation to enable single instantiation of test classes, which allows the use of `@BeforeAll`
and `@AfterAll` annotations on non-static methods, which is a good fit for Kotlin.
You can also change the default behavior to `PER_CLASS` thanks to a `junit-platform.properties`
NOTE: You can also change the default behavior to `PER_CLASS` in a `junit-platform.properties`
file with a `junit.jupiter.testinstance.lifecycle.default = per_class` property.
The following example demonstrates `@BeforeAll` and `@AfterAll` annotations on non-static methods:
+87 -10
View File
@@ -137,10 +137,12 @@ demonstrate its API and protocol features.
The `spring-messaging` module contains the following:
* xref:rsocket.adoc#rsocket-requester[RSocketRequester] -- fluent API to make requests through an `io.rsocket.RSocket`
with data and metadata encoding/decoding.
* xref:rsocket.adoc#rsocket-annot-responders[Annotated Responders] -- `@MessageMapping` annotated handler methods for
responding.
* xref:rsocket.adoc#rsocket-requester[RSocketRequester] -- fluent API to make requests
through an `io.rsocket.RSocket` with data and metadata encoding/decoding.
* xref:rsocket.adoc#rsocket-annot-responders[Annotated Responders] -- `@MessageMapping`
and `@RSocketExchange` annotated handler methods for responding.
* xref:rsocket.adoc#rsocket-interface[RSocket Interface] -- RSocket service declaration
as Java interface with `@RSocketExchange` methods, for use as requester or responder.
The `spring-web` module contains `Encoder` and `Decoder` implementations such as Jackson
CBOR/JSON, and Protobuf that RSocket applications will likely need. It also contains the
@@ -863,6 +865,69 @@ interaction type(s):
[[rsocket-annot-rsocketexchange]]
=== @RSocketExchange
As an alternative to `@MessageMapping`, you can also handle requests with
`@RSocketExchange` methods. Such methods are declared on an
xref:rsocket-interface[RSocket Interface] and can be used as a requester via
`RSocketServiceProxyFactory` or implemented by a responder.
For example, to handle requests as a responder:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public interface RadarsService {
@RSocketExchange("locate.radars.within")
Flux<AirportLocation> radars(MapRequest request);
}
@Controller
public class RadarsController implements RadarsService {
public Flux<AirportLocation> radars(MapRequest request) {
// ...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
interface RadarsService {
@RSocketExchange("locate.radars.within")
fun radars(request: MapRequest): Flow<AirportLocation>
}
@Controller
class RadarsController : RadarsService {
override fun radars(request: MapRequest): Flow<AirportLocation> {
// ...
}
}
----
======
There some differences between `@RSocketExhange` and `@MessageMapping` since the
former needs to remain suitable for requester and responder use. For example, while
`@MessageMapping` can be declared to handle any number of routes and each route can
be a pattern, `@RSocketExchange` must be declared with a single, concrete route. There are
also small differences in the supported method parameters related to metadata, see
xref:rsocket-annot-messagemapping[@MessageMapping] and
xref:rsocket-interface[RSocket Interface] for a list of supported parameters.
`@RSocketExchange` can be used at the type level to specify a common prefix for all routes
for a given RSocket service interface.
[[rsocket-annot-connectmapping]]
=== @ConnectMapping
@@ -997,12 +1062,13 @@ Kotlin::
[[rsocket-interface]]
== RSocket Interface
The Spring Framework lets you define an RSocket service as a Java interface with annotated
methods for RSocket exchanges. You can then generate a proxy that implements this interface
and performs the exchanges. This helps to simplify RSocket remote access by wrapping the
use of the underlying xref:rsocket.adoc#rsocket-requester[RSocketRequester].
The Spring Framework lets you define an RSocket service as a Java interface with
`@RSocketExchange` methods. You can pass such an interface to `RSocketServiceProxyFactory`
to create a proxy which performs requests through an
xref:rsocket.adoc#rsocket-requester[RSocketRequester]. You can also implement the
interface as a responder that handles requests.
One, declare an interface with `@RSocketExchange` methods:
Start by creating the interface with `@RSocketExchange` methods:
[source,java,indent=0,subs="verbatim,quotes"]
----
@@ -1016,7 +1082,7 @@ One, declare an interface with `@RSocketExchange` methods:
}
----
Two, create a proxy that will perform the declared RSocket exchanges:
Now you can create a proxy that performs requests when methods are called:
[source,java,indent=0,subs="verbatim,quotes"]
----
@@ -1026,6 +1092,10 @@ Two, create a proxy that will perform the declared RSocket exchanges:
RadarService service = factory.createClient(RadarService.class);
----
You can also implement the interface to handle requests as a responder.
See xref:rsocket.adoc#rsocket-annot-rsocketexchange[Annotated Responders].
[[rsocket-interface-method-parameters]]
=== Method Parameters
@@ -1066,3 +1136,10 @@ method parameters:
Annotated, RSocket exchange methods support return values that are concrete value(s), or
any producer of value(s) that can be adapted to a Reactive Streams `Publisher` via
`ReactiveAdapterRegistry`.
By default, the behavior of RSocket service methods with synchronous (blocking) method
signature depends on response timeout settings of the underlying RSocket `ClientTransport`
as well as RSocket keep-alive settings. `RSocketServiceProxyFactory.Builder` does expose a
`blockTimeout` option that also lets you configure the maximum time to block for a response,
but we recommend configuring timeout values at the RSocket level for more control.
@@ -11,6 +11,7 @@ xref:testing/testcontext-framework/support-classes.adoc#testcontext-junit-jupite
* xref:testing/annotations/integration-junit-jupiter.adoc#integration-testing-annotations-nestedtestconfiguration[`@NestedTestConfiguration`]
* xref:testing/annotations/integration-junit-jupiter.adoc#integration-testing-annotations-junit-jupiter-enabledif[`@EnabledIf`]
* xref:testing/annotations/integration-junit-jupiter.adoc#integration-testing-annotations-junit-jupiter-disabledif[`@DisabledIf`]
* xref:testing/annotations/integration-spring/annotation-disabledinaotmode.adoc[`@DisabledInAotMode`]
[[integration-testing-annotations-junit-jupiter-springjunitconfig]]
== `@SpringJUnitConfig`
@@ -170,8 +171,9 @@ of a test class constructor are autowired from components in the test's
If `@TestConstructor` is not present or meta-present on a test class, the default _test
constructor autowire mode_ will be used. See the tip below for details on how to change
the default mode. Note, however, that a local declaration of `@Autowired` on a
constructor takes precedence over both `@TestConstructor` and the default mode.
the default mode. Note, however, that a local declaration of `@Autowired`,
`@jakarta.inject.Inject`, or `@javax.inject.Inject` on a constructor takes precedence
over both `@TestConstructor` and the default mode.
.Changing the default test constructor autowire mode
[TIP]
@@ -222,6 +224,7 @@ following annotations.
* xref:testing/annotations/integration-spring/annotation-contextconfiguration.adoc[`@ContextConfiguration`]
* xref:testing/annotations/integration-spring/annotation-webappconfiguration.adoc[`@WebAppConfiguration`]
* xref:testing/annotations/integration-spring/annotation-contexthierarchy.adoc[`@ContextHierarchy`]
* xref:testing/annotations/integration-spring/annotation-contextcustomizerfactories.adoc[`@ContextCustomizerFactories`]
* xref:testing/annotations/integration-spring/annotation-activeprofiles.adoc[`@ActiveProfiles`]
* xref:testing/annotations/integration-spring/annotation-testpropertysource.adoc[`@TestPropertySource`]
* xref:testing/annotations/integration-spring/annotation-dynamicpropertysource.adoc[`@DynamicPropertySource`]
@@ -11,6 +11,7 @@ xref:testing/testcontext-framework.adoc[TestContext framework].
* `@BootstrapWith`
* `@ContextConfiguration`
* `@ContextHierarchy`
* `@ContextCustomizerFactories`
* `@ActiveProfiles`
* `@TestPropertySource`
* `@DirtiesContext`
@@ -12,6 +12,7 @@ Spring's testing annotations include the following:
* xref:testing/annotations/integration-spring/annotation-contextconfiguration.adoc[`@ContextConfiguration`]
* xref:testing/annotations/integration-spring/annotation-webappconfiguration.adoc[`@WebAppConfiguration`]
* xref:testing/annotations/integration-spring/annotation-contexthierarchy.adoc[`@ContextHierarchy`]
* xref:testing/annotations/integration-spring/annotation-contextcustomizerfactories.adoc[`@ContextCustomizerFactories`]
* xref:testing/annotations/integration-spring/annotation-activeprofiles.adoc[`@ActiveProfiles`]
* xref:testing/annotations/integration-spring/annotation-testpropertysource.adoc[`@TestPropertySource`]
* xref:testing/annotations/integration-spring/annotation-dynamicpropertysource.adoc[`@DynamicPropertySource`]
@@ -26,4 +27,5 @@ Spring's testing annotations include the following:
* xref:testing/annotations/integration-spring/annotation-sqlconfig.adoc[`@SqlConfig`]
* xref:testing/annotations/integration-spring/annotation-sqlmergemode.adoc[`@SqlMergeMode`]
* xref:testing/annotations/integration-spring/annotation-sqlgroup.adoc[`@SqlGroup`]
* xref:testing/annotations/integration-spring/annotation-disabledinaotmode.adoc[`@DisabledInAotMode`]
@@ -0,0 +1,45 @@
[[spring-testing-annotation-contextcustomizerfactories]]
= `@ContextCustomizerFactories`
`@ContextCustomizerFactories` is used to register `ContextCustomizerFactory`
implementations for a particular test class, its subclasses, and its nested classes. If
you wish to register a factory globally, you should register it via the automatic
discovery mechanism described in
xref:testing/testcontext-framework/ctx-management/context-customizers.adoc[`ContextCustomizerFactory` Configuration].
The following example shows how to register two `ContextCustomizerFactory` implementations:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@ContextConfiguration
@ContextCustomizerFactories({CustomContextCustomizerFactory.class, AnotherContextCustomizerFactory.class}) // <1>
class CustomContextCustomizerFactoryTests {
// class body...
}
----
<1> Register two `ContextCustomizerFactory` implementations.
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@ContextConfiguration
@ContextCustomizerFactories([CustomContextCustomizerFactory::class, AnotherContextCustomizerFactory::class]) // <1>
class CustomContextCustomizerFactoryTests {
// class body...
}
----
<1> Register two `ContextCustomizerFactory` implementations.
======
By default, `@ContextCustomizerFactories` provides support for inheriting factories from
superclasses or enclosing classes. See
xref:testing/testcontext-framework/support-classes.adoc#testcontext-junit-jupiter-nested-test-configuration[`@Nested` test class configuration] and the
{api-spring-framework}/test/context/ContextCustomizerFactories.html[`@ContextCustomizerFactories`
javadoc] for an example and further details.
@@ -0,0 +1,20 @@
[[spring-testing-annotation-disabledinaotmode]]
= `@DisabledInAotMode`
`@DisabledInAotMode` signals that an annotated test class is disabled in Spring AOT
(ahead-of-time) mode, which means that the `ApplicationContext` for the test class will
not be processed for AOT optimizations at build time.
If a test class is annotated with `@DisabledInAotMode`, all other test classes which
specify configuration to load the same `ApplicationContext` must also be annotated with
`@DisabledInAotMode`. Failure to annotate all such test classes will result in an
exception, either at build time or run time.
When used with JUnit Jupiter based tests, `@DisabledInAotMode` also signals that the
annotated test class or test method is disabled when running the test suite in Spring AOT
mode. When applied at the class level, all test methods within that class will be
disabled. In this sense, `@DisabledInAotMode` has semantics similar to those of JUnit
Jupiter's `@DisabledInNativeImage` annotation.
For details on AOT support specific to integration tests, see
xref:testing/testcontext-framework/aot.adoc[Ahead of Time Support for Tests].
@@ -19,7 +19,31 @@ following features.
use an AOT-optimized `ApplicationContext` that participates transparently with the
xref:testing/testcontext-framework/ctx-management/caching.adoc[context cache].
[WARNING]
All tests are enabled in AOT mode by default. However, you can selectively disable an
entire test class or individual test method in AOT mode by annotating it with
xref:testing/annotations/integration-spring/annotation-disabledinaotmode.adoc[`@DisabledInAotMode`].
When using JUnit Jupiter, you may selectively enable or disable tests in a GraalVM native
image via Jupiter's `@EnabledInNativeImage` and `@DisabledInNativeImage` annotations.
Note that `@DisabledInAotMode` also disables the annotated test class or test method when
running within a GraalVM native image, analogous to JUnit Jupiter's
`@DisabledInNativeImage` annotation.
[TIP]
====
By default, if an error is encountered during build-time AOT processing, an exception
will be thrown, and the overall process will fail immediately.
If you would prefer that build-time AOT processing continue after errors are encountered,
you can disable the `failOnError` mode which results in errors being logged at `WARN`
level or with greater detail at `DEBUG` level.
The `failOnError` mode can be disabled from the command line or a build script by setting
a JVM system property named `spring.test.aot.processing.failOnError` to `false`. As an
alternative, you can set the same property via the
xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism.
====
[NOTE]
====
The `@ContextHierarchy` annotation is currently not supported in AOT mode.
====
@@ -112,6 +112,7 @@ advanced use cases.
* xref:testing/testcontext-framework/ctx-management/groovy.adoc[Context Configuration with Groovy Scripts]
* xref:testing/testcontext-framework/ctx-management/javaconfig.adoc[Context Configuration with Component Classes]
* xref:testing/testcontext-framework/ctx-management/mixed-config.adoc[Mixing XML, Groovy Scripts, and Component Classes]
* xref:testing/testcontext-framework/ctx-management/context-customizers.adoc[Context Configuration with Context Customizers]
* xref:testing/testcontext-framework/ctx-management/initializers.adoc[Context Configuration with Context Initializers]
* xref:testing/testcontext-framework/ctx-management/inheritance.adoc[Context Configuration Inheritance]
* xref:testing/testcontext-framework/ctx-management/env-profiles.adoc[Context Configuration with Environment Profiles]
@@ -119,5 +120,6 @@ advanced use cases.
* xref:testing/testcontext-framework/ctx-management/dynamic-property-sources.adoc[Context Configuration with Dynamic Property Sources]
* xref:testing/testcontext-framework/ctx-management/web.adoc[Loading a `WebApplicationContext`]
* xref:testing/testcontext-framework/ctx-management/caching.adoc[Context Caching]
* xref:testing/testcontext-framework/ctx-management/failure-threshold.adoc[Context Failure Threshold]
* xref:testing/testcontext-framework/ctx-management/hierarchies.adoc[Context Hierarchies]
@@ -20,7 +20,7 @@ framework uses the following configuration parameters to build the context cache
* `contextLoader` (from `@ContextConfiguration`)
* `parent` (from `@ContextHierarchy`)
* `activeProfiles` (from `@ActiveProfiles`)
* `propertySourceLocations` (from `@TestPropertySource`)
* `propertySourceDescriptors` (from `@TestPropertySource`)
* `propertySourceProperties` (from `@TestPropertySource`)
* `resourceBasePath` (from `@WebAppConfiguration`)
@@ -0,0 +1,69 @@
[[testcontext-context-customizers]]
= Configuration Configuration with Context Customizers
A `ContextCustomizer` is responsible for customizing the supplied
`ConfigurableApplicationContext` after bean definitions have been loaded into the context
but before the context has been refreshed.
A `ContextCustomizerFactory` is responsible for creating a `ContextCustomizer`, based on
some custom logic which determines if the `ContextCustomizer` is necessary for a given
test class -- for example, based on the presence of a certain annotation. Factories are
invoked after `ContextLoaders` have processed context configuration attributes for a test
class but before the `MergedContextConfiguration` is created.
For example, Spring Framework provides the following `ContextCustomizerFactory`
implementation which is registered by default:
`MockServerContainerContextCustomizerFactory`:: Creates a
`MockServerContainerContextCustomizer` if WebSocket support is present in the classpath
and the test class or one of its enclosing classes is annotated or meta-annotated with
`@WebAppConfiguration`. `MockServerContainerContextCustomizer` instantiates a new
`MockServerContainer` and stores it in the `ServletContext` under the attribute named
`jakarta.websocket.server.ServerContainer`.
[[testcontext-context-customizers-registration]]
== Registering `ContextCustomizerFactory` Implementations
You can register `ContextCustomizerFactory` implementations explicitly for a test class, its
subclasses, and its nested classes by using the `@ContextCustomizerFactories` annotation. See
xref:testing/annotations/integration-spring/annotation-contextcustomizerfactories.adoc[annotation support]
and the javadoc for
{api-spring-framework}/test/context/ContextCustomizerFactories.html[`@ContextCustomizerFactories`]
for details and examples.
[[testcontext-context-customizers-automatic-discovery]]
== Automatic Discovery of Default `ContextCustomizerFactory` Implementations
Registering `ContextCustomizerFactory` implementations by using `@ContextCustomizerFactories` is
suitable for custom factories that are used in limited testing scenarios. However, it can
become cumbersome if a custom factory needs to be used across an entire test suite. This
issue is addressed through support for automatic discovery of default
`ContextCustomizerFactory` implementations through the `SpringFactoriesLoader` mechanism.
Specifically, the modules that make up the testing support in Spring Framework and Spring
Boot declare all core default `ContextCustomizerFactory` implementations under the
`org.springframework.test.context.ContextCustomizerFactory` key in their
`META-INF/spring.factories` properties files. Third-party frameworks and developers can
contribute their own `ContextCustomizerFactory` implementations to the list of default
factories in the same manner through their own `META-INF/spring.factories` properties
files.
[[testcontext-context-customizers-merging]]
== Merging `ContextCustomizerFactory` Implementations
If a custom `ContextCustomizerFactory` is registered via `@ContextCustomizerFactories`, it
will be _merged_ with the default factories that have been registered using the aforementioned
xref:testing/testcontext-framework/ctx-management/context-customizers.adoc#testcontext-context-customizers-automatic-discovery[automatic discovery mechanism].
The merging algorithm ensures that duplicates are removed from the list and that locally
declared factories are appended to the list of default factories when merged.
[TIP]
====
To replace the default factories for a test class, its subclasses, and its nested
classes, you can set the `mergeMode` attribute of `@ContextCustomizerFactories` to
`MergeMode.REPLACE_DEFAULTS`.
====
@@ -0,0 +1,23 @@
[[testcontext-ctx-management-failure-threshold]]
= Context Failure Threshold
As of Spring Framework 6.1, a context _failure threshold_ policy is in place which helps
avoid repeated attempts to load a failing `ApplicationContext`. By default, the failure
threshold is set to `1` which means that only one attempt will be made to load an
`ApplicationContext` for a given context cache key (see
xref:testing/testcontext-framework/ctx-management/caching.adoc[Context Caching]). Any
subsequent attempt to load the `ApplicationContext` for the same context cache key will
result in an immediate `IllegalStateException` with an error message which explains that
the attempt was preemptively skipped. This behavior allows individual test classes and
test suites to fail faster by avoiding repeated attempts to load an `ApplicationContext`
that will never successfully load -- for example, due to a configuration error or a missing
external resource that prevents the context from loading in the current environment.
You can configure the context failure threshold from the command line or a build script
by setting a JVM system property named `spring.test.context.failure.threshold` with a
positive integer value. As an alternative, you can set the same property via the
xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism.
NOTE: If you wish to effectively disable the context failure threshold, you can set the
property to a very large value. For example, from the command line you could set the
system property via `-Dspring.test.context.failure.threshold=1000000`.
@@ -16,7 +16,7 @@ SPI, but `@TestPropertySource` is not supported with implementations of the olde
`ContextLoader` SPI.
Implementations of `SmartContextLoader` gain access to merged test property source values
through the `getPropertySourceLocations()` and `getPropertySourceProperties()` methods in
through the `getPropertySourceDescriptors()` and `getPropertySourceProperties()` methods in
`MergedContextConfiguration`.
====
@@ -26,17 +26,23 @@ through the `getPropertySourceLocations()` and `getPropertySourceProperties()` m
You can configure test properties files by using the `locations` or `value` attribute of
`@TestPropertySource`.
Both traditional and XML-based properties file formats are supported -- for example,
`"classpath:/com/example/test.properties"` or `"file:///path/to/file.xml"`.
By default, both traditional and XML-based `java.util.Properties` file formats are
supported -- for example, `"classpath:/com/example/test.properties"` or
`"file:///path/to/file.xml"`. As of Spring Framework 6.1, you can configure a custom
`PropertySourceFactory` via the `factory` attribute in `@TestPropertySource` in order to
support a different file format such as JSON, YAML, etc.
Each path is interpreted as a Spring `Resource`. A plain path (for example,
`"test.properties"`) is treated as a classpath resource that is relative to the package
in which the test class is defined. A path starting with a slash is treated as an
absolute classpath resource (for example: `"/org/example/test.xml"`). A path that
references a URL (for example, a path prefixed with `classpath:`, `file:`, or `http:`) is
loaded by using the specified resource protocol. Resource location wildcards (such as
`{asterisk}{asterisk}/{asterisk}.properties`) are not permitted: Each location must
evaluate to exactly one `.properties` or `.xml` resource.
loaded by using the specified resource protocol.
Property placeholders in paths (such as `${...}`) will be resolved against the `Environment`.
As of Spring Framework 6.1, resource location patterns are also supported — for
example, `"classpath*:/config/*.properties"`.
The following example uses a test properties file:
@@ -80,6 +86,20 @@ a Java properties file:
* `key:value`
* `key value`
[TIP]
====
Although properties can be defined using any of the above syntax variants and any number
of spaces between the key and the value, it is recommended that you use one syntax
variant and consistent spacing within your test suite — for example, consider always
using `key = value` instead of `key= value`, `key=value`, etc. Similarly, if you define
inlined properties using text blocks you should consistently use text blocks for inlined
properties throughout your test suite.
The reason is that the exact strings you provide will be used to determine the key for
the context cache. Consequently, to benefit from the context cache you must ensure that
you define inlined properties consistently.
====
The following example sets two inlined properties:
[tabs]
@@ -89,24 +109,61 @@ Java::
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@ContextConfiguration
@TestPropertySource(properties = {"timezone = GMT", "port: 4242"}) // <1>
@TestPropertySource(properties = {"timezone = GMT", "port = 4242"}) // <1>
class MyIntegrationTests {
// class body...
}
----
<1> Setting two properties by using two variations of the key-value syntax.
<1> Setting two properties via an array of strings.
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@ContextConfiguration
@TestPropertySource(properties = ["timezone = GMT", "port: 4242"]) // <1>
@TestPropertySource(properties = ["timezone = GMT", "port = 4242"]) // <1>
class MyIntegrationTests {
// class body...
}
----
<1> Setting two properties by using two variations of the key-value syntax.
<1> Setting two properties via an array of strings.
======
As of Spring Framework 6.1, you can use _text blocks_ to define multiple inlined
properties in a single `String`. The following example sets two inlined properties using
a text block:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@ContextConfiguration
@TestPropertySource(properties = """
timezone = GMT
port = 4242
""") // <1>
class MyIntegrationTests {
// class body...
}
----
<1> Setting two properties via a text block.
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@ContextConfiguration
@TestPropertySource(properties = ["""
timezone = GMT
port = 4242
"""]) // <1>
class MyIntegrationTests {
// class body...
}
----
<1> Setting two properties via a text block.
======
[NOTE]
@@ -166,7 +223,7 @@ Java::
@ContextConfiguration
@TestPropertySource(
locations = "/test.properties",
properties = {"timezone = GMT", "port: 4242"}
properties = {"timezone = GMT", "port = 4242"}
)
class MyIntegrationTests {
// class body...
@@ -179,7 +236,7 @@ Kotlin::
----
@ContextConfiguration
@TestPropertySource("/test.properties",
properties = ["timezone = GMT", "port: 4242"]
properties = ["timezone = GMT", "port = 4242"]
)
class MyIntegrationTests {
// class body...
@@ -95,13 +95,22 @@ In addition to the aforementioned mechanisms for running SQL scripts programmati
you can declaratively configure SQL scripts in the Spring TestContext Framework.
Specifically, you can declare the `@Sql` annotation on a test class or test method to
configure individual SQL statements or the resource paths to SQL scripts that should be
run against a given database before or after an integration test method. Support for
`@Sql` is provided by the `SqlScriptsTestExecutionListener`, which is enabled by default.
run against a given database before or after an integration test class or test method.
Support for `@Sql` is provided by the `SqlScriptsTestExecutionListener`, which is enabled
by default.
NOTE: Method-level `@Sql` declarations override class-level declarations by default. As
of Spring Framework 5.2, however, this behavior may be configured per test class or per
test method via `@SqlMergeMode`. See
xref:testing/testcontext-framework/executing-sql.adoc#testcontext-executing-sql-declaratively-script-merging[Merging and Overriding Configuration with `@SqlMergeMode`] for further details.
[NOTE]
====
Method-level `@Sql` declarations override class-level declarations by default, but this
behavior may be configured per test class or per test method via `@SqlMergeMode`. See
xref:testing/testcontext-framework/executing-sql.adoc#testcontext-executing-sql-declaratively-script-merging[Merging and Overriding Configuration with `@SqlMergeMode`]
for further details.
However, this does not apply to class-level declarations configured for the
`BEFORE_TEST_CLASS` or `AFTER_TEST_CLASS` execution phases. Such declarations cannot be
overridden, and the corresponding scripts and statements will be executed once per class
in addition to any method-level scripts and statements.
====
[[testcontext-executing-sql-declaratively-script-resources]]
=== Path Resource Semantics
@@ -174,17 +183,25 @@ script, depending on where `@Sql` is declared. If a default cannot be detected,
defined in the class `com.example.MyTest`, the corresponding default script is
`classpath:com/example/MyTest.testMethod.sql`.
[[testcontext-executing-sql-declaratively-logging]]
=== Logging SQL Scripts and Statements
If you want to see which SQL scripts are being executed, set the
`org.springframework.test.context.jdbc` logging category to `DEBUG`.
If you want to see which SQL statements are being executed, set the
`org.springframework.jdbc.datasource.init` logging category to `DEBUG`.
[[testcontext-executing-sql-declaratively-multiple-annotations]]
=== Declaring Multiple `@Sql` Sets
If you need to configure multiple sets of SQL scripts for a given test class or test
method but with different syntax configuration, different error handling rules, or
different execution phases per set, you can declare multiple instances of `@Sql`. With
Java 8, you can use `@Sql` as a repeatable annotation. Otherwise, you can use the
`@SqlGroup` annotation as an explicit container for declaring multiple instances of
`@Sql`.
different execution phases per set, you can declare multiple instances of `@Sql`. You can
either use `@Sql` as a repeatable annotation, or you can use the `@SqlGroup` annotation
as an explicit container for declaring multiple instances of `@Sql`.
The following example shows how to use `@Sql` as a repeatable annotation with Java 8:
The following example shows how to use `@Sql` as a repeatable annotation:
[tabs]
======
@@ -204,7 +221,12 @@ Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
// Repeatable annotations with non-SOURCE retention are not yet supported by Kotlin
@Test
@Sql("/test-schema.sql", config = SqlConfig(commentPrefix = "`"))
@Sql("/test-user-data.sql")
fun userTest() {
// run code that uses the test schema and test data
}
----
======
@@ -212,9 +234,8 @@ In the scenario presented in the preceding example, the `test-schema.sql` script
different syntax for single-line comments.
The following example is identical to the preceding example, except that the `@Sql`
declarations are grouped together within `@SqlGroup`. With Java 8 and above, the use of
`@SqlGroup` is optional, but you may need to use `@SqlGroup` for compatibility with
other JVM languages such as Kotlin.
declarations are grouped together within `@SqlGroup`. The use of `@SqlGroup` is optional,
but you may need to use `@SqlGroup` for compatibility with other JVM languages.
[tabs]
======
@@ -239,7 +260,8 @@ Kotlin::
@Test
@SqlGroup(
Sql("/test-schema.sql", config = SqlConfig(commentPrefix = "`")),
Sql("/test-user-data.sql"))
Sql("/test-user-data.sql")
)
fun userTest() {
// Run code that uses the test schema and test data
}
@@ -249,10 +271,10 @@ Kotlin::
[[testcontext-executing-sql-declaratively-script-execution-phases]]
=== Script Execution Phases
By default, SQL scripts are run before the corresponding test method. However, if
you need to run a particular set of scripts after the test method (for example, to clean
up database state), you can use the `executionPhase` attribute in `@Sql`, as the
following example shows:
By default, SQL scripts are run before the corresponding test method. However, if you
need to run a particular set of scripts after the test method (for example, to clean up
database state), you can set the `executionPhase` attribute in `@Sql` to
`AFTER_TEST_METHOD`, as the following example shows:
[tabs]
======
@@ -281,12 +303,11 @@ Kotlin::
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@Test
@SqlGroup(
Sql("create-test-data.sql",
config = SqlConfig(transactionMode = ISOLATED)),
Sql("delete-test-data.sql",
config = SqlConfig(transactionMode = ISOLATED),
executionPhase = AFTER_TEST_METHOD))
@Sql("create-test-data.sql",
config = SqlConfig(transactionMode = ISOLATED))
@Sql("delete-test-data.sql",
config = SqlConfig(transactionMode = ISOLATED),
executionPhase = AFTER_TEST_METHOD)
fun userTest() {
// run code that needs the test data to be committed
// to the database outside of the test's transaction
@@ -294,9 +315,60 @@ Kotlin::
----
======
Note that `ISOLATED` and `AFTER_TEST_METHOD` are statically imported from
NOTE: `ISOLATED` and `AFTER_TEST_METHOD` are statically imported from
`Sql.TransactionMode` and `Sql.ExecutionPhase`, respectively.
As of Spring Framework 6.1, it is possible to run a particular set of scripts before or
after the test class by setting the `executionPhase` attribute in a class-level `@Sql`
declaration to `BEFORE_TEST_CLASS` or `AFTER_TEST_CLASS`, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@SpringJUnitConfig
@Sql(scripts = "/test-schema.sql", executionPhase = BEFORE_TEST_CLASS)
class DatabaseTests {
@Test
void emptySchemaTest() {
// run code that uses the test schema without any test data
}
@Test
@Sql("/test-user-data.sql")
void userTest() {
// run code that uses the test schema and test data
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@SpringJUnitConfig
@Sql("/test-schema.sql", executionPhase = BEFORE_TEST_CLASS)
class DatabaseTests {
@Test
fun emptySchemaTest() {
// run code that uses the test schema without any test data
}
@Test
@Sql("/test-user-data.sql")
fun userTest() {
// run code that uses the test schema and test data
}
}
----
======
NOTE: `BEFORE_TEST_CLASS` is statically imported from `Sql.ExecutionPhase`.
[[testcontext-executing-sql-declaratively-script-configuration]]
=== Script Configuration with `@SqlConfig`
@@ -324,7 +396,7 @@ individual attributes in {api-spring-framework}/test/context/jdbc/Sql.html[`@Sql
{api-spring-framework}/test/context/jdbc/SqlConfig.html[`@SqlConfig`] for details.
[[testcontext-executing-sql-declaratively-tx]]
*Transaction management for `@Sql`*
==== Transaction management for `@Sql`
By default, the `SqlScriptsTestExecutionListener` infers the desired transaction
semantics for scripts configured by using `@Sql`. Specifically, SQL scripts are run
@@ -177,7 +177,7 @@ following features above and beyond the feature set that Spring supports for JUn
TestNG:
* Dependency injection for test constructors, test methods, and test lifecycle callback
methods. See xref:testing/testcontext-framework/support-classes.adoc#testcontext-junit-jupiter-di[Dependency Injection with `SpringExtension`] for further details.
methods. See xref:testing/testcontext-framework/support-classes.adoc#testcontext-junit-jupiter-di[Dependency Injection with the `SpringExtension`] for further details.
* Powerful support for link:https://junit.org/junit5/docs/current/user-guide/#extensions-conditions[conditional
test execution] based on SpEL expressions, environment variables, system properties,
and so on. See the documentation for `@EnabledIf` and `@DisabledIf` in
@@ -310,17 +310,19 @@ See the documentation for `@SpringJUnitConfig` and `@SpringJUnitWebConfig` in
xref:testing/annotations/integration-junit-jupiter.adoc[Spring JUnit Jupiter Testing Annotations] for further details.
[[testcontext-junit-jupiter-di]]
=== Dependency Injection with `SpringExtension`
=== Dependency Injection with the `SpringExtension`
`SpringExtension` implements the
The `SpringExtension` implements the
link:https://junit.org/junit5/docs/current/user-guide/#extensions-parameter-resolution[`ParameterResolver`]
extension API from JUnit Jupiter, which lets Spring provide dependency injection for test
constructors, test methods, and test lifecycle callback methods.
Specifically, `SpringExtension` can inject dependencies from the test's
Specifically, the `SpringExtension` can inject dependencies from the test's
`ApplicationContext` into test constructors and methods that are annotated with
`@BeforeAll`, `@AfterAll`, `@BeforeEach`, `@AfterEach`, `@Test`, `@RepeatedTest`,
`@ParameterizedTest`, and others.
Spring's `@BeforeTransaction` and `@AfterTransaction` or JUnit's `@BeforeAll`,
`@AfterAll`, `@BeforeEach`, `@AfterEach`, `@Test`, `@RepeatedTest`, `@ParameterizedTest`,
and others.
[[testcontext-junit-jupiter-di-constructor]]
==== Constructor Injection
@@ -534,7 +536,7 @@ The _Spring TestContext Framework_ has supported the use of test-related annotat
Framework 5.3 class-level test configuration annotations were not _inherited_ from
enclosing classes like they are from superclasses.
Spring Framework 5.3 introduces first-class support for inheriting test class
Spring Framework 5.3 introduced first-class support for inheriting test class
configuration from enclosing classes, and such configuration will be inherited by
default. To change from the default `INHERIT` mode to `OVERRIDE` mode, you may annotate
an individual `@Nested` test class with
@@ -295,14 +295,56 @@ behavior after your test runs (if the test was configured to commit the transact
`TransactionalTestExecutionListener` supports the `@BeforeTransaction` and
`@AfterTransaction` annotations for exactly such scenarios. You can annotate any `void`
method in a test class or any `void` default method in a test interface with one of these
annotations, and the `TransactionalTestExecutionListener` ensures that your before
transaction method or after transaction method runs at the appropriate time.
annotations, and the `TransactionalTestExecutionListener` ensures that your
before-transaction method or after-transaction method runs at the appropriate time.
TIP: Any before methods (such as methods annotated with JUnit Jupiter's `@BeforeEach`)
and any after methods (such as methods annotated with JUnit Jupiter's `@AfterEach`) are
run within a transaction. In addition, methods annotated with `@BeforeTransaction` or
`@AfterTransaction` are not run for test methods that are not configured to run within a
transaction.
[NOTE]
====
Generally speaking, `@BeforeTransaction` and `@AfterTransaction` methods must not accept
any arguments.
However, as of Spring Framework 6.1, for tests using the
xref:testing/testcontext-framework/support-classes.adoc#testcontext-junit-jupiter-extension[`SpringExtension`]
with JUnit Jupiter, `@BeforeTransaction` and `@AfterTransaction` methods may optionally
accept arguments which will be resolved by any registered JUnit `ParameterResolver`
extension such as the `SpringExtension`. This means that JUnit-specific arguments like
`TestInfo` or beans from the test's `ApplicationContext` may be provided to
`@BeforeTransaction` and `@AfterTransaction` methods, as demonstrated in the following
example.
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@BeforeTransaction
void verifyInitialDatabaseState(@Autowired DataSource dataSource) {
// Use the DataSource to verify the initial state before a transaction is started
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@BeforeTransaction
fun verifyInitialDatabaseState(@Autowired dataSource: DataSource) {
// Use the DataSource to verify the initial state before a transaction is started
}
----
======
====
[TIP]
====
Any before methods (such as methods annotated with JUnit Jupiter's `@BeforeEach`) and any
after methods (such as methods annotated with JUnit Jupiter's `@AfterEach`) are run
within the test-managed transaction for a transactional test method.
Similarly, methods annotated with `@BeforeTransaction` or `@AfterTransaction` are only
run for transactional test methods.
====
[[testcontext-tx-mgr-config]]
== Configuring a Transaction Manager
@@ -148,5 +148,75 @@ Kotlin::
----
======
The example below demonstrates how to use the `ExchangeFilterFunction` interface to create
a custom filter class that helps with computing a `Content-Length` header for `PUT` and `POST`
`multipart/form-data` requests using buffering.
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class MultipartExchangeFilterFunction implements ExchangeFilterFunction {
@Override
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
if (MediaType.MULTIPART_FORM_DATA.includes(request.headers().getContentType())
&& (request.method() == HttpMethod.PUT || request.method() == HttpMethod.POST)) {
return next.exchange(ClientRequest.from(request).body((outputMessage, context) ->
request.body().insert(new BufferingDecorator(outputMessage), context)).build()
);
} else {
return next.exchange(request);
}
}
private static final class BufferingDecorator extends ClientHttpRequestDecorator {
private BufferingDecorator(ClientHttpRequest delegate) {
super(delegate);
}
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
return DataBufferUtils.join(body).flatMap(buffer -> {
getHeaders().setContentLength(buffer.readableByteCount());
return super.writeWith(Mono.just(buffer));
});
}
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class MultipartExchangeFilterFunction : ExchangeFilterFunction {
override fun filter(request: ClientRequest, next: ExchangeFunction): Mono<ClientResponse> {
return if (MediaType.MULTIPART_FORM_DATA.includes(request.headers().getContentType())
&& (request.method() == HttpMethod.PUT || request.method() == HttpMethod.POST)) {
next.exchange(ClientRequest.from(request)
.body { message, context -> request.body().insert(BufferingDecorator(message), context) }
.build())
}
else {
next.exchange(request)
}
}
private class BufferingDecorator(delegate: ClientHttpRequest) : ClientHttpRequestDecorator(delegate) {
override fun writeWith(body: Publisher<out DataBuffer>): Mono<Void> {
return DataBufferUtils.join(body)
.flatMap {
headers.contentLength = it.readableByteCount().toLong()
super.writeWith(Mono.just(it))
}
}
}
}
----
======
@@ -67,52 +67,44 @@ from an existing `ProblemDetail`. This could be done centrally, e.g. from an
[[webflux-ann-rest-exceptions-i18n]]
== Internationalization
== Customization and i18n
[.small]#xref:web/webmvc/mvc-ann-rest-exceptions.adoc#mvc-ann-rest-exceptions-i18n[See equivalent in the Servlet stack]#
It is a common requirement to internationalize error response details, and good practice
to customize the problem details for Spring WebFlux exceptions. This is supported as follows:
It is a common requirement to customize and internationalize error response details.
It is also good practice to customize the problem details for Spring WebFlux exceptions
to avoid revealing implementation details. This section describes the support for that.
- Each `ErrorResponse` exposes a message code and arguments to resolve the "detail" field
through a xref:core/beans/context-introduction.adoc#context-functionality-messagesource[MessageSource].
The actual message code value is parameterized with placeholders, e.g.
`+"HTTP method {0} not supported"+` to be expanded from the arguments.
- Each `ErrorResponse` also exposes a message code to resolve the "title" field.
- `ResponseEntityExceptionHandler` uses the message code and arguments to resolve the
"detail" and the "title" fields.
An `ErrorResponse` exposes message codes for "type", "title", and "detail", as well as
message code arguments for the "detail" field. `ResponseEntityExceptionHandler` resolves
these through a xref:core/beans/context-introduction.adoc#context-functionality-messagesource[MessageSource]
and updates the corresponding `ProblemDetail` fields accordingly.
By default, the message code for the "detail" field is "problemDetail." + the fully
qualified exception class name. Some exceptions may expose additional message codes in
which case a suffix is added to the default message code. The table below lists message
arguments and codes for Spring WebFlux exceptions:
The default strategy for message codes follows the pattern:
`problemDetail.[type|title|detail].[fully qualified exception class name]`
An `ErrorResponse` may expose more than one message code, typically adding a suffix
to the default message code. The table below lists message codes, and arguments for
Spring WebFlux exceptions:
[[webflux-ann-rest-exceptions-codes]]
[cols="1,1,2", options="header"]
|===
| Exception | Message Code | Message Code Arguments
| `UnsupportedMediaTypeStatusException`
| `HandlerMethodValidationException`
| (default)
| `+{0}+` the media type that is not supported, `+{1}+` list of supported media types
| `+{0}+` list all validation errors.
Message codes and arguments for each error are also resolved via `MessageSource`.
| `UnsupportedMediaTypeStatusException`
| (default) + ".parseError"
|
| `MethodNotAllowedException`
| (default)
| `+{0}+` the current HTTP method, `+{1}+` the list of supported HTTP methods
| `MissingRequestValueException`
| (default)
| `+{0}+` a label for the value (e.g. "request header", "cookie value", ...), `+{1}+` the value name
| `UnsatisfiedRequestParameterException`
| (default)
| `+{0}+` the list of parameter conditions
| `WebExchangeBindException`
| (default)
| `+{0}+` the list of global errors, `+{1}+` the list of field errors.
Message codes and arguments for each error within the `BindingResult` are also resolved
via `MessageSource`.
| `NotAcceptableStatusException`
| (default)
| `+{0}+` list of supported media types
@@ -125,14 +117,32 @@ via `MessageSource`.
| (default)
| `+{0}+` the failure reason provided to the class constructor
| `MethodNotAllowedException`
| `UnsupportedMediaTypeStatusException`
| (default)
| `+{0}+` the current HTTP method, `+{1}+` the list of supported HTTP methods
| `+{0}+` the media type that is not supported, `+{1}+` list of supported media types
| `UnsupportedMediaTypeStatusException`
| (default) + ".parseError"
|
| `UnsatisfiedRequestParameterException`
| (default)
| `+{0}+` the list of parameter conditions
| `WebExchangeBindException`
| (default)
| `+{0}+` the list of global errors, `+{1}+` the list of field errors.
Message codes and arguments for each error are also resolved via `MessageSource`.
|===
By default, the message code for the "title" field is "problemDetail.title." + the fully
qualified exception class name.
NOTE: Unlike other exceptions, the message arguments for
`WebExchangeBindException` and `HandlerMethodValidationException` are based on a list of
`MessageSourceResolvable` errors that can also be customized through a
xref:core/beans/context-introduction.adoc#context-functionality-messagesource[MessageSource]
resource bundle. See
xref:core/validation/beanvalidation.adoc#validation-beanvalidation-spring-method-i18n[Customizing Validation Errors]
for more details.
@@ -700,9 +700,8 @@ Java::
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer
.setUseCaseSensitiveMatch(true)
.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController.class));
configurer.addPathPrefix(
"/api", HandlerTypePredicate.forAnnotation(RestController.class));
}
}
----
@@ -717,9 +716,8 @@ Kotlin::
@Override
fun configurePathMatch(configurer: PathMatchConfigurer) {
configurer
.setUseCaseSensitiveMatch(true)
.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController::class.java))
configurer.addPathPrefix(
"/api", HandlerTypePredicate.forAnnotation(RestController::class.java))
}
}
----
@@ -740,6 +738,59 @@ reliance on it.
[[webflux-config-blocking-execution]]
== Blocking Execution
The WebFlux Java config allows you to customize blocking execution in WebFlux.
You can have blocking controller methods called on a separate thread by providing
an `AsyncTaskExecutor` such as the
{api-spring-framework}/core/task/VirtualThreadTaskExecutor.html[`VirtualThreadTaskExecutor`]
as follows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureBlockingExecution(BlockingExecutionConfigurer configurer) {
AsyncTaskExecutor executor = ...
configurer.setExecutor(executor);
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
@Override
fun configureBlockingExecution(configurer: BlockingExecutionConfigurer) {
val executor = ...
configurer.setExecutor(executor)
}
}
----
======
By default, controller methods whose return type is not recognized by the configured
`ReactiveAdapterRegistry` are considered blocking, but you can set a custom controller
method predicate via `BlockingExecutionConfigurer`.
[[webflux-config-websocket-service]]
== WebSocketService
@@ -3,23 +3,21 @@
[.small]#xref:web/webmvc/mvc-controller/ann-initbinder.adoc[See equivalent in the Servlet stack]#
`@Controller` or `@ControllerAdvice` classes can have `@InitBinder` methods, to
initialize instances of `WebDataBinder`. Those, in turn, are used to:
`@Controller` or `@ControllerAdvice` classes can have `@InitBinder` methods to
initialize `WebDataBinder` instances that in turn can:
* Bind request parameters (that is, form data or query) to a model object.
* Convert `String`-based request values (such as request parameters, path variables,
headers, cookies, and others) to the target type of controller method arguments.
* Format model object values as `String` values when rendering HTML forms.
* Bind request parameters to a model object.
* Convert request values from string to object property types.
* Format model object properties as strings when rendering HTML forms.
`@InitBinder` methods can register controller-specific `java.beans.PropertyEditor` or
Spring `Converter` and `Formatter` components. In addition, you can use the
xref:web/webflux/config.adoc#webflux-config-conversion[WebFlux Java configuration] to register `Converter` and
`Formatter` types in a globally shared `FormattingConversionService`.
In an `@Controller`, `DataBinder` customizations apply locally within the controller,
or even to a specific model attribute referenced by name through the annotation.
In an `@ControllerAdvice` customizations can apply to all or a subset of controllers.
`@InitBinder` methods support many of the same arguments that `@RequestMapping` methods
do, except for `@ModelAttribute` (command object) arguments. Typically, they are declared
with a `WebDataBinder` argument, for registrations, and a `void` return value.
The following example uses the `@InitBinder` annotation:
You can register `PropertyEditor`, `Converter`, and `Formatter` components in the
`DataBinder` for type conversion. Alternatively, you can use the
xref:web/webflux/config.adoc#webflux-config-conversion[WebFlux config] to register
`Converter` and `Formatter` components in a globally shared `FormattingConversionService`.
--
[tabs]
@@ -112,4 +110,5 @@ Kotlin::
== Model Design
[.small]#xref:web/webmvc/mvc-controller/ann-initbinder.adoc#mvc-ann-initbinder-model-design[See equivalent in the Servlet stack]#
include::partial$web/web-data-binding-model-design.adoc[]
@@ -3,11 +3,8 @@
[.small]#xref:web/webmvc/mvc-controller/ann-methods/modelattrib-method-args.adoc[See equivalent in the Servlet stack]#
You can use the `@ModelAttribute` annotation on a method argument to access an attribute from the
model or have it instantiated if not present. The model attribute is also overlaid with
the values of query parameters and form fields whose names match to field names. This is
referred to as data binding, and it saves you from having to deal with parsing and
converting individual query parameters and form fields. The following example binds an instance of `Pet`:
The `@ModelAttribute` method parameter annotation binds request parameters onto a model
object. For example:
[tabs]
======
@@ -18,7 +15,7 @@ Java::
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute Pet pet) { } // <1>
----
<1> Bind an instance of `Pet`.
<1> Bind to an instance of `Pet`.
Kotlin::
+
@@ -27,28 +24,66 @@ Kotlin::
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@ModelAttribute pet: Pet): String { } // <1>
----
<1> Bind an instance of `Pet`.
<1> Bind to an instance of `Pet`.
======
The `Pet` instance in the preceding example is resolved as follows:
The `Pet` instance may be:
* From the model if already added through xref:web/webflux/controller/ann-modelattrib-methods.adoc[`Model`].
* From the HTTP session through xref:web/webflux/controller/ann-methods/sessionattributes.adoc[`@SessionAttributes`].
* From the invocation of a default constructor.
* From the invocation of a "`primary constructor`" with arguments that match query
parameters or form fields. Argument names are determined through JavaBeans
`@ConstructorProperties` or through runtime-retained parameter names in the bytecode.
* Accessed from the model where it could have been added by a
xref:web/webflux/controller/ann-modelattrib-methods.adoc[`Model`].
* Accessed from the HTTP session if the model attribute was listed in
the class-level xref:web/webflux/controller/ann-methods/sessionattributes.adoc[`@SessionAttributes`].
* Instantiated through a default constructor.
* Instantiated through a "`primary constructor`" with arguments that match to Servlet
request parameters. Argument names are determined through runtime-retained parameter
names in the bytecode.
After the model attribute instance is obtained, data binding is applied. The
`WebExchangeDataBinder` class matches names of query parameters and form fields to field
names on the target `Object`. Matching fields are populated after type conversion is applied
where necessary. For more on data binding (and validation), see
xref:web/webmvc/mvc-config/validation.adoc[Validation]. For more on customizing data binding, see
xref:web/webflux/controller/ann-initbinder.adoc[`DataBinder`].
By default, both constructor and property
xref:core/validation/beans-beans.adoc#beans-binding[data binding] are applied. However,
model object design requires careful consideration, and for security reasons it is
recommended either to use an object tailored specifically for web binding, or to apply
constructor binding only. If property binding must still be used, then _allowedFields_
patterns should be set to limit which properties can be set. For further details on this
and example configuration, see
xref:web/webflux/controller/ann-initbinder.adoc#webflux-ann-initbinder-model-design[model design].
Data binding can result in errors. By default, a `WebExchangeBindException` is raised, but,
to check for such errors in the controller method, you can add a `BindingResult` argument
immediately next to the `@ModelAttribute`, as the following example shows:
When using constructor binding, you can customize request parameter names through an
`@BindParam` annotation. For example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
class Account {
private final String firstName;
public Account(@BindParam("first-name") String firstName) {
this.firstName = firstName;
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class Account(@BindParam("first-name") val firstName: String)
----
======
NOTE: The `@BindParam` may also be placed on the fields that correspond to constructor
parameters. While `@BindParam` is supported out of the box, you can also use a
different annotation by setting a `DataBinder.NameResolver` on `DataBinder`
WebFlux, unlike Spring MVC, supports reactive types in the model, e.g. `Mono<Account>`.
You can declare a `@ModelAttribute` argument with or without a reactive type wrapper, and
it will be resolved accordingly to the actual value.
If data binding results in errors, by default a `WebExchangeBindException` is raised,
but you can also add a `BindingResult` argument immediately next to the `@ModelAttribute`
in order to handle such errors in the controller method. For example:
[tabs]
======
@@ -81,49 +116,9 @@ Kotlin::
<1> Adding a `BindingResult`.
======
You can automatically apply validation after data binding by adding the
`jakarta.validation.Valid` annotation or Spring's `@Validated` annotation (see also
xref:core/validation/beanvalidation.adoc[Bean Validation] and
xref:web/webmvc/mvc-config/validation.adoc[Spring validation]). The following example uses the `@Valid` annotation:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult result) { // <1>
if (result.hasErrors()) {
return "petForm";
}
// ...
}
----
<1> Using `@Valid` on a model attribute argument.
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@Valid @ModelAttribute("pet") pet: Pet, result: BindingResult): String { // <1>
if (result.hasErrors()) {
return "petForm"
}
// ...
}
----
<1> Using `@Valid` on a model attribute argument.
======
Spring WebFlux, unlike Spring MVC, supports reactive types in the model -- for example,
`Mono<Account>` or `io.reactivex.Single<Account>`. You can declare a `@ModelAttribute` argument
with or without a reactive type wrapper, and it will be resolved accordingly,
to the actual value if necessary. However, note that, to use a `BindingResult`
argument, you must declare the `@ModelAttribute` argument before it without a reactive
type wrapper, as shown earlier. Alternatively, you can handle any errors through the
reactive type, as the following example shows:
To use a `BindingResult` argument, you must declare the `@ModelAttribute` argument before
it without a reactive type wrapper. If you want to use the reactive, you can handle errors
directly through it. For example:
[tabs]
======
@@ -160,10 +155,49 @@ Kotlin::
----
======
Note that use of `@ModelAttribute` is optional -- for example, to set its attributes.
By default, any argument that is not a simple value type (as determined by
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty])
and is not resolved by any other argument resolver is treated as if it were annotated
with `@ModelAttribute`.
You can automatically apply validation after data binding by adding the
`jakarta.validation.Valid` annotation or Spring's `@Validated` annotation (see
xref:core/validation/beanvalidation.adoc[Bean Validation] and
xref:web/webmvc/mvc-config/validation.adoc[Spring validation]). For example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult result) { // <1>
if (result.hasErrors()) {
return "petForm";
}
// ...
}
----
<1> Using `@Valid` on a model attribute argument.
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@Valid @ModelAttribute("pet") pet: Pet, result: BindingResult): String { // <1>
if (result.hasErrors()) {
return "petForm"
}
// ...
}
----
<1> Using `@Valid` on a model attribute argument.
======
If method validation applies because other parameters have `@Constraint` annotations,
then `HandlerMethodValidationException` would be raised instead. See the section on
controller method xref:web/webmvc/mvc-controller/ann-validation.adoc[Validation].
TIP: Using `@ModelAttribute` is optional. By default, any argument that is not a simple
value type as determined by
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty]
_AND_ that is not resolved by any other argument resolver is treated as an `@ModelAttribute`.
@@ -176,6 +176,10 @@ Kotlin::
======
--
If method validation applies because other parameters have `@Constraint` annotations,
then `HandlerMethodValidationException` is raised instead. See the section on
xref:web/webflux/controller/ann-validation.adoc[Validation].
To access all multipart data as a `MultiValueMap`, you can use `@RequestBody`,
as the following example shows:
@@ -306,5 +310,3 @@ file upload.
Received part events can also be relayed to another service by using the `WebClient`.
See xref:web/webflux-webclient/client-body.adoc#webflux-client-body-multipart[Multipart Data].
@@ -89,4 +89,33 @@ Kotlin::
----
======
You can also declare an `Errors` parameter for access to validation errors, but in
that case the request body must not be a `Mono`, and will be resolved first:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@PostMapping("/accounts")
public void handle(@Valid @RequestBody Account account, Errors errors) {
// use one of the onError* operators...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@PostMapping("/accounts")
fun handle(@Valid @RequestBody account: Mono<Account>) {
// ...
}
----
======
If method validation applies because other parameters have `@Constraint` annotations,
then `HandlerMethodValidationException` is raised instead. For more details, see the
section on xref:web/webflux/controller/ann-validation.adoc[Validation].
@@ -1,8 +1,15 @@
[[webflux-ann-requestmapping]]
= Request Mapping
= Mapping Requests
[.small]#xref:web/webmvc/mvc-controller/ann-requestmapping.adoc[See equivalent in the Servlet stack]#
This section discusses request mapping for annotated controllers.
[[webflux-ann-requestmapping-annotation]]
== `@RequestMapping`
[.small]#xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-requestmapping-annotation[See equivalent in the Servlet stack]#
The `@RequestMapping` annotation is used to map requests to controllers methods. It has
various attributes to match by URL, HTTP method, request parameters, headers, and media
types. You can use it at the class level to express shared mappings or at the method level
@@ -500,3 +507,68 @@ Kotlin::
[[webflux-ann-httpexchange-annotation]]
== `@HttpExchange`
[.small]#xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-httpexchange-annotation[See equivalent in the Reactive stack]#
As an alternative to `@RequestMapping`, you can also handle requests with `@HttpExchange`
methods. Such methods are declared on an
xref:integration/rest-clients.adoc#rest-http-interface[HTTP Interface] and can be used as
a client via `HttpServiceProxyFactory` or implemented by a server `@Controller`.
For example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@RestController
@HttpExchange("/persons")
class PersonController {
@GetExchange("/{id}")
public Person getPerson(@PathVariable Long id) {
// ...
}
@PostExchange
@ResponseStatus(HttpStatus.CREATED)
public void add(@RequestBody Person person) {
// ...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@RestController
@HttpExchange("/persons")
class PersonController {
@GetExchange("/{id}")
fun getPerson(@PathVariable id: Long): Person {
// ...
}
@PostExchange
@ResponseStatus(HttpStatus.CREATED)
fun add(@RequestBody person: Person) {
// ...
}
}
----
======
There some differences between `@HttpExchange` and `@RequestMapping` since the
former needs to remain suitable for client and server use. For example, while
`@RequestMapping` can be declared to handle any number of paths and each path can
be a pattern, `@HttpExchange` must be declared with a single, concrete path. There are
also differences in the supported method parameters. Generally, `@HttpExchange` supports
a subset of method parameters that `@RequestMapping` does, excluding any parameters that
are server side only. For details see the list of supported method parameters for
xref:integration/rest-clients.adoc#rest-http-interface-method-parameters[HTTP interface] and for
xref:web/webflux/controller/ann-methods/arguments.adoc[@RequestMapping].
@@ -0,0 +1,111 @@
[[mvc-ann-validation]]
= Validation
[.small]#xref:web/webmvc/mvc-controller/ann-validation.adoc[See equivalent in the Servlet stack]#
Spring WebFlux has built-in xref:core/validation/validator.adoc[Validation] support for
`@RequestMapping` methods, including the option to use
xref:core/validation/beanvalidation.adoc[Java Bean Validation].
The validation support works on two levels.
First, method parameters such as
xref:web/webflux/controller/ann-methods/modelattrib-method-args.adoc[@ModelAttribute],
xref:web/webflux/controller/ann-methods/requestbody.adoc[@RequestBody], and
xref:web/webflux/controller/ann-methods/multipart-forms.adoc[@RequestPart] do perform
validation if annotated with Jakarta's `@Valid` or Spring's `@Validated` annotation, and
raise `MethodArgumentNotValidException` in case of validation errors. If you want to handle
the errors in the controller method instead, you can declare an `Errors` or `BindingResult`
method parameter immediately after the validated parameter.
Second, if https://beanvalidation.org/[Java Bean Validation] is present _AND_ other method
parameters, e.g. `@RequestHeader`, `@RequestParam`, `@PathVariable` have `@Constraint`
annotations, then method validation is applied to all method arguments, raising
`HandlerMethodValidationException` in case of validation errors. You can still declare an
`Errors` or `BindingResult` after an `@Valid` method parameter, and handle validation
errors within the controller method, as long as there are no validation errors on other
method arguments.
You can configure a `Validator` globally through the
xref:web/webflux/config.adoc#webflux-config-validation[WebMvc config], or locally
through an xref:web/webflux/controller/ann-initbinder.adoc[@InitBinder] method in an
`@Controller` or `@ControllerAdvice`. You can also use multiple validators.
NOTE: If a controller has a class level `@Validated`, then
xref:core/validation/beanvalidation.adoc#validation-beanvalidation-spring-method[method validation is applied]
through an AOP proxy. In order to take advantage of the Spring MVC built-in support for
method validation added in Spring Framework 6.1, you need to remove the class level
`@Validated` annotation from the controller.
The xref:web/webmvc/mvc-ann-rest-exceptions.adoc[Error Responses] section provides further
details on how `MethodArgumentNotValidException` and `HandlerMethodValidationException`
are handled, and also how their rendering can be customized through a `MessageSource` and
locale and language specific resource bundles.
For further custom handling of method validation errors, you can extend
`ResponseEntityExceptionHandler` or use an `@ExceptionHandler` method in a controller
or in a `@ControllerAdvice`, and handle `HandlerMethodValidationException` directly.
The exception contains a list of``ParameterValidationResult``s that group validation errors
by method parameter. You can either iterate over those, or provide a visitor with callback
methods by controller method parameter type:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
HandlerMethodValidationException ex = ... ;
ex.visitResults(new HandlerMethodValidationException.Visitor() {
@Override
public void requestHeader(RequestHeader requestHeader, ParameterValidationResult result) {
// ...
}
@Override
public void requestParam(@Nullable RequestParam requestParam, ParameterValidationResult result) {
// ...
}
@Override
public void modelAttribute(@Nullable ModelAttribute modelAttribute, ParameterErrors errors) {
// ...
@Override
public void other(ParameterValidationResult result) {
// ...
}
});
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
// HandlerMethodValidationException
val ex
ex.visitResults(object : HandlerMethodValidationException.Visitor {
override fun requestHeader(requestHeader: RequestHeader, result: ParameterValidationResult) {
// ...
}
override fun requestParam(requestParam: RequestParam?, result: ParameterValidationResult) {
// ...
}
override fun modelAttribute(modelAttribute: ModelAttribute?, errors: ParameterErrors) {
// ...
}
// ...
override fun other(result: ParameterValidationResult) {
// ...
}
})
----
======
@@ -368,26 +368,18 @@ collecting to a `MultiValueMap`.
=== Forwarded Headers
[.small]#xref:web/webmvc/filters.adoc#filters-forwarded-headers[See equivalent in the Servlet stack]#
As a request goes through proxies (such as load balancers), the host, port, and
scheme may change. That makes it a challenge, from a client perspective, to create links that point to the correct
host, port, and scheme.
include::partial$web/forwarded-headers.adoc[]
https://tools.ietf.org/html/rfc7239[RFC 7239] defines the `Forwarded` HTTP header
that proxies can use to provide information about the original request. There are other
non-standard headers, too, including `X-Forwarded-Host`, `X-Forwarded-Port`,
`X-Forwarded-Proto`, `X-Forwarded-Ssl`, and `X-Forwarded-Prefix`.
[[webflux-forwarded-headers-transformer]]
=== ForwardedHeaderTransformer
`ForwardedHeaderTransformer` is a component that modifies the host, port, and scheme of
the request, based on forwarded headers, and then removes those headers. If you declare
it as a bean with the name `forwardedHeaderTransformer`, it will be
xref:web/webflux/reactive-spring.adoc#webflux-web-handler-api-special-beans[detected] and used.
There are security considerations for forwarded headers, since an application cannot know
if the headers were added by a proxy, as intended, or by a malicious client. This is why
a proxy at the boundary of trust should be configured to remove untrusted forwarded traffic coming
from the outside. You can also configure the `ForwardedHeaderTransformer` with
`removeOnly=true`, in which case it removes but does not use the headers.
NOTE: In 5.1 `ForwardedHeaderFilter` was deprecated and superseded by
`ForwardedHeaderTransformer` so forwarded headers can be processed earlier, before the
exchange is created. If the filter is configured anyway, it is taken out of the list of
@@ -395,6 +387,17 @@ filters, and `ForwardedHeaderTransformer` is used instead.
[[webflux-forwarded-headers-security]]
=== Security Considerations
There are security considerations for forwarded headers since an application cannot know
if the headers were added by a proxy, as intended, or by a malicious client. This is why
a proxy at the boundary of trust should be configured to remove untrusted forwarded traffic coming
from the outside. You can also configure the `ForwardedHeaderTransformer` with
`removeOnly=true`, in which case it removes but does not use the headers.
[[webflux-filters]]
== Filters
[.small]#xref:web/webmvc/filters.adoc[See equivalent in the Servlet stack]#
@@ -6,6 +6,26 @@ This section describes options for client-side access to REST endpoints.
[[webmvc-restclient]]
== `RestClient`
`RestClient` is a synchronous HTTP client that exposes a modern, fluent API.
See xref:integration/rest-clients.adoc#rest-restclient[`RestClient`] for more details.
[[webmvc-webclient]]
== `WebClient`
`WebClient` is a reactive client to perform HTTP requests with a fluent API.
See xref:web/webflux-webclient.adoc[WebClient] for more details.
[[webmvc-resttemplate]]
== `RestTemplate`
@@ -13,37 +33,8 @@ This section describes options for client-side access to REST endpoints.
Spring REST client and exposes a simple, template-method API over underlying HTTP client
libraries.
NOTE: As of 5.0 the `RestTemplate` is in maintenance mode, with only requests for minor
changes and bugs to be accepted. Please, consider using the
xref:web/webflux-webclient.adoc[WebClient] which offers a more modern API and
supports sync, async, and streaming scenarios.
See xref:integration/rest-clients.adoc[REST Endpoints] for details.
[[webmvc-webclient]]
== `WebClient`
`WebClient` is a non-blocking, reactive client to perform HTTP requests. It was
introduced in 5.0 and offers a modern alternative to the `RestTemplate`, with efficient
support for both synchronous and asynchronous, as well as streaming scenarios.
In contrast to `RestTemplate`, `WebClient` supports the following:
* Non-blocking I/O.
* Reactive Streams back pressure.
* High concurrency with fewer hardware resources.
* Functional-style, fluent API that takes advantage of Java 8 lambdas.
* Synchronous and asynchronous interactions.
* Streaming up to or streaming down from a server.
See xref:web/webflux-webclient.adoc[WebClient] for more details.
[[webmvc-http-interface]]
== HTTP Interface
@@ -26,18 +26,16 @@ available through the `ServletRequest.getParameter{asterisk}()` family of method
[[filters-forwarded-headers]]
[[forwarded-headers]]
== Forwarded Headers
[.small]#xref:web/webflux/reactive-spring.adoc#webflux-forwarded-headers[See equivalent in the Reactive stack]#
As a request goes through proxies (such as load balancers) the host, port, and
scheme may change, and that makes it a challenge to create links that point to the correct
host, port, and scheme from a client perspective.
include::partial$web/forwarded-headers.adoc[]
https://tools.ietf.org/html/rfc7239[RFC 7239] defines the `Forwarded` HTTP header
that proxies can use to provide information about the original request. There are other
non-standard headers, too, including `X-Forwarded-Host`, `X-Forwarded-Port`,
`X-Forwarded-Proto`, `X-Forwarded-Ssl`, and `X-Forwarded-Prefix`.
[[filters-forwarded-headers-non-forwardedheaderfilter]]
=== ForwardedHeaderFilter
`ForwardedHeaderFilter` is a Servlet filter that modifies the request in order to
a) change the host, port, and scheme based on `Forwarded` headers, and b) to remove those
@@ -45,12 +43,22 @@ headers to eliminate further impact. The filter relies on wrapping the request,
therefore it must be ordered ahead of other filters, such as `RequestContextFilter`, that
should work with the modified and not the original request.
[[filters-forwarded-headers-security]]
=== Security Considerations
There are security considerations for forwarded headers since an application cannot know
if the headers were added by a proxy, as intended, or by a malicious client. This is why
a proxy at the boundary of trust should be configured to remove untrusted `Forwarded`
headers that come from the outside. You can also configure the `ForwardedHeaderFilter`
with `removeOnly=true`, in which case it removes but does not use the headers.
[[filters-forwarded-headers-dispatcher]]
=== Dispatcher Types
In order to support xref:web/webmvc/mvc-ann-async.adoc[asynchronous requests] and error dispatches this
filter should be mapped with `DispatcherType.ASYNC` and also `DispatcherType.ERROR`.
If using Spring Framework's `AbstractAnnotationConfigDispatcherServletInitializer`
@@ -92,7 +92,7 @@ Kotlin::
======
The return value can then be obtained by running the given task through the
xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-configuration-spring-mvc[configured] `TaskExecutor`.
xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-configuration-spring-mvc[configured] `AsyncTaskExecutor`.
@@ -128,7 +128,7 @@ Here is a very concise overview of Servlet asynchronous request processing:
* The controller returns a `Callable`.
* Spring MVC calls `request.startAsync()` and submits the `Callable` to
a `TaskExecutor` for processing in a separate thread.
an `AsyncTaskExecutor` for processing in a separate thread.
* Meanwhile, the `DispatcherServlet` and all filters exit the Servlet container thread,
but the response remains open.
* Eventually the `Callable` produces a result, and Spring MVC dispatches the request back
@@ -404,11 +404,10 @@ TIP: Spring MVC supports Reactor and RxJava through the
For streaming to the response, reactive back pressure is supported, but writes to the
response are still blocking and are run on a separate thread through the
xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-configuration-spring-mvc[configured] `TaskExecutor`, to avoid
blocking the upstream source (such as a `Flux` returned from `WebClient`).
By default, `SimpleAsyncTaskExecutor` is used for the blocking writes, but that is not
suitable under load. If you plan to stream with a reactive type, you should use the
xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-configuration-spring-mvc[MVC configuration] to configure a task executor.
xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-configuration-spring-mvc[configured]
`AsyncTaskExecutor`, to avoid blocking the upstream source such as a `Flux` returned
from `WebClient`.
@@ -494,7 +493,7 @@ In `web.xml` configuration, you can add `<async-supported>true</async-supported>
[[mvc-ann-async-configuration-spring-mvc]]
=== Spring MVC
The MVC configuration exposes the following options related to asynchronous request processing:
The MVC configuration exposes the following options for asynchronous request processing:
* Java configuration: Use the `configureAsyncSupport` callback on `WebMvcConfigurer`.
* XML namespace: Use the `<async-support>` element under `<mvc:annotation-driven>`.
@@ -504,10 +503,9 @@ You can configure the following:
* Default timeout value for async requests, which if not set, depends
on the underlying Servlet container.
* `AsyncTaskExecutor` to use for blocking writes when streaming with
xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-reactive-types[Reactive Types] and for executing `Callable` instances returned from
controller methods. We highly recommended configuring this property if you
stream with reactive types or have controller methods that return `Callable`, since
by default, it is a `SimpleAsyncTaskExecutor`.
xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-reactive-types[Reactive Types] and for
executing `Callable` instances returned from controller methods.
The one used by default is not suitable for production under load.
* `DeferredResultProcessingInterceptor` implementations and `CallableProcessingInterceptor` implementations.
Note that you can also set the default timeout value on a `DeferredResult`,
@@ -67,24 +67,25 @@ from an existing `ProblemDetail`. This could be done centrally, e.g. from an
[[mvc-ann-rest-exceptions-i18n]]
== Internationalization
== Customization and i18n
[.small]#xref:web/webflux/ann-rest-exceptions.adoc#webflux-ann-rest-exceptions-i18n[See equivalent in the Reactive stack]#
It is a common requirement to internationalize error response details, and good practice
to customize the problem details for Spring MVC exceptions. This is supported as follows:
It is a common requirement to customize and internationalize error response details.
It is also good practice to customize the problem details for Spring MVC exceptions
to avoid revealing implementation details. This section describes the support for that.
- Each `ErrorResponse` exposes a message code and arguments to resolve the "detail" field
through a xref:core/beans/context-introduction.adoc#context-functionality-messagesource[MessageSource].
The actual message code value is parameterized with placeholders, e.g.
`+"HTTP method {0} not supported"+` to be expanded from the arguments.
- Each `ErrorResponse` also exposes a message code to resolve the "title" field.
- `ResponseEntityExceptionHandler` uses the message code and arguments to resolve the
"detail" and the "title" fields.
An `ErrorResponse` exposes message codes for "type", "title", and "detail", as well as
message code arguments for the "detail" field. `ResponseEntityExceptionHandler` resolves
these through a xref:core/beans/context-introduction.adoc#context-functionality-messagesource[MessageSource]
and updates the corresponding `ProblemDetail` fields accordingly.
By default, the message code for the "detail" field is "problemDetail." + the fully
qualified exception class name. Some exceptions may expose additional message codes in
which case a suffix is added to the default message code. The table below lists message
arguments and codes for Spring MVC exceptions:
The default strategy for message codes follows the pattern:
`problemDetail.[type|title|detail].[fully qualified exception class name]`
An `ErrorResponse` may expose more than one message code, typically adding a suffix
to the default message code. The table below lists message codes, and arguments for
Spring MVC exceptions:
[[mvc-ann-rest-exceptions-codes]]
[cols="1,1,2", options="header"]
@@ -99,6 +100,11 @@ arguments and codes for Spring MVC exceptions:
| (default)
| `+{0}+` property name, `+{1}+` property value
| `HandlerMethodValidationException`
| (default)
| `+{0}+` list all validation errors.
Message codes and arguments for each error are also resolved via `MessageSource`.
| `HttpMediaTypeNotAcceptableException`
| (default)
| `+{0}+` list of supported media types
@@ -130,8 +136,7 @@ arguments and codes for Spring MVC exceptions:
| `MethodArgumentNotValidException`
| (default)
| `+{0}+` the list of global errors, `+{1}+` the list of field errors.
Message codes and arguments for each error within the `BindingResult` are also resolved
via `MessageSource`.
Message codes and arguments for each error are also resolvedvia `MessageSource`.
| `MissingRequestHeaderException`
| (default)
@@ -161,6 +166,10 @@ arguments and codes for Spring MVC exceptions:
| (default)
|
| `NoResourceFoundException`
| (default)
|
| `TypeMismatchException`
| (default)
| `+{0}+` property name, `+{1}+` property value
@@ -171,8 +180,13 @@ arguments and codes for Spring MVC exceptions:
|===
By default, the message code for the "title" field is "problemDetail.title." + the fully
qualified exception class name.
NOTE: Unlike other exceptions, the message arguments for
`MethodArgumentValidException` and `HandlerMethodValidationException` are baed on a list of
`MessageSourceResolvable` errors that can also be customized through a
xref:core/beans/context-introduction.adoc#context-functionality-messagesource[MessageSource]
resource bundle. See
xref:core/validation/beanvalidation.adoc#validation-beanvalidation-spring-method-i18n[Customizing Validation Errors]
for more details.
@@ -6,7 +6,7 @@
By default, if xref:core/validation/beanvalidation.adoc#validation-beanvalidation-overview[Bean Validation] is present
on the classpath (for example, Hibernate Validator), the `LocalValidatorFactoryBean` is
registered as a global xref:core/validation/validator.adoc[Validator] for use with `@Valid` and
`Validated` on controller method arguments.
`@Validated` on controller method arguments.
In Java configuration, you can customize the global `Validator` instance, as the
following example shows:
@@ -1,25 +1,27 @@
[[mvc-ann-initbinder]]
= `DataBinder`
= `@InitBinder`
[.small]#xref:web/webflux/controller/ann-initbinder.adoc[See equivalent in the Reactive stack]#
`@Controller` or `@ControllerAdvice` classes can have `@InitBinder` methods that
initialize instances of `WebDataBinder`, and those, in turn, can:
`@Controller` or `@ControllerAdvice` classes can have `@InitBinder` methods to
initialize `WebDataBinder` instances that in turn can:
* Bind request parameters (that is, form or query data) to a model object.
* Convert String-based request values (such as request parameters, path variables,
headers, cookies, and others) to the target type of controller method arguments.
* Format model object values as `String` values when rendering HTML forms.
* Bind request parameters to a model object.
* Convert request values from string to object property types.
* Format model object properties as strings when rendering HTML forms.
`@InitBinder` methods can register controller-specific `java.beans.PropertyEditor` or
Spring `Converter` and `Formatter` components. In addition, you can use the
xref:web/webmvc/mvc-config/conversion.adoc[MVC config] to register `Converter` and `Formatter`
types in a globally shared `FormattingConversionService`.
In an `@Controller`, `DataBinder` customizations apply locally within the controller,
or even to a specific model attribute referenced by name through the annotation.
In an `@ControllerAdvice` customizations can apply to all or a subset of controllers.
`@InitBinder` methods support many of the same arguments that `@RequestMapping` methods
do, except for `@ModelAttribute` (command object) arguments. Typically, they are declared
with a `WebDataBinder` argument (for registrations) and a `void` return value.
The following listing shows an example:
You can register `PropertyEditor`, `Converter`, and `Formatter` components in the
`DataBinder` for type conversion. Alternatively, you can use the
xref:web/webmvc/mvc-config/conversion.adoc[MVC config] to register `Converter` and
`Formatter` components in a globally shared `FormattingConversionService`.
`@InitBinder` methods can have many of the same arguments that `@RequestMapping` methods
have, with the notable exception of `@ModelAttribute`. Typically, such methods have a
`WebDataBinder` argument (for registrations) and a `void` return value, for example:
[tabs]
======
@@ -3,11 +3,8 @@
[.small]#xref:web/webflux/controller/ann-methods/modelattrib-method-args.adoc[See equivalent in the Reactive stack]#
You can use the `@ModelAttribute` annotation on a method argument to access an attribute from
the model or have it be instantiated if not present. The model attribute is also overlain with
values from HTTP Servlet request parameters whose names match to field names. This is referred
to as data binding, and it saves you from having to deal with parsing and converting individual
query parameters and form fields. The following example shows how to do so:
The `@ModelAttribute` method parameter annotation binds request parameters onto a model
object. For example:
[tabs]
======
@@ -20,7 +17,7 @@ Java::
// method logic...
}
----
<1> Bind an instance of `Pet`.
<1> Bind to an instance of `Pet`.
Kotlin::
+
@@ -31,30 +28,27 @@ fun processSubmit(@ModelAttribute pet: Pet): String { // <1>
// method logic...
}
----
<1> Bind an instance of `Pet`.
<1> Bind to an instance of `Pet`.
======
The `Pet` instance above is sourced in one of the following ways:
The `Pet` instance may be:
* Retrieved from the model where it may have been added by a
* Accessed from the model where it could have been added by a
xref:web/webmvc/mvc-controller/ann-modelattrib-methods.adoc[@ModelAttribute method].
* Retrieved from the HTTP session if the model attribute was listed in
* Accessed from the HTTP session if the model attribute was listed in
the class-level xref:web/webmvc/mvc-controller/ann-methods/sessionattributes.adoc[`@SessionAttributes`] annotation.
* Obtained through a `Converter` where the model attribute name matches the name of a
request value such as a path variable or a request parameter (see next example).
* Instantiated using its default constructor.
* Obtained through a `Converter` if the model attribute name matches the name of a
request value such as a path variable or a request parameter (example follows).
* Instantiated through a default constructor.
* Instantiated through a "`primary constructor`" with arguments that match to Servlet
request parameters. Argument names are determined through JavaBeans
`@ConstructorProperties` or through runtime-retained parameter names in the bytecode.
request parameters. Argument names are determined through runtime-retained parameter
names in the bytecode.
One alternative to using a xref:web/webmvc/mvc-controller/ann-modelattrib-methods.adoc[@ModelAttribute method] to
supply it or relying on the framework to create the model attribute, is to have a
`Converter<String, T>` to provide the instance. This is applied when the model attribute
name matches to the name of a request value such as a path variable or a request
parameter, and there is a `Converter` from `String` to the model attribute type.
In the following example, the model attribute name is `account` which matches the URI
path variable `account`, and there is a registered `Converter<String, Account>` which
could load the `Account` from a data store:
As mentioned above, a `Converter<String, T>` may be used to obtain the model object if
the model attribute name matches to the name of a request value such as a path variable or a
request parameter, _and_ there is a compatible `Converter<String, T>`. In the below example,
the model attribute name `account` matches URI path variable `account`, and there is a
registered `Converter<String, Account>` that perhaps retrieves it from a persistence store:
[tabs]
======
@@ -67,7 +61,6 @@ Java::
// ...
}
----
<1> Bind an instance of `Account` using an explicit attribute name.
Kotlin::
+
@@ -78,19 +71,101 @@ Kotlin::
// ...
}
----
<1> Bind an instance of `Account` using an explicit attribute name.
======
After the model attribute instance is obtained, data binding is applied. The
`WebDataBinder` class matches Servlet request parameter names (query parameters and form
fields) to field names on the target `Object`. Matching fields are populated after type
conversion is applied, where necessary. For more on data binding (and validation), see
xref:web/webmvc/mvc-config/validation.adoc[Validation]. For more on customizing data binding, see
xref:web/webmvc/mvc-controller/ann-initbinder.adoc[`DataBinder`].
By default, both constructor and property
xref:core/validation/beans-beans.adoc#beans-binding[data binding] are applied. However,
model object design requires careful consideration, and for security reasons it is
recommended either to use an object tailored specifically for web binding, or to apply
constructor binding only. If property binding must still be used, then _allowedFields_
patterns should be set to limit which properties can be set. For further details on this
and example configuration, see
xref:web/webmvc/mvc-controller/ann-initbinder.adoc#mvc-ann-initbinder-model-design[model design].
Data binding can result in errors. By default, a `BindException` is raised. However, to check
for such errors in the controller method, you can add a `BindingResult` argument immediately next
to the `@ModelAttribute`, as the following example shows:
When using constructor binding, you can customize request parameter names through an
`@BindParam` annotation. For example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
class Account {
private final String firstName;
public Account(@BindParam("first-name") String firstName) {
this.firstName = firstName;
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class Account(@BindParam("first-name") val firstName: String)
----
======
NOTE: The `@BindParam` may also be placed on the fields that correspond to constructor
parameters. While `@BindParam` is supported out of the box, you can also use a
different annotation by setting a `DataBinder.NameResolver` on `DataBinder`
In some cases, you may want access to a model attribute without data binding. For such
cases, you can inject the `Model` into the controller and access it directly or,
alternatively, set `@ModelAttribute(binding=false)`, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@ModelAttribute
public AccountForm setUpForm() {
return new AccountForm();
}
@ModelAttribute
public Account findAccount(@PathVariable String accountId) {
return accountRepository.findOne(accountId);
}
@PostMapping("update")
public String update(AccountForm form, BindingResult result,
@ModelAttribute(binding=false) Account account) { // <1>
// ...
}
----
<1> Setting `@ModelAttribute(binding=false)`.
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@ModelAttribute
fun setUpForm(): AccountForm {
return AccountForm()
}
@ModelAttribute
fun findAccount(@PathVariable accountId: String): Account {
return accountRepository.findOne(accountId)
}
@PostMapping("update")
fun update(form: AccountForm, result: BindingResult,
@ModelAttribute(binding = false) account: Account): String { // <1>
// ...
}
----
<1> Setting `@ModelAt\tribute(binding=false)`.
======
If data binding results in errors, by default a `MethodArgumentNotValidException` is raised,
but you can also add a `BindingResult` argument immediately next to the `@ModelAttribute`
in order to handle such errors in the controller method. For example:
[tabs]
======
@@ -123,61 +198,10 @@ Kotlin::
<1> Adding a `BindingResult` next to the `@ModelAttribute`.
======
In some cases, you may want access to a model attribute without data binding. For such
cases, you can inject the `Model` into the controller and access it directly or,
alternatively, set `@ModelAttribute(binding=false)`, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@ModelAttribute
public AccountForm setUpForm() {
return new AccountForm();
}
@ModelAttribute
public Account findAccount(@PathVariable String accountId) {
return accountRepository.findOne(accountId);
}
@PostMapping("update")
public String update(@Valid AccountForm form, BindingResult result,
@ModelAttribute(binding=false) Account account) { // <1>
// ...
}
----
<1> Setting `@ModelAttribute(binding=false)`.
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@ModelAttribute
fun setUpForm(): AccountForm {
return AccountForm()
}
@ModelAttribute
fun findAccount(@PathVariable accountId: String): Account {
return accountRepository.findOne(accountId)
}
@PostMapping("update")
fun update(@Valid form: AccountForm, result: BindingResult,
@ModelAttribute(binding = false) account: Account): String { // <1>
// ...
}
----
<1> Setting `@ModelAttribute(binding=false)`.
======
You can automatically apply validation after data binding by adding the
`jakarta.validation.Valid` annotation or Spring's `@Validated` annotation
(xref:core/validation/beanvalidation.adoc[Bean Validation] and
xref:web/webmvc/mvc-config/validation.adoc[Spring validation]). The following example shows how to do so:
`jakarta.validation.Valid` annotation or Spring's `@Validated` annotation.
See xref:core/validation/beanvalidation.adoc[Bean Validation] and
xref:web/webmvc/mvc-config/validation.adoc[Spring validation]. For example:
[tabs]
======
@@ -210,10 +234,13 @@ Kotlin::
<1> Validate the `Pet` instance.
======
Note that using `@ModelAttribute` is optional (for example, to set its attributes).
By default, any argument that is not a simple value type (as determined by
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty])
and is not resolved by any other argument resolver is treated as if it were annotated
with `@ModelAttribute`.
If there is no `BindingResult` parameter after the `@ModelAttribute`, then
`MethodArgumentNotValueException` is raised with the validation errors. However, if method
validation applies because other parameters have `@jakarta.validation.Constraint` annotations,
then `HandlerMethodValidationException` is raised instead. For more details, see the section
xref:web/webmvc/mvc-controller/ann-validation.adoc[Validation].
TIP: Using `@ModelAttribute` is optional. By default, any parameter that is not a simple
value type as determined by
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty]
_AND_ that is not resolved by any other argument resolver is treated as an `@ModelAttribute`.
@@ -188,8 +188,7 @@ Java::
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@PostMapping("/")
public String handle(@Valid @RequestPart("meta-data") MetaData metadata,
BindingResult result) {
public String handle(@Valid @RequestPart("meta-data") MetaData metadata, Errors errors) {
// ...
}
----
@@ -199,12 +198,14 @@ Kotlin::
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@PostMapping("/")
fun handle(@Valid @RequestPart("meta-data") metadata: MetaData,
result: BindingResult): String {
fun handle(@Valid @RequestPart("meta-data") metadata: MetaData, errors: Errors): String {
// ...
}
----
======
If method validation applies because other parameters have `@Constraint` annotations,
then `HandlerMethodValidationException` is raised instead. For more details, see the
section on xref:web/webmvc/mvc-controller/ann-validation.adoc[Validation].
@@ -48,7 +48,7 @@ Java::
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@PostMapping("/accounts")
public void handle(@Valid @RequestBody Account account, BindingResult result) {
public void handle(@Valid @RequestBody Account account, Errors errors) {
// ...
}
----
@@ -58,10 +58,13 @@ Kotlin::
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@PostMapping("/accounts")
fun handle(@Valid @RequestBody account: Account, result: BindingResult) {
fun handle(@Valid @RequestBody account: Account, errors: Errors) {
// ...
}
----
======
If method validation applies because other parameters have `@Constraint` annotations,
then `HandlerMethodValidationException` is raised instead. For more details, see the
section on xref:web/webmvc/mvc-controller/ann-validation.adoc[Validation].
@@ -1,8 +1,17 @@
[[mvc-ann-requestmapping]]
= Request Mapping
= Mapping Requests
[.small]#xref:web/webflux/controller/ann-requestmapping.adoc[See equivalent in the Reactive stack]#
This section discusses request mapping for annotated controllers.
[[mvc-ann-requestmapping-annotation]]
== `@RequestMapping`
[.small]#xref:web/webflux/controller/ann-requestmapping.adoc#webflux-ann-requestmapping-annotation[See equivalent in the Reactive stack]#
You can use the `@RequestMapping` annotation to map requests to controllers methods. It has
various attributes to match by URL, HTTP method, request parameters, headers, and media
types. You can use it at the class level to express shared mappings or at the method level
@@ -549,3 +558,68 @@ Kotlin::
[[mvc-ann-httpexchange-annotation]]
== `@HttpExchange`
[.small]#xref:web/webflux/controller/ann-requestmapping.adoc#webflux-ann-httpexchange-annotation[See equivalent in the Reactive stack]#
As an alternative to `@RequestMapping`, you can also handle requests with `@HttpExchange`
methods. Such methods are declared on an
xref:integration/rest-clients.adoc#rest-http-interface[HTTP Interface] and can be used as
a client via `HttpServiceProxyFactory` or implemented by a server `@Controller`.
For example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@RestController
@HttpExchange("/persons")
class PersonController {
@GetExchange("/{id}")
public Person getPerson(@PathVariable Long id) {
// ...
}
@PostExchange
@ResponseStatus(HttpStatus.CREATED)
public void add(@RequestBody Person person) {
// ...
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@RestController
@HttpExchange("/persons")
class PersonController {
@GetExchange("/{id}")
fun getPerson(@PathVariable id: Long): Person {
// ...
}
@PostExchange
@ResponseStatus(HttpStatus.CREATED)
fun add(@RequestBody person: Person) {
// ...
}
}
----
======
There some differences between `@HttpExchange` and `@RequestMapping` since the
former needs to remain suitable for client and server use. For example, while
`@RequestMapping` can be declared to handle any number of paths and each path can
be a pattern, `@HttpExchange` must be declared with a single, concrete path. There are
also differences in the supported method parameters. Generally, `@HttpExchange` supports
a subset of method parameters that `@RequestMapping` does, excluding any parameters that
are server side only. For details see the list of supported method parameters for
xref:integration/rest-clients.adoc#rest-http-interface-method-parameters[HTTP interface] and for
xref:web/webmvc/mvc-controller/ann-methods/arguments.adoc[@RequestMapping].
@@ -0,0 +1,112 @@
[[mvc-ann-validation]]
= Validation
[.small]#xref:web/webflux/controller/ann-validation.adoc[See equivalent in the Reactive stack]#
Spring MVC has built-in xref:core/validation/validator.adoc[Validation] support for
`@RequestMapping` methods, including the option to use
xref:core/validation/beanvalidation.adoc[Java Bean Validation].
The validation support works on two levels.
First, method parameters such as
xref:web/webmvc/mvc-controller/ann-methods/modelattrib-method-args.adoc[@ModelAttribute],
xref:web/webmvc/mvc-controller/ann-methods/requestbody.adoc[@RequestBody], and
xref:web/webmvc/mvc-controller/ann-methods/multipart-forms.adoc[@RequestPart] do perform
validation if annotated with Jakarta's `@Valid` or Spring's `@Validated` annotation, and
raise `MethodArgumentNotValidException` in case of validation errors. If you want to handle
the errors in the controller method instead, you can declare an `Errors` or `BindingResult`
method parameter immediately after the validated parameter.
Second, if https://beanvalidation.org/[Java Bean Validation] is present _AND_ other method
parameters, e.g. `@RequestHeader`, `@RequestParam`, `@PathVariable` have `@Constraint`
annotations, then method validation is applied to all method arguments, raising
`HandlerMethodValidationException` in case of validation errors. You can still declare an
`Errors` or `BindingResult` after an `@Valid` method parameter, and handle validation
errors within the controller method, as long as there are no validation errors on other
method arguments. Method validation is also applied to the return value if the method
is annotated with `@Valid` or has other `@Constraint` annotations.
You can configure a `Validator` globally through the
xref:web/webmvc/mvc-config/validation.adoc[WebMvc config], or locally through an
xref:web/webmvc/mvc-controller/ann-initbinder.adoc[@InitBinder] method in an
`@Controller` or `@ControllerAdvice`. You can also use multiple validators.
NOTE: If a controller has a class level `@Validated`, then
xref:core/validation/beanvalidation.adoc#validation-beanvalidation-spring-method[method validation is applied]
through an AOP proxy. In order to take advantage of the Spring MVC built-in support for
method validation added in Spring Framework 6.1, you need to remove the class level
`@Validated` annotation from the controller.
The xref:web/webmvc/mvc-ann-rest-exceptions.adoc[Error Responses] section provides further
details on how `MethodArgumentNotValidException` and `HandlerMethodValidationException`
are handled, and also how their rendering can be customized through a `MessageSource` and
locale and language specific resource bundles.
For further custom handling of method validation errors, you can extend
`ResponseEntityExceptionHandler` or use an `@ExceptionHandler` method in a controller
or in a `@ControllerAdvice`, and handle `HandlerMethodValidationException` directly.
The exception contains a list of``ParameterValidationResult``s that group validation errors
by method parameter. You can either iterate over those, or provide a visitor with callback
methods by controller method parameter type:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
HandlerMethodValidationException ex = ... ;
ex.visitResults(new HandlerMethodValidationException.Visitor() {
@Override
public void requestHeader(RequestHeader requestHeader, ParameterValidationResult result) {
// ...
}
@Override
public void requestParam(@Nullable RequestParam requestParam, ParameterValidationResult result) {
// ...
}
@Override
public void modelAttribute(@Nullable ModelAttribute modelAttribute, ParameterErrors errors) {
// ...
@Override
public void other(ParameterValidationResult result) {
// ...
}
});
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
// HandlerMethodValidationException
val ex
ex.visitResults(object : HandlerMethodValidationException.Visitor {
override fun requestHeader(requestHeader: RequestHeader, result: ParameterValidationResult) {
// ...
}
override fun requestParam(requestParam: RequestParam?, result: ParameterValidationResult) {
// ...
}
override fun modelAttribute(modelAttribute: ModelAttribute?, errors: ParameterErrors) {
// ...
}
// ...
override fun other(result: ParameterValidationResult) {
// ...
}
})
----
======
@@ -62,8 +62,7 @@ initialization parameters (`init-param` elements) to the Servlet declaration in
The exception can then be caught with a `HandlerExceptionResolver` (for example, by using an
`@ExceptionHandler` controller method) and handled as any others.
By default, this is set to `false`, in which case the `DispatcherServlet` sets the
response status to 404 (NOT_FOUND) without raising an exception.
As of 6.1, this property is set to `true` and deprecated.
Note that, if xref:web/webmvc/mvc-config/default-servlet-handler.adoc[default servlet handling] is
also configured, unresolved requests are always forwarded to the default servlet
@@ -280,9 +280,7 @@ The following example shows the XML configuration equivalent of the preceding ex
NOTE: For client-side WebSocket configuration, you should use `WebSocketContainerFactoryBean`
(XML) or `ContainerProvider.getWebSocketContainer()` (Java configuration).
For Jetty, you need to supply a pre-configured Jetty `WebSocketServerFactory` and plug
that into Spring's `DefaultHandshakeHandler` through your WebSocket Java config.
The following example shows how to do so:
For Jetty, you need to supply a `Consumer` callback to configure the WebSocket server. For example:
[source,java,indent=0,subs="verbatim,quotes"]
----
@@ -292,62 +290,20 @@ The following example shows how to do so:
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
JettyRequestUpgradeStrategy upgradeStrategy = new JettyRequestUpgradeStrategy();
upgradeStrategy.addWebSocketConfigurer(configurable -> {
policy.setInputBufferSize(8192);
policy.setIdleTimeout(600000);
});
registry.addHandler(echoWebSocketHandler(),
"/echo").setHandshakeHandler(handshakeHandler());
}
@Bean
public DefaultHandshakeHandler handshakeHandler() {
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
policy.setInputBufferSize(8192);
policy.setIdleTimeout(600000);
return new DefaultHandshakeHandler(
new JettyRequestUpgradeStrategy(new WebSocketServerFactory(policy)));
"/echo").setHandshakeHandler(new DefaultHandshakeHandler(upgradeStrategy));
}
}
----
The following example shows the XML configuration equivalent of the preceding example:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket
https://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:handlers>
<websocket:mapping path="/echo" handler="echoHandler"/>
<websocket:handshake-handler ref="handshakeHandler"/>
</websocket:handlers>
<bean id="handshakeHandler" class="org.springframework...DefaultHandshakeHandler">
<constructor-arg ref="upgradeStrategy"/>
</bean>
<bean id="upgradeStrategy" class="org.springframework...JettyRequestUpgradeStrategy">
<constructor-arg ref="serverFactory"/>
</bean>
<bean id="serverFactory" class="org.eclipse.jetty...WebSocketServerFactory">
<constructor-arg>
<bean class="org.eclipse.jetty...WebSocketPolicy">
<constructor-arg value="SERVER"/>
<property name="inputBufferSize" value="8092"/>
<property name="idleTimeout" value="600000"/>
</bean>
</constructor-arg>
</bean>
</beans>
----
@@ -6,7 +6,7 @@ written to WebSocket sessions. As the channel is backed by a `ThreadPoolExecutor
are processed in different threads, and the resulting sequence received by the client may
not match the exact order of publication.
If this is an issue, enable the `setPreservePublishOrder` flag, as the following example shows:
To enable ordered publishing, set the `setPreservePublishOrder` flag as follows:
[source,java,indent=0,subs="verbatim,quotes"]
----
@@ -47,5 +47,22 @@ When the flag is set, messages within the same client session are published to t
`clientOutboundChannel` one at a time, so that the order of publication is guaranteed.
Note that this incurs a small performance overhead, so you should enable it only if it is required.
The same also applies to messages from the client, which are sent to the `clientInboundChannel`,
from where they are handled according to their destination prefix. As the channel is backed by
a `ThreadPoolExecutor`, messages are processed in different threads, and the resulting sequence
of handling may not match the exact order in which they were received.
To enable ordered publishing, set the `setPreserveReceiveOrder` flag as follows:
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@EnableWebSocketMessageBroker
public class MyConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.setPreserveReceiveOrder(true);
}
}
----
@@ -0,0 +1,122 @@
As a request goes through proxies such as load balancers the host, port, and
scheme may change, and that makes it a challenge to create links that point to the correct
host, port, and scheme from a client perspective.
https://tools.ietf.org/html/rfc7239[RFC 7239] defines the `Forwarded` HTTP header
that proxies can use to provide information about the original request.
[[forwarded-headers-non-standard]]
=== Non-standard Headers
There are other non-standard headers, too, including `X-Forwarded-Host`, `X-Forwarded-Port`,
`X-Forwarded-Proto`, `X-Forwarded-Ssl`, and `X-Forwarded-Prefix`.
[[x-forwarded-host]]
==== X-Forwarded-Host
While not standard, https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host[`X-Forwarded-Host: <host>`]
is a de-facto standard header that is used to communicate the original host to a
downstream server. For example, if a request of `https://example.com/resource` is sent to
a proxy which forwards the request to `http://localhost:8080/resource`, then a header of
`X-Forwarded-Host: example.com` can be sent to inform the server that the original host was `example.com`.
[[x-forwarded-port]]
==== X-Forwarded-Port
While not standard, `X-Forwarded-Port: <port>` is a de-facto standard header that is used to
communicate the original port to a downstream server. For example, if a request of
`https://example.com/resource` is sent to a proxy which forwards the request to
`http://localhost:8080/resource`, then a header of `X-Forwarded-Port: 443` can be sent
to inform the server that the original port was `443`.
[[x-forwarded-proto]]
==== X-Forwarded-Proto
While not standard, https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto[`X-Forwarded-Proto: (https|http)`]
is a de-facto standard header that is used to communicate the original protocol (e.g. https / https)
to a downstream server. For example, if a request of `https://example.com/resource` is sent to
a proxy which forwards the request to `http://localhost:8080/resource`, then a header of
`X-Forwarded-Proto: https` can be sent to inform the server that the original protocol was `https`.
[[x-forwarded-ssl]]
==== X-Forwarded-Ssl
While not standard, `X-Forwarded-Ssl: (on|off)` is a de-facto standard header that is used to communicate the
original protocol (e.g. https / https) to a downstream server. For example, if a request of
`https://example.com/resource` is sent to a proxy which forwards the request to
`http://localhost:8080/resource`, then a header of `X-Forwarded-Ssl: on` to inform the server that the
original protocol was `https`.
[[x-forwarded-prefix]]
==== X-Forwarded-Prefix
While not standard, https://microsoft.github.io/reverse-proxy/articles/transforms.html#defaults[`X-Forwarded-Prefix: <prefix>`]
is a de-facto standard header that is used to communicate the original URL path prefix to a
downstream server.
Use of `X-Forwarded-Prefix` can vary by deployment scenario, and needs to be flexible to
allow replacing, removing, or prepending the path prefix of the target server.
_Scenario 1: Override path prefix_
[subs="-attributes"]
----
https://example.com/api/{path} -> http://localhost:8080/app1/{path}
----
The prefix is the start of the path before the capture group `+{path}+`. For the proxy,
the prefix is `/api` while for the server the prefix is `/app1`. In this case, the proxy
can send `X-Forwarded-Prefix: /api` to have the original prefix `/api` override the
server prefix `/app1`.
_Scenario 2: Remove path prefix_
At times, an application may want to have the prefix removed. For example, consider the
following proxy to server mapping:
[subs="-attributes"]
----
https://app1.example.com/{path} -> http://localhost:8080/app1/{path}
https://app2.example.com/{path} -> http://localhost:8080/app2/{path}
----
The proxy has no prefix, while applications `app1` and `app2` have path prefixes
`/app1` and `/app2` respectively. The proxy can send ``X-Forwarded-Prefix: `` to
have the empty prefix override server prefixes `/app1` and `/app2`.
[NOTE]
====
A common case for this deployment scenario is where licenses are paid per
production application server, and it is preferable to deploy multiple applications per
server to reduce fees. Another reason is to run more applications on the same server in
order to share the resources required by the server to run.
In these scenarios, applications need a non-empty context root because there are multiple
applications on the same server. However, this should not be visible in URL paths of
the public API where applications may use different subdomains that provides benefits
such as:
* Added security, e.g. same origin policy
* Independent scaling of applications (different domain points to different IP address)
====
_Scenario 3: Insert path prefix_
In other cases, it may be necessary to prepend a prefix. For example, consider the
following proxy to server mapping:
[subs="-attributes"]
----
https://example.com/api/app1/{path} -> http://localhost:8080/app1/{path}
----
In this case, the proxy has a prefix of `/api/app1` and the server has a prefix of
`/app1`. The proxy can send `X-Forwarded-Prefix: /api/app1` to have the original prefix
`/api/app1` override the server prefix `/app1`.
@@ -1,29 +1,16 @@
In the context of web applications, _data binding_ involves the binding of HTTP request
parameters (that is, form data or query parameters) to properties in a model object and
its nested objects.
xref:core/validation/beans-beans.adoc#beans-binding[Data binding] for web requests involves
binding request parameters to a model object. By default, request parameters can be bound
to any public property of the model object, which means malicious clients can provide
extra values for properties that exist in the model object graph, but are not expected to
be set. This is why model object design requires careful consideration.
Only `public` properties following the
https://www.oracle.com/java/technologies/javase/javabeans-spec.html[JavaBeans naming conventions]
are exposed for data binding — for example, `public String getFirstName()` and
`public void setFirstName(String)` methods for a `firstName` property.
TIP: The model object, and its nested object graph, is also sometimes referred to as a
TIP: The model object, and its nested object graph is also sometimes referred to as a
_command object_, _form-backing object_, or _POJO_ (Plain Old Java Object).
By default, Spring permits binding to all public properties in the model object graph.
This means you need to carefully consider what public properties the model has, since a
client could target any public property path, even some that are not expected to be
targeted for a given use case.
For example, given an HTTP form data endpoint, a malicious client could supply values for
properties that exist in the model object graph but are not part of the HTML form
presented in the browser. This could lead to data being set on the model object and any
of its nested objects, that is not expected to be updated.
The recommended approach is to use a _dedicated model object_ that exposes only
properties that are relevant for the form submission. For example, on a form for changing
a user's email address, the model object should declare a minimum set of properties such
as in the following `ChangeEmailForm`.
A good practice is to use a _dedicated model object_ rather than exposing your domain
model such as JPA or Hibernate entities for web data binding. For example, on a form to
change an email address, create a `ChangeEmailForm` model object that declares only
the properties required for the input:
[source,java,indent=0,subs="verbatim,quotes"]
----
@@ -51,13 +38,16 @@ as in the following `ChangeEmailForm`.
}
----
If you cannot or do not want to use a _dedicated model object_ for each data
binding use case, you **must** limit the properties that are allowed for data binding.
Ideally, you can achieve this by registering _allowed field patterns_ via the
`setAllowedFields()` method on `WebDataBinder`.
Another good practice is to apply
xref:core/validation/beans-beans.adoc#beans-constructor-binding[constructor binding],
which uses only the request parameters it needs for constructor arguments, and any other
input is ignored. This is in contrast to property binding which by default binds every
request parameter for which there is a matching property.
For example, to register allowed field patterns in your application, you can implement an
`@InitBinder` method in a `@Controller` or `@ControllerAdvice` component as shown below:
If neither a dedicated model object nor constructor binding is sufficient, and you must
use property binding, we strongy recommend registering `allowedFields` patterns (case
sensitive) on `WebDataBinder` in order to prevent unexpected properties from being set.
For example:
[source,java,indent=0,subs="verbatim,quotes"]
----
@@ -74,22 +64,28 @@ For example, to register allowed field patterns in your application, you can imp
}
----
In addition to registering allowed patterns, it is also possible to register _disallowed
field patterns_ via the `setDisallowedFields()` method in `DataBinder` and its subclasses.
Please note, however, that an "allow list" is safer than a "deny list". Consequently,
`setAllowedFields()` should be favored over `setDisallowedFields()`.
You can also register `disallowedFields` patterns (case insensitive). However,
"allowed" configuration is preferred over "disallowed" as it is more explicit and less
prone to mistakes.
Note that matching against allowed field patterns is case-sensitive; whereas, matching
against disallowed field patterns is case-insensitive. In addition, a field matching a
disallowed pattern will not be accepted even if it also happens to match a pattern in the
allowed list.
By default, constructor and property binding are both used. If you want to use
constructor binding only, you can set the `declarativeBinding` flag on `WebDataBinder`
through an `@InitBinder` method either locally within a controller or globally through an
`@ControllerAdvice`. Turning this flag on ensures that only constructor binding is used
and that property binding is not used unless `allowedFields` patterns are configured.
For example:
[WARNING]
====
It is extremely important to properly configure allowed and disallowed field patterns
when exposing your domain model directly for data binding purposes. Otherwise, it is a
big security risk.
[source,java,indent=0,subs="verbatim,quotes"]
----
@Controller
public class MyController {
Furthermore, it is strongly recommended that you do **not** use types from your domain
model such as JPA or Hibernate entities as the model object in data binding scenarios.
====
@InitBinder
void initBinder(WebDataBinder binder) {
binder.setDeclarativeBinding(true);
}
// @RequestMapping methods, etc.
}
----
@@ -0,0 +1,2 @@
# All Modules
_See also the <a href="../javadoc-api/" target="_blank">Java API documentation (Javadoc)</a>._
+4 -1
View File
@@ -1,7 +1,10 @@
<html>
<body>
<p>
This is the public API documentation for the <a href="https://github.com/spring-projects/spring-framework" target="_top">Spring Framework</a>.
This is the public Java API documentation (Javadoc) for the <a href="https://github.com/spring-projects/spring-framework" target="_top">Spring Framework</a>.
</p>
<p><em>
See also the <a href="../kdoc-api/" target="_blank">Kotlin API documentation (KDoc)</a>.
</em></p>
</body>
</html>

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