Compare commits

...

583 Commits

Author SHA1 Message Date
Brian Clozel 77140da643 Release v6.1.19 2025-04-17 08:41:38 +02:00
Stéphane Nicoll d879112885 Upgrade to github-changelog-generator 0.0.12
Closes gh-34756
2025-04-15 10:06:17 +02:00
Juergen Hoeller 0a71df7aee Polishing 2025-04-10 18:55:34 +02:00
Juergen Hoeller 82b7fcb2cc Try loadClass on LinkageError in case of ClassLoader mismatch
See gh-34677

(cherry picked from commit 7f2c1f447f)
2025-04-10 18:49:31 +02:00
Juergen Hoeller 6717fca4ec Explicitly use original ClassLoader in case of package visibility
Closes gh-34684

(cherry picked from commit 6bb964e2d0)
2025-04-02 23:50:39 +02:00
Juergen Hoeller 86ea7003f7 Upgrade to Groovy 4.0.26, Jetty 12.0.18, Apache HttpClient 5.4.3, Checkstyle 10.22 2025-04-01 23:42:56 +02:00
Juergen Hoeller 0a157faec1 Polishing (backported from 6.2.x) 2025-04-01 22:36:40 +02:00
Juergen Hoeller 2548d44f3b Include cause in MethodInvocationException message
Closes gh-34691

(cherry picked from commit 203ca30a64)
2025-04-01 22:28:39 +02:00
Juergen Hoeller 6cc6ea1b2b Make jar caching configurable through setUseCaches
Closes gh-34694
2025-03-31 17:24:33 +02:00
Juergen Hoeller b73ca60811 Only attempt load for CGLIB classes in AOT mode
Closes gh-34677

(cherry picked from commit 743f32675d)
2025-03-31 17:23:46 +02:00
Sam Brannen d689629036 Support abstract @⁠Configuration classes without @⁠Bean methods again
Historically, @⁠Configuration classes that did not declare @⁠Bean
methods were allowed to be abstract. However, the changes made in
76a6b9ea79 introduced a regression that prevents such classes from
being abstract, resulting in a BeanInstantiationException. This change
in behavior is caused by the fact that such a @⁠Configuration class is
no longer replaced by a concrete subclass created dynamically by CGLIB.

This commit restores support for abstract @⁠Configuration classes
without @⁠Bean methods by modifying the "no enhancement required" check
in ConfigurationClassParser.

See gh-34486
Closes gh-34663

(cherry picked from commit 044258f085)
2025-03-31 14:33:02 +02:00
rstoyanchev 077721bdb4 Remove outdated notes on forwarded headers.
Closes gh-34625
2025-03-31 11:38:51 +01:00
Stéphane Nicoll b7654dd984 Make sure the generated values are available from a static context
This commit updates the tests of property values code generated to
invoke the generated code from a `static` context. This ensures that
the test fails if that's not the case.

This commit also updated LinkedHashMap handling that did suffer from
that problem.

Closes gh-34661
2025-03-27 12:09:29 +01:00
Juergen Hoeller 4645ce60c8 Polishing 2025-03-25 19:27:37 +01:00
Juergen Hoeller 564d3f6f5e Enable qualifier annotation tests including backported precedence tests
See gh-34644
2025-03-25 00:24:23 +01:00
Juergen Hoeller 7a1dfe79a0 Polishing (aligned with 6.2.x) 2025-03-21 16:08:02 +01:00
Juergen Hoeller 19257f4fdb Add javadoc notes on potential exception suppression in getBeansOfType
Closes gh-34629

(cherry picked from commit dc41ff569e)
2025-03-21 16:02:01 +01:00
Juergen Hoeller f06167ea01 Polishing 2025-03-21 11:06:10 +01:00
rstoyanchev 618e003b91 Fix dated Javadoc in MvcUriComponentsBuilder
related to forwarded headers

Closes gh-34615
2025-03-19 12:37:12 +00:00
Juergen Hoeller 8c494e5165 Defer triggerAfterCompletion invocation in doRollbackOnCommitException
Closes gh-34595

(cherry picked from commit cc986cd2e8)
2025-03-19 11:04:51 +01:00
Juergen Hoeller 62d7396769 Suggest compilation with -parameters in case of ambiguity
Closes gh-34609

(cherry picked from commit 86b2617c7f)
2025-03-19 11:04:39 +01:00
Brian Clozel 252058a65a Next development version (v6.1.19-SNAPSHOT) 2025-03-13 09:00:08 +01:00
Juergen Hoeller 9ea049ad6f Upgrade to Reactor 2023.0.16
Includes Netty 4.1.119 and Jetty 12.0.17

Closes gh-34579
2025-03-12 13:28:03 +01:00
Juergen Hoeller 1e31cd685e Avoid getTargetConnection call on transaction-aware Connection close
Closes gh-34484

(cherry picked from commit c64dae3623)
2025-02-28 14:21:55 +01:00
Juergen Hoeller 0d60f266ad Defensively call isShutdown method for executor description
Closes gh-34514

(cherry picked from commit 559ea6c480)
2025-02-28 14:21:41 +01:00
Juergen Hoeller a018ae6e02 Lenient fallback when cached WeakReference returns null
Closes gh-34423
2025-02-26 10:25:07 +01:00
Juergen Hoeller ea419d2dcd Avoid unnecessary CGLIB processing on configuration classes
Closes gh-34486

(cherry picked from commit aff9ac72ec)
2025-02-25 18:42:18 +01:00
Brian Clozel c02d07fdef Fix multiple Content-Language values in MockHttpServletResponse
Prior to this commit, `MockHttpServletResponse` would only support
adding a `Content-Language` once. Adding multiple header values would
always replace the content-language property in the response and the
entire header value.

This commit ensures that this behavior is supported.

Fixes gh-34491
2025-02-25 17:57:27 +01:00
Juergen Hoeller 7460be617b Consistent default ClassLoader fallback in hint classes
Closes gh-34470
2025-02-23 15:23:51 +01:00
Brian Clozel ccf4b028d2 Fix null value support in ContentCachingResponseWrapper
Prior to this commit, calling `setHeader` on the response wrapper would
have a separate code path for the "Content-Length" header. This did not
support calls with `null` values and would result in an exception.

This commit ensures that the cached content length value is reset in
this case and that the call is forwarded properly to the superclass.

Fixes gh-34465
2025-02-21 14:36:09 +01:00
Brian Clozel b5c89c91a9 Handle null values in MockHttpServletResponse#setHeader
Prior to this commit, `MockHttpServletResponse#setHeader` would not
remove the header entry when given a `null` value, as documented in the
Servlet API.
This commit ensures that this behavior is enforced.

Fixes gh-34466
2025-02-21 14:35:37 +01:00
Sébastien Deleuze 01ae0a7c26 Fix broken antora task
See https://github.com/spring-io/antora-extensions/pull/43

Closes gh-34455
2025-02-19 16:45:08 +01:00
Juergen Hoeller b48d72cbd0 Apply fallback in case of initial SmartClassLoader mismatch as well
See gh-34423

(cherry picked from commit 6786e1c3e5)
2025-02-18 20:53:21 +01:00
Juergen Hoeller 48628194dc Apply fallback in case of any exception coming out of createClass
Closes gh-34423

(cherry picked from commit 93134fd4d1)
2025-02-18 15:41:38 +01:00
Juergen Hoeller 3cf1fbf222 Mark XML-configured executor/scheduler as infrastructure bean
Closes gh-34015

(cherry picked from commit d0ceefedc6)
2025-02-18 15:41:17 +01:00
Stéphane Nicoll ecd943c7ec Next development version (v6.1.18-SNAPSHOT) 2025-02-13 13:23:32 +01:00
Juergen Hoeller 9d6d67188a Upgrade to Jetty 12.0.16, Netty 4.1.118, XStream 1.4.21, AssertJ 3.27.3, Checkstyle 10.21.2 2025-02-11 22:47:24 +01:00
Juergen Hoeller 24fd0940bd Align with SmartClassLoader handling for AOP proxy classes
Closes gh-34274

(cherry picked from commit f53da04717)
2025-02-11 22:19:43 +01:00
Sam Brannen 5b928f47a8 Finish incomplete sentences
(cherry picked from commit 9d3374b28d)
2025-02-11 12:32:27 +01:00
Stéphane Nicoll 5e52baee86 Upgrade to Reactor 2023.0.15
Closes gh-34406
2025-02-11 11:44:35 +01:00
Stéphane Nicoll c10596a1fd Upgrade to RSocket 1.1.5
Closes gh-34405
2025-02-11 11:43:04 +01:00
Sam Brannen a68b7289f0 Improve warning for unexpected use of value attribute as @⁠Component name
Prior to this commit, if a String 'value' attribute of an annotation
was annotated with @⁠AliasFor and explicitly configured to alias an
attribute other than @⁠Component.value, the value was still used as the
@⁠Component name, but the warning message that was logged stated that
the 'value' attribute should be annotated with
@⁠AliasFor(annotation=Component.class). However, it is not possible to
annotate an annotation attribute twice with @⁠AliasFor.

To address that, this commit revises the logic in
AnnotationBeanNameGenerator so that it issues a log message similar to
the following in such scenarios.

WARN o.s.c.a.AnnotationBeanNameGenerator - Although the 'value'
attribute in @⁠example.MyStereotype declares @⁠AliasFor for an
attribute other than @⁠Component's 'value' attribute, the value is
still used as the @⁠Component name based on convention. As of Spring
Framework 7.0, such a 'value' attribute will no longer be used as the
@⁠Component name.

See gh-34346
Closes gh-34317

(cherry picked from commit 17a94fb110)
2025-02-10 13:32:28 +01:00
Sam Brannen a5b9e667e3 Polishing
(cherry picked from commit 2fcae65853)
2025-02-10 13:32:20 +01:00
Branden Clark 78fe55f4d1 Check hasNext on sessionIds in UserDestinationResult
Closes gh-34333

Signed-off-by: Branden Clark <brandenrayclark@gmail.com>
2025-02-10 11:22:28 +00:00
Brian Clozel 65913c3655 Fix "Nth day of week" Quartz-style cron expressions
Prior to this commit, `CronExpression` would support Quartz-style
expressions with "Nth occurence of a  dayOfWeek" semantics by using the
`TemporalAdjusters.dayOfWeekInMonth` JDK support. This method will
return the Nth occurence starting with the month of the given temporal,
but in some cases will overflow to the next or previous month.
This behavior is not expected for our cron expression support.

This commit ensures that when an overflow happens (meaning, the
resulting date is not in the same month as the input temporal), we
should instead have another attempt at finding a valid month for this
expression.

Fixes gh-34377
2025-02-06 18:34:24 +01:00
Sam Brannen b7a996a64b Clarify component scanning of abstract classes with @⁠Lookup methods
Due to changes in gh-19118, classes that contain @⁠Lookup methods are
no longer required to be concrete classes for use with component
scanning; however, the reference documentation still states that such
classes must not be abstract.

This commit therefore removes the outdated reference documentation and
updates the corresponding Javadoc.

See gh-19118
Closes gh-34367

(cherry picked from commit 819a7c86c1)
2025-02-05 13:44:28 +01:00
Stéphane Nicoll 5b1a7c7f21 Handle arbitrary JoinPoint argument index
Closes gh-34369
2025-02-05 11:55:11 +01:00
Brian Clozel ebd80bdd6c Delete failing Freemarker test
This test was already ignored as of Java 21 because of a Java behavior
change, and now it started failing as of 17.0.14.
This commit removes the test entirely.
2025-02-04 10:03:50 +01:00
Juergen Hoeller a4fc68b8e8 Explicitly set custom ClassLoader on CGLIB Enhancer
Closes gh-34274

(cherry picked from commit 1b18928bf0)
2025-02-03 15:37:04 +01:00
Sam Brannen c333946b0b Restore property binding support for a Map that implements Iterable
The changes in commit c20a2e4763 introduced a regression with regard to
binding to a Map property when the Map also happens to implement
Iterable.

Although that is perhaps not a very common scenario, this commit
reorders the if-blocks in AbstractNestablePropertyAccessor's
getPropertyValue(PropertyTokenHolder) method so that a Map is
considered before an Iterable, thereby allowing an Iterable-Map to be
accessed as a Map.

See gh-907
Closes gh-34332

(cherry picked from commit b9e43d05bd)
2025-01-29 17:46:19 +01:00
rstoyanchev b0a8a3ec5f Enhance DisconnectedClientHelper exception type checks
We now look for the target exception types in cause chain as well,
but return false if we encounter a RestClient or WebClient
exception in the chain.

Closes gh-34264
2025-01-21 12:25:45 +00:00
rstoyanchev bb5be2119c Restore exception phrase in DisconnectedClientHelper
Effectively revert 203fa7, and add implementation comment and tests.

See gh-34264
2025-01-21 12:25:35 +00:00
Brian Clozel cf662368a5 Fix Wrong parentId tracking in JFR application startup
This commit fixes the tracking of the main event parentId for the Java
Flight Recorder implementation variant.

Fixes gh-34254
2025-01-13 20:22:07 +01:00
rstoyanchev e1b06ccfaa Improve logging in ReactiveTypeHandler
See gh-34188
2025-01-06 12:33:38 +00:00
rstoyanchev 9eefdb8041 Synchronize in WebAsyncManager onError/onTimeout
On connection loss, in a race between application thread and onError
callback trying to set the DeferredResult and dispatch, the onError
callback must not exit until dispatch completes. Currently, it may do
so because the DeferredResult has checks to bypasses locking or even
trying to dispatch if result is already set.

Closes gh-34192
2025-01-06 12:33:17 +00:00
rstoyanchev c50cb10964 Minor refactoring in WebAsyncManager
There is no need to set the DeferredResult from WebAsyncManager in an
onError notification because it is already done from the Lifecycle
interceptor in DeferredResult.

See gh-34192
2025-01-06 12:33:02 +00:00
rstoyanchev 245341231f Polishing in WebAsyncManager
See gh-34192
2025-01-06 12:32:40 +00:00
Sébastien Deleuze 875cc828cf Upgrade to Java 17.0.13 2024-12-30 12:14:52 +01:00
Stéphane Nicoll 898d3ec86a Backport tests for exact match resolution
See gh-34124
2024-12-23 12:15:44 +01:00
Tran Ngoc Nhan 8ccaabe778 Fix broken links in the web reference documentation
Backport of gh-34115.

Closes gh-34139
2024-12-23 11:22:17 +01:00
Sam Brannen 9c934b5019 Support varargs-only MethodHandle as SpEL function
Prior to this commit, if a MethodHandle was registered as a custom
function in the Spring Expression Language (SpEL) for a static method
that accepted only a variable argument list (for example,
`static String func(String... args)`), attempting to invoke the
registered function within a SpEL expression resulted in a
ClassCastException because the varargs array was unnecessarily wrapped
in an Object[].

This commit modifies the logic in FunctionReference's internal
executeFunctionViaMethodHandle() method to address that.

Closes gh-34109
2024-12-18 15:34:27 +01:00
Brian Clozel 4b45338ae6 Improve PathMatcher/PatternParser XML configuration
Prior to this commit, the MVC namespace for the XML Spring configuration
model would use the `PathMatcher` bean instance when provided like this:

```
<bean id="pathMatcher" class="org.springframework.util.AntPathMatcher"/>
<mvc:annotation-driven>
  <mvc:path-matching path-matcher="pathMatcher"/>
</mvc:annotation-driven>
<mvc:resources mapping="/resources/**" location="classpath:/static/"/>
```

With this configuration, the handler mapping for annotated controller
would use the given `AntPathMatcher` instance but the handler mapping
for resources would still use the default, which is `PathPatternParser`
since 6.0.

This commit ensures that when a custom `path-matcher` is defined, it's
consistently used for all MVC handler mappings as an alias to the
well-known bean name. This allows to use `AntPathMatcher` consistently
while working on a migration path to `PathPatternParser`

This commit also adds a new XML attribute to the path matching
configuration that makes it possible to use a custom `PathPatternParser`
instance:

```
<bean id="patternParser" class="org.springframework.web.util.pattern.PathPatternParser"/>
<mvc:annotation-driven>
  <mvc:path-matching pattern-parser="patternParser"/>
</mvc:annotation-driven>
```

Closes gh-34102
See gh-34064
2024-12-17 10:30:18 +01:00
Juergen Hoeller 95003e3512 Avoid logger serialization behind shared EntityManager proxy
See gh-34084
2024-12-12 19:52:21 +01:00
Stéphane Nicoll 68368621f3 Prevent execution of Antora jobs on forks
Closes gh-34083
2024-12-12 17:39:59 +01:00
Brian Clozel 890a8f4311 Next development version (v6.1.17-SNAPSHOT) 2024-12-12 10:04:11 +01:00
Juergen Hoeller 0976d1a252 Upgrade to RxJava 3.1.10 and Checkstyle 10.20.2 2024-12-11 17:49:18 +01:00
Juergen Hoeller 2c0ce790d8 Avoid deprecated ListenableFuture name for internal class 2024-12-11 17:47:11 +01:00
Juergen Hoeller d512aafc36 Avoid javadoc references to deprecated types/methods
(cherry picked from commit 68997d8416)
2024-12-11 17:47:03 +01:00
Sam Brannen faa000f330 Log alias removal in DefaultListableBeanFactory
Prior to this commit, information was logged when a bean definition
overrode an existing bean definition, but nothing was logged when the
registration of a bean definition resulted in the removal of an alias.

With this commit, an INFO message is now logged whenever an alias is
removed in DefaultListableBeanFactory.

Closes gh-34070

(cherry picked from commit 41d9f21ab9)
2024-12-11 15:05:42 +01:00
Juergen Hoeller daf1b3d7a7 Remove unnecessary downcast to DefaultListableBeanFactory
See gh-33920
See gh-25952
2024-12-10 22:33:01 +01:00
Juergen Hoeller a48897a241 Log provider setup failure at info level without stacktrace
Closes gh-33979

(cherry picked from commit 3e3ca74020)
2024-12-10 22:28:38 +01:00
Stéphane Nicoll 7ffa12f90f Upgrade to Reactor 2023.0.13
Closes gh-34049
2024-12-10 14:09:57 +01:00
Stéphane Nicoll 0e74ffa144 Start building against Reactor 2023.0.13 snapshots
See gh-34049
2024-12-08 10:47:15 +01:00
Juergen Hoeller 357195289d Unit test for match against unresolvable wildcard
See gh-33982
2024-12-05 17:53:30 +01:00
Sébastien Deleuze 4fbca99f20 Remove unnecessary HandshakeHandlerRuntimeHints
Those hints are not needed anymore as of Spring Framework 6.1.
Backport of gh-34032.

Closes gh-34033
2024-12-05 15:46:31 +01:00
Juergen Hoeller c48ca5151f Upgrade to Gradle 8.11.1 2024-12-04 17:36:11 +01:00
Juergen Hoeller aaf2e8fbe6 Polishing
(cherry picked from commit edf7f3cd43)
2024-12-04 17:35:50 +01:00
Juergen Hoeller 3635ff0c17 Consistent fallback to NoUpgradeStrategyWebSocketService
Closes gh-33970

(cherry picked from commit 58c64cba2c)
2024-12-04 16:55:51 +01:00
Simon Baslé f20e76e227 Upgrade to Undertow 2.3.18.Final
Closes gh-33976
2024-11-27 14:31:46 +01:00
Simon Baslé dd32f95192 Dispatch in UndertowHttpHandlerAdapter
This ensures that the reactive handling of the request is dispatched
from the Undertow IO thread, marking the exchange as async rather than
ending it once the Undertow `handleRequest` method returns.

See gh-33885
Closes gh-33969
2024-11-26 16:58:21 +01:00
Tran Ngoc Nhan 75a920bc9f Fix a typo in the filters documentation
Backport of gh-33959
Closes gh-33971
2024-11-26 16:17:18 +01:00
Sam Brannen 92874adae9 Polish SpEL documentation
(cherry picked from commit 7196f3f554)
2024-11-18 11:43:14 +01:00
Sam Brannen 55167b7f50 Fix SpEL examples in reference guide
Closes gh-33907

(cherry picked from commit a12d40e10b)
2024-11-18 11:43:05 +01:00
Sam Brannen 3129afba19 Upgrade to Gradle 8.11
Closes gh-33895

(cherry picked from commit bb32df0a06)
2024-11-15 16:08:05 +01:00
Sam Brannen 1366d2926b Upgrade to antora-ui-spring version 0.4.18
Closes gh-33892

(cherry picked from commit fe8573c0ab)
2024-11-15 14:34:00 +01:00
Brian Clozel 5145cf476f Next development version (v6.1.16-SNAPSHOT) 2024-11-14 15:28:50 +01:00
Juergen Hoeller 6cb41dc5e3 Upgrade to Netty 4.1.115 2024-11-14 12:51:03 +01:00
Sam Brannen 1e95332f62 Fix link to "Resources" section in reference guide
Closes gh-33882
2024-11-14 10:15:34 +01:00
Juergen Hoeller fec6ba4dfe Polishing 2024-11-13 22:26:06 +01:00
Sam Brannen bfde33a514 Document options for Date/Time parsing & formatting issues with JDK 20+
This commit updates Javadoc and the reference guide to document options
for handling date/time parsing and formatting issues on JDK 20 and higher.

A new "Date and Time Formatting with JDK 20 and higher" page has also been
introduced in the wiki.

https://github.com/spring-projects/spring-framework/wiki/Date-and-Time-Formatting-with-JDK-20-and-higher

Closes gh-33151
2024-11-13 16:39:40 +01:00
Juergen Hoeller 14b9865de7 Remove ineffective JettyByteBufferIterator from WebSocket adapter
In JettyWebSocketHandlerAdapter, JettyByteBufferIterator does not actually add extra behavior (in contrast to JettyClientHttpConnector).
2024-11-13 15:10:32 +01:00
Juergen Hoeller 62eb21f938 Add note on declaring autowired fields as ObjectProvider
Closes gh-33834
2024-11-13 15:09:58 +01:00
Juergen Hoeller 01c85b1afb Add explicit note on blocking in case of concurrency limit
Closes gh-33873
2024-11-13 15:09:02 +01:00
Juergen Hoeller df376d9343 Upgrade to Micrometer 1.12.12 and Reactor 2023.0.12
Includes Netty 4.1.114, Jetty 12.0.15, Jetty Reactive HttpClient 4.0.8, RxJava 3.1.9, RSocket 1.1.4, Groovy 4.0.24, JRuby 9.4.9, Checkstyle 10.20.1

Closes gh-33877
Closes gh-33879
2024-11-13 15:08:40 +01:00
Sam Brannen 4d792d0e45 Remove mentions of Joda-Time support
Since Joda-Time support was removed in Spring Framework 6.0, this commit
removes obsolete mentions of Joda-Time in the reference guide and Javadoc.

See gh-27426
Closes gh-33881
2024-11-13 14:16:14 +01:00
Sam Brannen 0a5bd89129 Align JettyByteBufferIterator implementations
Both are now static nested classes.
2024-11-13 12:31:27 +01:00
Tran Ngoc Nhan 53b9a2cb78 Fix formatting issue in validation section of reference guide
Closes gh-33871
2024-11-12 20:49:56 +01:00
rstoyanchev e78179b96e Decode static resource path with UriUtils
Closes gh-33859
2024-11-12 10:16:05 +00:00
Brian Clozel 49a63e2c37 Add tests for gh-33867
Closes gh-33867
2024-11-12 10:02:48 +01:00
ZLATAN628 5666e363d1 Fix wrong uri tag for client observation convention
Prior to this commit, a client sending a request to
"https://example.org" would record the wrong URI tag as
"/https://example.org".

This commit ensures that the scheme+host part is matched correctly in
the default client observation conventions.

See gh-33867
2024-11-12 10:02:39 +01:00
Stéphane Nicoll f06853a339 Merge pull request #33865 from ngocnhan-tran1996
* pr/33865:
  Fix typo in reference documentation

Closes gh-33865
2024-11-10 14:45:49 +09:00
Tran Ngoc Nhan 8afd01ba2c Fix typo in reference documentation
See gh-33865
2024-11-10 14:45:19 +09:00
Sam Brannen 9724f9b9c8 Introduce tests for SpEL PropertyAccessor ordering
Closes gh-33861
2024-11-08 16:19:12 +01:00
Sam Brannen 0d9033592b Document that circular dependencies should be avoided in AOT mode
Closes gh-33786
2024-11-07 12:23:39 +01:00
Sam Brannen fc7b8ae966 Fix anchor name, consistently use title case, and polish wording
(cherry picked from commit 2e6c8daec6)
2024-11-07 12:22:25 +01:00
Sam Brannen c457131f1c Fix heading level for "Programmatic bean registration" in AOT chapter
(cherry picked from commit 9f0dbc4051)
2024-11-07 12:22:02 +01:00
Sam Brannen 39cfe136da Polishing 2024-11-07 11:49:22 +01:00
Sam Brannen 05a880e3b5 Fix XML bean reference example in reference manual
Closes gh-33855
2024-11-07 10:44:01 +01:00
Simon Baslé c93af1f76d Polishing: copyright header year
See gh-33823
2024-11-07 10:04:53 +01:00
Stéphane Nicoll 541866fd70 Merge pull request #33850 from wilkinsona
* pr/33850:
  Polish "Prefer modified resources over the originals in TestCompiler"
  Prefer modified resources over the originals in TestCompiler

Closes gh-33850
2024-11-06 23:11:58 +09:00
Stéphane Nicoll 0219ee656f Polish "Prefer modified resources over the originals in TestCompiler"
See gh-33850
2024-11-06 23:03:11 +09:00
Andy Wilkinson f6e1a5de09 Prefer modified resources over the originals in TestCompiler
Previously, when the test compiler had been seeded with a resource
file, any modifications to this resource performed during
compilation would be lost as this original content would always
be returned.

This commit updates the DynamicJavaFileManager to always store
the dynamic resource in the dynamicResourceFiles map, irrespective
of whether it's being created afresh or from some existing resource
content. This ensures that any modifications made to the resource
can be retrieved later on.

Similarly, DynamicClassLoader has been updated to prefer dynamic
resource files over any original resource files. This ensures that
the resource that it finds reflects any modifications that have
been made to it.

See gh-33850
2024-11-06 23:00:08 +09:00
Simon Baslé 9b3cb15389 Introduce HttpHeaders#headerSet to guarantee case-insensitive iteration
The `HttpHeaders#headerSet` method is intended as a drop-in replacement
for `entrySet` that guarantees a single casing for all header names
reported during the iteration, as the cost of some overhead but with
support for iterator removal and entry value-setting.

The `formatHeaders` static method is also altered to do a similar
deduplication of casing variants, but now additionally mentions
"with native header names [native name set]" if the native name set
contains casing variants.

Closes gh-33823
2024-11-06 11:11:39 +01:00
Hosam Aly 4ef2b429e0 Fix a typo in beanvalidation.adoc
ContraintViolation => ConstraintViolation

Closes gh-33846
2024-11-06 10:09:05 +01:00
Johnny Lim 0beb56a58c Fix indentation to use tabs in Kotlin source files
Closes gh-33840
2024-11-05 10:24:02 +01:00
Sam Brannen 6bd4687706 Update copyright headers
See gh-33839
2024-11-03 16:14:41 +01:00
Tran Ngoc Nhan 07b12666b4 Fix typos in Javadoc and variable names
Closes gh-33839
2024-11-03 16:13:50 +01:00
Stéphane Nicoll 438d6de3c1 Merge pull request #33768 from kunaljani1100
* pr/33768:
  Polish "Add test coverage for DomUtils"
  Add test coverage for DomUtils

Closes gh-33768
2024-11-03 18:16:17 +09:00
Stéphane Nicoll d43126705f Polish "Add test coverage for DomUtils"
See gh-33768
2024-11-03 18:15:34 +09:00
kunaljani1100 57bbf0ca0f Add test coverage for DomUtils
See gh-33768
2024-11-03 13:44:07 +09:00
Sam Brannen 27912b1ed1 Prevent accidental printing to System.err in the codebase
This also revises the Checkstyle rule so that invocations such as
System.out.printf() are also forbidden.
2024-11-01 10:42:31 +01:00
Brian Clozel 8ffbafd384 Prevent accidental Sysouts in the codebase 2024-10-30 10:36:30 +01:00
Juergen Hoeller 022fdcd67e Provide removeCache method on Caffeine/ConcurrentMapCacheManager
Closes gh-33813
2024-10-29 23:02:48 +01:00
Juergen Hoeller 11ebceee38 Call get/setRequestConfig for HttpClient 5.4 compatibility
Includes upgrade to HttpClient 5.4.1 while retaining a HttpClient 5.1 baseline.

Closes gh-33806
2024-10-29 23:01:57 +01:00
Juergen Hoeller fa21dffcf8 Restore traditional AspectJ behavior through "spring.aop.ajc.ignore=true"
Closes gh-33704
2024-10-29 23:01:16 +01:00
Juergen Hoeller 323de1208a Document limited support for lifecycle management
Closes gh-33780
2024-10-28 22:08:41 +01:00
Juergen Hoeller 94d46eba3c Exclusively mention CompletableFuture instead of ListenableFuture
Closes gh-33805
2024-10-28 22:05:10 +01:00
Sam Brannen e340e45f5a Rename aopAvailable constants in TransactionSynchronizationUtils
Closes gh-33796
2024-10-25 14:41:41 +02:00
Brian Clozel a06bbccf9e HttpHeaders.writeableHttpHeaders should unwrap many times
Prior to this commit, the `HttpHeaders.writeableHttpHeaders` would only
consider headers read-only instances that were wrapped once by
`HttpHeaders.readOnlyHttpHeaders`. This does not work when other
`HttpHeaders` wrappers are involved in the chain.

This commit ensures that `writeableHttpHeaders` unwraps all headers
instances down to the actual multivalue map and create a new headers
instance out of it.

Fixes gh-33789
2024-10-25 10:22:12 +02:00
rstoyanchev bbe362c0e6 Allow null from RestClient exchange methods
Closes gh-33779
2024-10-23 19:08:54 +01:00
Brian Clozel 4a81f2c904 Remove HTTP parts workaround for Resin
A workaround was added for the Resin Servlet container in gh-13937.
This avoids attempting to delete parts that are not named, because the
`part.delete()` call would fail for non-file entries. This can be
problematic for files that are unnamed as they might not be removed by
the Framework.

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

Fixes gh-33511
2024-10-23 09:24:30 +02:00
Sam Brannen fb0a108254 Improve Javadoc for core SpEL APIs 2024-10-22 13:04:29 +02:00
Sam Brannen c98f314665 Throw ParseException for unsupported character in SpEL expression
Prior to this commit, the SpEL Tokenizer threw an IllegalStateException
when an unsupported character was detected in a SpEL expression;
however, the Javadoc for ExpressionParser.parseExpression() states that
it throws a ParseException if an exception occurred during parsing.

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

Closes gh-33767
2024-10-22 13:03:08 +02:00
Sehwan Lim d22924c728 Fix incorrect regex rendering in MVC controller documentation
This commit fixes the issue where the regex pattern in the reference documentation
was not rendering correctly for the `/projects/{project:[a-z]+}/versions` mapping.

Closes gh-33766
2024-10-21 18:32:44 +02:00
Juergen Hoeller e235e661d8 Polishing 2024-10-21 18:13:42 +02:00
Juergen Hoeller 09fe0adb40 Load-time weaving support for WildFly 24+
Closes gh-33728
2024-10-21 18:13:34 +02:00
Brian Clozel 84e762b470 Fix double accounting of JMS process observations
Prior to this commit, the instrumentation of the processing of JMS
messages would happen a different levels of the hierarchy, accounting
for alli known implementations, `SimpleMessageListenerContainer` and
`DefaultMessageListenerContainer` as well as various use cases and
`MessageListener` variants.

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

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

Fixes gh-33758
2024-10-21 16:09:58 +02:00
Juergen Hoeller e90a2da05d Clarify defensive impact of allowEagerInit flag for type matching
Closes gh-33740
2024-10-21 15:38:25 +02:00
Sam Brannen d48f388c6a Polish Javadoc for @⁠DateTimeFormat 2024-10-21 12:19:35 +02:00
Sam Brannen bbbb7c396e Update Date/Time formatting tests for pre/post JDK 20
This commit updates our Date/Time formatting/printing tests to
demonstrate that the use of fallback patterns can help mitigate
locale-based parsing/formatting issues beginning with JDK 20.

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

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

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

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

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

Closes gh-33733
2024-10-19 14:54:29 +02:00
Brian Clozel 67d78eb61c Avoid Servlet observations failures for invalid HTTP status
Prior to this commit, the `DefaultServerRequestObservationConvention`
for Servlet failed when the HTTP response status was invalid (for
example, set to "0").

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

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

For now, Undertow 2.3.17.Final is still used.

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

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

This commit ensures that buffers are released on cancel signals.

Fixes gh-33731
2024-10-18 10:51:38 +02:00
Stéphane Nicoll a55701588e Next development version (v6.1.15-SNAPSHOT) 2024-10-17 10:28:22 +02:00
Juergen Hoeller fde7116ae4 Consistently skip processing of plain Java annotations
Closes gh-33580
2024-10-16 17:17:22 +02:00
Brian Clozel 0a645916cd Add checkstyle rule for toLowerCase/toUpperCase
This commit adds a checkstyle rule that prevents the re-introduction of
such calls.

See gh-33708
2024-10-16 16:25:03 +02:00
Habin Song 5302e7aa25 Update fallback.adoc
Fix a typo.

Closes gh-33721
2024-10-16 14:20:56 +02:00
github-actions[bot] cad02c1743 Update Antora Spring UI to v0.4.17 2024-10-16 14:15:55 +02:00
Juergen Hoeller c765d03a59 Use Locale.ROOT consistently for toLower/toUpperCase
Closes gh-33708
2024-10-16 13:44:59 +02:00
Juergen Hoeller 11d4272ff4 Use Locale.ROOT consistently for toLower/toUpperCase
Closes gh-33708
2024-10-16 13:36:23 +02:00
rstoyanchev 23656aebc6 Use Locale.ROOT consistently for toLower/toUpperCase
See gh-33708
2024-10-16 12:05:54 +01:00
Juergen Hoeller feb6a5f52d Polishing 2024-10-16 11:35:23 +02:00
Stéphane Nicoll a228eb8bd6 Upgrade to Reactor 2023.0.11
Closes gh-33637
2024-10-15 14:56:57 +02:00
Stéphane Nicoll c015814140 Upgrade to Micrometer 1.12.11
Closes gh-33647
2024-10-15 09:06:27 +02:00
rstoyanchev fb7890d739 Update processPath for double encoding
See gh-33689
2024-10-14 18:13:55 +01:00
Habin Song 7c2c4d7c9a Update scheduling.adoc
Change 'OutOfMemoryErrors' to 'OutOfMemoryError'.

Closes gh-33703
2024-10-14 19:01:33 +02:00
rstoyanchev 3bfbe30a78 Normalize static resource path early
Rather than leaving it to the Resource implementation, and
potentially normalizing twice, we apply it once as part of the
initial processPath checks.

Closes gh-33689
2024-10-14 15:52:15 +01:00
Brian Clozel 32962894a0 Add runtime hints for JMS connection factories proxies
Prior to this commit, the JMS connection factories would proxy various
interfaces. This typically requires runtime hints for GraalVM native
applications and spring-jms is missing those.

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

Fixes gh-33590
2024-10-14 14:54:24 +02:00
Hosam Aly 97bce6d361 Fix link in testing/support-jdbc.adoc
Fix the link to "Testing Data Access Logic with an Embedded Database".

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

Closes gh-33688
2024-10-14 11:50:19 +02:00
Stéphane Nicoll f991c19b30 Merge pull request #33617 from asibross
* pr/33617:
  Polish "Adapt Javadoc note about log level of BeanPostProcessorChecker"
  Adapt Javadoc note about log level of BeanPostProcessorChecker

Closes gh-33617
2024-10-09 14:44:32 +02:00
Stéphane Nicoll 3c80d4c978 Polish "Adapt Javadoc note about log level of BeanPostProcessorChecker"
See gh-33617
2024-10-09 14:42:36 +02:00
Asi Bross 6da32b4631 Adapt Javadoc note about log level of BeanPostProcessorChecker
See gh-33617
2024-10-09 14:40:49 +02:00
Stéphane Nicoll 91cadf7f24 Start building against Reactor 2023.0.11 snapshots
See gh-33637
2024-10-09 14:16:14 +02:00
Stéphane Nicoll 90637b6344 Start building against Micrometer 1.12.11 snapshots
See gh-33647
2024-10-09 14:15:22 +02:00
Juergen Hoeller 2622db1dbe Consistent references to annotation-based autowiring 2024-10-08 11:26:42 +02:00
Juergen Hoeller 3dac274d20 Avoid synchronization for delegate initialization
Closes gh-33656
2024-10-07 10:19:16 +02:00
Stéphane Nicoll 6b975592bf Harmonize GitHub Actions structure
See https://github.com/spring-projects/spring-boot/issues/42512
2024-10-07 07:57:16 +02:00
Sam Brannen c44e43d791 Upgrade to JUnit 5.10.5 2024-10-04 15:33:25 +02:00
Stéphane Nicoll c41f8ea3c8 Merge pull request #33634 from junhyeongkim2
* pr/33634:
  Use HttpMethod.GET for better readability

Closes gh-33634
2024-10-04 10:20:20 +02:00
jun a668580f77 Use HttpMethod.GET for better readability
See gh-33634
2024-10-04 10:10:58 +02:00
Simon Baslé b54420f8aa Include argument name in MethodArgumentTypeMismatchException message
Closes gh-33573
2024-10-03 16:32:29 +02:00
Sam Brannen 0b3b1391c1 Avoid usage of deprecated AssertJ feature 2024-09-30 12:41:35 +02:00
Johnny Lim 64daba34de Upgrade to Awaitility 4.2.2
See gh-33143
Closes gh-33604
2024-09-30 12:36:54 +02:00
Juergen Hoeller 87157d3200 Polishing 2024-09-30 11:13:50 +02:00
Juergen Hoeller 95f181352f Defensively check MethodParameter.getMethod() in KotlinDelegate
Closes gh-33609
2024-09-30 11:13:26 +02:00
Simon Baslé e32a2f339d Propagate method error in some cases of reactive findInCaches errors
In a Cacheable reactive method, if an exception is propagated from
both the method and the caching infrastructure, an NPE could previously
surface due to the `CacheAspectSupport` attempting to perform an
`onErrorResume` with a `null`. This change ensures that in such a case
the user-level exception from the method is propagated instead.

Closes gh-33492
2024-09-30 10:18:59 +02:00
Juergen Hoeller 9f4968ed05 Polishing 2024-09-27 19:16:12 +02:00
Juergen Hoeller b6cfa2db0b Refine warn log message with advisor and ROLE_INFRASTRUCTURE hints
Closes gh-33184
2024-09-27 19:16:05 +02:00
Juergen Hoeller 26054d1ab0 Fix TargetSource setup for valid proxy interface specification
See gh-31304
2024-09-26 15:26:31 +02:00
Juergen Hoeller f2b522211f Upgrade to Groovy 4.0.23 2024-09-25 14:23:23 +02:00
Juergen Hoeller 49da92b6a3 Avoid http URL String (making checkstyleNohttp happy)
See gh-33561
2024-09-25 13:53:34 +02:00
Juergen Hoeller daa109e2ec Preserve URLStreamHandler in toRelativeURL and convertClassLoaderURL
Closes gh-33561
See gh-33199
2024-09-25 12:45:34 +02:00
Juergen Hoeller ca0448260f Convert DateTimeException to expected IllegalArgumentException
Closes gh-33545
2024-09-25 12:45:20 +02:00
Sébastien Deleuze 2ab0101b8a Add coroutine context tests for WebClientExtensions
Closes gh-33548
2024-09-25 12:14:50 +02:00
Illia Sorokoumov 478aa250a0 Preserve coroutine context in WebClientExtensions
See gh-33548
2024-09-25 11:46:30 +02:00
Sam Brannen 5cc4d0a2ca Do not invoke AotTestExecutionListener for @⁠DisabledInAotMode tests
Closes gh-33589
2024-09-24 16:47:48 +02:00
Sam Brannen 602ac903ff Upgrade to JUnit 5.10.4 2024-09-24 15:39:53 +02:00
Sam Brannen af3a26ab06 Clean up warnings in Gradle build 2024-09-24 12:33:35 +02:00
Sam Brannen 1cecf52883 Upgrade to Apache HttpCore Reactive 5.3
Closes gh-33588
2024-09-24 12:21:50 +02:00
Sam Brannen 88905ea20d Upgrade to Apache HttpClient 5.4
This commit also updates the external Javadoc link to avoid the following
warning in the build.

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

Closes gh-33587
2024-09-24 12:20:44 +02:00
Simon Baslé 7df9db3bb7 Polishing test
Assert that BlockHound doesn't trigger, rather than assertions on a
condition that makes the test flakky because concurrency is involved.
2024-09-24 11:01:37 +02:00
Sam Brannen bd9c05a909 Upgrade to Gradle 8.10.2
Closes gh-33584
2024-09-24 10:46:58 +02:00
Andrey Popov 94c04821ff Use correct method to check encoded resource path
Closes: gh-33568
2024-09-20 09:32:24 +01:00
Brian Clozel 776811bdb8 Defer ExchangeFilterFunction execution in WebClient
Prior to this commit, the `DefaultWebClient` would execute the configured
`ExchangeFilterFunction` as the reactive pipeline is assembled during
subscription. This means that if imperative code is executed in a filter
function, it won't be aware of the current observation through the local
scope.

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

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

Fixes gh-33559
2024-09-18 11:18:17 +02:00
Simon Baslé de4ff4b44b Polishing tests
This commit adds more test coverage of SpringCoreBlockHoundIntegration.

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

Closes gh-33450
2024-09-17 16:40:40 +02:00
Antoine Rey daea92397f Reference the spring-framework-petclinic repository
Closes gh-33539
2024-09-16 16:58:34 +02:00
Brian Clozel 5efb385e64 Read Expires cookie attribute in HttpComponents connector
Prior to this commit, the HttpComponents implementation for the
`WebClient` would only consider the max-age attribute of response
cookies when parsing the response. This is not aligned with other client
implementations that consider the max-age attribute first, and then the
expires if the former was not present. The expires date is then
translated into a max-age duration. This behavior is done naturally by
several implementations.

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

Fixes gh-33157
2024-09-13 15:49:06 +02:00
Sam Brannen b388ff60dd Fix parameterized test display names and polishing 2024-09-13 15:26:56 +02:00
Brian Clozel 412f5f677b Fix NPEs in MimeMessageHelper when adding files without names
Prior to this commit, `MimeMessageHelper` would accept `Resource`
instances as inline attachments in multipart MIME messages. If the
provided `Resource` implementation returns `null` for `getFileName()`,
the `addInLine` method would fail with a `NullPointerException` as
Jakarta activation fails to detect the content type for a null filename.

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

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

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

Fixes gh-33422
2024-09-13 09:28:45 +02:00
Stéphane Nicoll 2ae62dec8c Next development version (v6.1.14-SNAPSHOT) 2024-09-12 14:11:01 +02:00
rstoyanchev d86bf8b205 Align RouterFunctions resource handling
Closes: gh-33434
2024-09-12 08:33:37 +01:00
Sam Brannen c77de8a6fb Downgrade to Tomcat 10.1.28
Tomcat 10.1.29 was causing failures in spring-webflux when running a
full build.
2024-09-11 18:08:01 +02:00
Juergen Hoeller 4e49f67ec5 Upgrade to SLF4J 2.0.16, Tomcat 10.1.29, Jetty 12.0.13, Netty 4.1.113, Undertow 2.3.17, AssertJ 3.26.3, Checkstyle 10.18.1 2024-09-11 17:16:14 +02:00
Juergen Hoeller 54dbb9f52a Upgrade to Objenesis 3.4
Closes gh-33526
2024-09-11 17:15:37 +02:00
Stéphane Nicoll 34f649c3f5 Upgrade to Reactor 2023.0.10
Closes gh-33519
2024-09-10 15:05:08 +02:00
Stéphane Nicoll 5b01f31387 Upgrade to Micrometer 1.12.10
Closes gh-33518
2024-09-10 15:04:42 +02:00
Sébastien Deleuze 9150c81d92 Document fixed rate scheduling with CRaC
Closes gh-33490
2024-09-09 18:43:55 +02:00
Sam Brannen 4e1756d738 Polishing 2024-09-09 15:34:00 +02:00
rstoyanchev 5c1ab7ecd5 Polishing contribution
Closes gh-33498
2024-09-09 11:55:15 +01:00
yfoelsin 7655329463 Set status code on DefaultRenderingBuilder for RedirectView
See gh-33498
2024-09-09 11:54:50 +01:00
rstoyanchev 3d1bf28445 Refine how async request state lock is obtained
Rather than waiting indefinitely, keep checking if the state
changed from ASYNC (e.g. to ERROR).

Closes gh-33421
2024-09-09 11:54:38 +01:00
Johnny Lim b7c7823315 Add @⁠since tag for CodeWarnings.detectDeprecation(ResolvableType)
See gh-32850
Closes gh-33493
2024-09-05 17:45:52 +02:00
Sam Brannen caaa86d6cf Make AspectJ pointcut in test more robust
The previous pointcut attempted to match against a local lambda type;
however, that pointcut was unreliable and failed sporadically.

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

Closes gh-33465
2024-09-04 16:12:44 +02:00
Sébastien Deleuze 83be0f2dac Improve documentation on reading form data
`@RequestParam` should be favored over `@RequestBody`
which can't always be used reliably due to how the Servlet
API behaves.

Closes gh-33409
2024-09-03 20:22:00 +02:00
Sébastien Deleuze 3c2831030b Upgrade to Kotlin 1.9.25
Closes gh-33471
2024-09-03 15:34:53 +02:00
Juergen Hoeller 1f6ab1a0c9 Polishing 2024-08-31 12:00:41 +02:00
Juergen Hoeller ce5869eeb0 Consistent test execution with Locale.UK 2024-08-31 12:00:34 +02:00
Juergen Hoeller 1db9faf248 Avoid shutdown timeout in case of exception on stop
Closes gh-33442
2024-08-31 12:00:26 +02:00
Juergen Hoeller 5d80d75051 Follow symlinks during root path traversal
Closes gh-33424
2024-08-31 12:00:14 +02:00
Brian Clozel debba6545b Listen to multiple async operations in ServerHttpObservationFilter
Prior to this commit, the `ServerHttpObservationFilter` was fixed to
re-enable instrumentation for async dispatches. This fix involves using
an AsyncListener to be notified of exchange completion.

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

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

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

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

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

Closes gh-33456
2024-08-30 19:06:35 +02:00
Sam Brannen dca55236c4 Stop documenting use of -debug compiler flag in reference manual
Closes gh-33453
2024-08-30 11:24:39 +02:00
Sam Brannen 61b5b1edd8 Fix example for @⁠ImportResource in the reference manual
Prior to this commit, the main() method attempted to retrieve a
TransferService bean from the context, but no such bean had been
configured in the context.

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

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

Closes gh-33447
2024-08-29 15:39:10 +02:00
Sam Brannen 29fdcf56eb Polishing 2024-08-29 15:15:26 +02:00
rstoyanchev 186deb777f Update deprecation notices on rawStatusCode
Mark for removal where not marked, and set to 7.0
consistently as the target for removal.

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

See gh-33440
2024-08-28 18:12:26 +03:00
Sébastien Deleuze 871539ab28 Fix a typo in the CDS documentation
Closes gh-33437
2024-08-27 15:38:56 -07:00
alfredo-toledano aca5db817d Fix link to core container introduction in ref docs
Closes gh-33417
2024-08-22 09:30:47 +02:00
Sam Brannen b2c1f978a4 Stop logging result in WebAsyncManager
Closes gh-33406
2024-08-19 13:53:06 +02:00
Brian Clozel 50be08480d Open observation scope in RestClient
Prior to this commit, the `RestClient` instrumentation would create and
close observations for HTTP requests, but would not open an observation
scope for the lifetime of the exchange.
This means that custom `ClientHttpRequestInterceptor` and
`ResponseErrorHandler` would not get access to the current observation
scope in case of tracing, possibly leading to missing trace ids in logs.

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

Fixes gh-33397
2024-08-19 11:48:26 +02:00
Sébastien Deleuze 0101945708 Prevent a leak in WebTestClient
This commit applies the same kind of processing for
Void.class element type in the ParameterizedTypeReference
variant of WebTestClient.ResponseSpec#returnResult than
in the Class variant.

Closes gh-33389
2024-08-19 10:46:47 +02:00
Sébastien Deleuze d41ca095ab Add native support for Kotlin default values in controllers
Closes gh-33384
2024-08-19 09:46:53 +02:00
Sam Brannen 143736e59b Enforce order of Javadoc tags for records
Closes gh-33403
2024-08-18 13:01:43 +02:00
Sébastien Deleuze e0cb7aa0a0 Build documentation branches only for 6.1 and later
To avoid a duplication error caused by a conflict between the
6.0.x branch and the v6.0.23 tag.

Closes gh-33398
2024-08-16 17:04:55 +02:00
Sébastien Deleuze 46c29b9175 Support Boolean property in BindingReflectionHintsRegistrar
Closes gh-33380
2024-08-16 14:37:12 +02:00
Stéphane Nicoll 1634e63506 Next development version (v6.1.13-SNAPSHOT) 2024-08-14 13:27:42 +02:00
rstoyanchev bb17ad8314 Efficient ETag parsing 2024-08-14 07:19:59 +03:00
Juergen Hoeller 63486bf19c Upgrade to Tomcat 10.1.28, Jetty 12.0.12, Netty 4.1.112, Undertow 2.3.15 2024-08-13 18:52:15 +02:00
Juergen Hoeller d0bff584d7 Polishing 2024-08-13 18:51:02 +02:00
Juergen Hoeller 8be5010f5d LocaleEditor supports BCP 47 language tags as well
Closes gh-33348
2024-08-13 18:50:30 +02:00
Stéphane Nicoll 86761cd233 Upgrade to Reactor 2023.0.9
Closes gh-33326
2024-08-13 17:27:02 +02:00
Stéphane Nicoll 07cdef410e Upgrade to Micrometer 1.12.9
Closes gh-33325
2024-08-13 17:26:38 +02:00
Sam Brannen e74406afd0 Introduce withAssignmentDisabled() option for SimpleEvaluationContext
To support additional use cases, this commit introduces a
withAssignmentDisabled() method in the Builder for
SimpleEvaluationContext.

Closes gh-33319
2024-08-13 17:26:34 +03:00
rstoyanchev fe4fd00429 Polishing contribution
Closes gh-33374
2024-08-13 16:59:13 +03:00
Riley Park 1703b71563 Fix incorrect weak ETag assertion
See gh-33374
2024-08-13 16:31:14 +03:00
Sébastien Deleuze 1911ca728d Support invoking bridged suspending functions in AopUtils
Closes gh-33045
2024-08-12 17:27:41 +02:00
Simon Baslé f4a73b79b8 Avoid CacheAspectSupport#findInCaches fall through to reactive handler
Prior to this commit if the return type is a CompletableFuture but a
cache get returns null, the execution falls through to the
reactiveCachingHandler.

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

Closes gh-33371
2024-08-12 14:54:15 +02:00
Stéphane Nicoll 289c35c829 Merge pull request #33368 from tafjwr
* pr/33368:
  Polish "Fix predicate setup in test"
  Fix predicate setup in test

Closes gh-33368
2024-08-12 11:02:02 +02:00
Stéphane Nicoll 749145be2a Polish "Fix predicate setup in test"
See gh-33368
2024-08-12 10:29:34 +02:00
tafjwr 28eece3da1 Fix predicate setup in test
See gh-33368
2024-08-12 10:29:23 +02:00
Stéphane Nicoll 2b8225f11c Polish "Sync GHA setup" 2024-08-09 15:52:27 +02:00
Stéphane Nicoll 1e6767ac03 Sync GHA setup 2024-08-09 15:37:43 +02:00
Stéphane Nicoll 7a250aa8ea Polish
See gh-33354
2024-08-09 09:52:06 +02:00
Stéphane Nicoll 21bc8726d6 Merge pull request #33354 from GoncaloPT
* pr/33354:
  Polish "Fix error codes in Customizing Validation Errors section"
  Fix error codes in Customizing Validation Errors section

Closes gh-33354
2024-08-09 09:04:34 +02:00
Stéphane Nicoll df7ac9b308 Polish "Fix error codes in Customizing Validation Errors section"
See gh-33354
2024-08-09 09:03:05 +02:00
Gonçalo Silva 43217bdf06 Fix error codes in Customizing Validation Errors section
See gh-33354
2024-08-09 09:02:53 +02:00
Robert Danczak a31945f8b6 Fix syntax error in RestClient documentation
Closes gh-33350
2024-08-08 17:15:27 +03:00
Simon Baslé a0edf129eb Fix misleading statement in ReactorResourceFactory javadoc
Closes gh-33338
2024-08-08 15:26:10 +02:00
Sam Brannen bcffa15c7d Reinstate qualifier support for JSR-330 @⁠javax.inject.Named
This commit revises QualifierAnnotationAutowireCandidateResolver to
reinstate "qualifier" support for the legacy JSR-330
@⁠javax.inject.Named annotation.

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

Closes gh-33341
2024-08-08 11:41:48 +02:00
Paul-Christian Volkmer 7e4884fcfa Add missing Kotlin example for expectAll()
See gh-33341
2024-08-08 11:35:12 +02:00
Jonatan Ivanov 38a3d18256 Start Observation before scope open for Scheduled operation
When ScheduledAnnotationReactiveSupport adds the Observation to the
context, Reactor opens a scope through the Context Propagation API.
This happens before TrackingSubscriber would start the Observation and
opening a scope without starting an Observation is invalid.

This change moves the Observation start before the scope opening.

Closes gh-33349
2024-08-08 10:46:19 +02:00
Jonatan Ivanov 6c74fee5e8 Remove unnecessary error signal from DefaultRestClient
Before UnknownContentTypeException is thrown, it is added to the current
Observation but since UnknownContentTypeException is a
RestClientException, the exception is added again in one of the
catch blocks later on.

Closes gh-33347
2024-08-08 09:30:22 +02:00
Jonatan Ivanov 36e84a5209 Fix RestClient instrumentation
ClientHttpResponse implements Closeable and the close method of
DefaultConvertibleClientHttpResponse also stops the current Observation.

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

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

Closes gh-33346
2024-08-08 09:11:57 +02:00
Sam Brannen 1e97b2137b Disable class data sharing (CDS) for tests
Prior to this commit, the Gradle build output the following warning
multiple times.

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

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

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

Closes gh-33251
2024-08-07 16:28:17 +02:00
Aleksey Genus 9b85a246d8 SimpleAsyncTaskScheduler stops accepting new tasks when isShutdown
This changes the criteria for simplified task rejection logging from
to be that the executor is in the shutdown phase, not fully terminated.

See gh-33334
Closes gh-33336
2024-08-07 15:58:27 +02:00
Stéphane Nicoll 5a99407847 Start building against Reactor 2023.0.9 snapshots
See gh-33326
2024-08-07 10:02:20 +02:00
Stéphane Nicoll 05bd246cab Start building against Micrometer 1.12.9 snapshots
See gh-33325
2024-08-07 10:01:54 +02:00
Sam Brannen 0127de5a7a Enforce read-only semantics in SpEL's SimpleEvaluationContext
SimpleEvaluationContext.forReadOnlyDataBinding() documents that it
creates a SimpleEvaluationContext for read-only access to public
properties; however, prior to this commit write access was not disabled
for indexed structures when using the assignment operator, the
increment operator, or the decrement operator.

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

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

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

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

Closes gh-33319
2024-08-06 13:54:11 +03:00
Sam Brannen fcc99a67b6 Support lists for varargs invocations in SpEL
The changes made in conjunction with gh-33013 resulted in a regression
for varargs support in SpEL expressions. Specifically, before gh-33013
one could supply a list -- for example, an "inline list" -- as the
varargs array when invoking a varargs constructor, method, or function
within a SpEL expression. However, after gh-33013 an inline list (or
collection in general) is no longer converted to an array for varargs
invocations. Instead, the list is supplied as a single argument of the
resulting varargs array which breaks applications that depend on the
previous behavior.

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

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

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

See gh-33013
Closes gh-33315
2024-08-05 16:28:11 +03:00
Sam Brannen 8afff3359b Polishing 2024-08-05 15:01:41 +03:00
Sam Brannen c57c2272a1 Throw exception for failure to set property as index in SpEL
Prior to this commit, the Indexer in the Spring Expression Language
(SpEL) silently ignored a failure to set a property via the indexed
property syntax (['<property name>'] = <new value>) – for example, if
property write access was disabled in the EvaluationContext.

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

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

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

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

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

Closes gh-33317
2024-08-05 11:56:48 +03:00
Sam Brannen 444e7eeb74 Enable test for primitive array to Object[] conversion in SpEL
See gh-33212
2024-08-05 11:05:53 +03:00
Sam Brannen cb6a5baac5 Support conversion from primitive array to Object[] in ConversionService
Prior to this commit, the ConversionService failed to convert a primitive
array (such as int[]) to an Object[] due to an error in the logic in
ArrayToArrayConverter.

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

Closes gh-33212
2024-08-04 17:13:56 +03:00
Stéphane Nicoll 3b2a818f1e Upgrade to Java 17.0.12 2024-08-04 09:34:13 +02:00
Stéphane Nicoll 84d1122190 Shorten CI and deploy snapshot jobs to 60 minutes
Closes gh-33302
2024-08-02 10:56:25 +02:00
Simon Baslé 722dcae1b1 Fix buffer leak in MultipartParser
This change fixes a buffer leak when the MultipartParser is encountering
a body DataBuffer that only contains a boundary.

Closes gh-33094
2024-08-01 16:28:50 +02:00
Stéphane Nicoll 850a0de1b0 Suppress deprecated warnings for autowiring
This commit extends our handling of deprecated with AOT to autowiring.

Closes gh-33295
2024-07-31 16:51:06 +02:00
Stéphane Nicoll 321e8a58ae Document that NoOpResponseErrorHandler is not a good fit with RestClient
Closes gh-33276
2024-07-30 17:17:39 +02:00
Stéphane Nicoll 46ba13b645 Review Caching infrastructure documentation
Closes gh-33288
2024-07-29 11:29:35 +02:00
Juergen Hoeller 9d9e621efe Defensive singleton check for non-registered bean
Closes gh-33286
2024-07-29 10:47:08 +02:00
Sam Brannen 5aa38833dd Fix XJC configuration to re-enable Eclipse IDE support
Our recent switch from the `org.unbroken-dome.xjc` plugin to the
`com.github.bjornvester.xjc` plugin resulted in errors when trying to
import Spring Framework projects into the Eclipse IDE.

This commit fixes those issues as follows.

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

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

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

Closes gh-33264
2024-07-26 16:39:40 +03:00
Stéphane Nicoll 9aac24c18a Merge pull request #33277 from sheip9
* pr/33277:
  Polish "Fix reference to configurePathMatching in code sample"
  Fix reference to configurePathMatching in code sample

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

Closes gh-33273
2024-07-25 16:28:40 +02:00
Stéphane Nicoll bcdc991838 Switch to Shadow plugin fork
This commit fixes to a fork of the shadow plugin that fixes support
with recent Gradle releases.

See https://github.com/johnrengelman/shadow/pull/876
2024-07-24 11:42:54 +02:00
Stéphane Nicoll 589f17f48b Polish "Upgrade XJC processing to com.github.bjornvester.xjc"
See gh-33264
2024-07-24 11:42:25 +02:00
Brian Clozel 9366308285 Fix Gradle warning in RuntimeHintsAgentPlugin
Fixing the following warning in the runtime hints plugin configuration:
https://docs.gradle.org/8.9/userguide/upgrading_version_8.html#test_task_default_classpath
2024-07-23 17:09:13 +02:00
Stéphane Nicoll 12b996b07d Upgrade XJC processing to com.github.bjornvester.xjc
This commit upgrades our build to use a different plugin for XJC
processing, so that Gradle doesn't output a compatibility warning
anymore.

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

Closes gh-33264
2024-07-23 16:19:30 +02:00
Stéphane Nicoll 656d08f075 Fix warning in doc generation 2024-07-23 15:06:59 +02:00
Stéphane Nicoll 6e9a19212f Consistently check for Content-Length value
This commit makes sure to consistently check that the content length
is not set above 2GB. Previously it was only checked in
setContentLength.

Closes gh-33256
2024-07-23 10:43:48 +02:00
Dawid Olbiński 83ff8e4e98 Support JAXBElement subtypes in Jaxb2XmlEncoder
Closes gh-33258
2024-07-23 09:19:11 +02:00
Stéphane Nicoll cbdaafd409 Order dependencies 2024-07-21 13:02:15 +02:00
Stéphane Nicoll e5c505b71a Merge pull request #33248 from ngocnhan-tran1996
* pr/33248:
  Polish "Stop referring to STRUCT and ARRAY as they are deprecated"
  Stop referring to STRUCT and ARRAY as they are deprecated

Closes gh-33248
2024-07-21 11:40:11 +02:00
Stéphane Nicoll af8dc44469 Polish "Stop referring to STRUCT and ARRAY as they are deprecated"
See gh-33248
2024-07-21 11:39:16 +02:00
Tran Ngoc Nhan 955602bdbd Stop referring to STRUCT and ARRAY as they are deprecated
See gh-33248
2024-07-21 11:18:12 +02:00
Stéphane Nicoll b62662296e Merge pull request #33245 from ngocnhan-tran1996
* pr/33245:
  Polish "Update links in reference manual"
  Update links in reference manual

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

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

Fixes gh-33221
2024-07-19 17:17:18 +02:00
Stéphane Nicoll e8630f3409 Remove useless permissions on build-and-deploy-snapshot workflow
Closes gh-33238
2024-07-19 11:17:50 +02:00
Stéphane Nicoll c250817284 Update GHA actions 2024-07-16 09:59:14 +02:00
rstoyanchev 77bdbf7e37 Polishing contribution
Closes gh-33181
2024-07-15 15:21:19 +01:00
kevin.kep 2fe7ab1f92 Trim last allowed origin in comma-delimited list
See gh-33181
2024-07-15 15:17:03 +01:00
Simon Baslé 6becfe2508 Fix AOP for Kotlin suspending function with aspect + @Cacheable
This change simplifies the CacheInterceptor way of dealing with cached
coroutines, thanks to the fact that lower level support for AOP has been
introduced in c8169e5c. This fix is similar to the one applied for
`@Transactional` in gh-33095.

Closes gh-33210
2024-07-15 11:47:12 +02:00
Stéphane Nicoll dfcd8374c7 Upgrade to Gradle 8.9
Closes gh-33214
2024-07-14 11:21:52 +02:00
Sam Brannen ae5dd54115 Add @⁠Disabled tests for primitive varargs array to Object[] conversion 2024-07-12 17:36:54 +02:00
Sam Brannen e088892fc1 Support MethodHandle invocation with primitive varargs array in SpEL
Prior to this commit, the Spring Expression Language (SpEL) could not
invoke a varargs MethodHandle function with a primitive array
containing the variable arguments, although that is supported for a
varargs Method function. Attempting to do so resulted in the first
element of the primitive array being supplied as a single argument to
the MethodHandle, effectively ignoring any variable arguments after the
first one.

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

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

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

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

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

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

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

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

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

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

Closes gh-33204
2024-07-12 08:37:36 +02:00
Stéphane Nicoll c9375167fd Harmonize properties of deploy action 2024-07-12 08:37:36 +02:00
Sam Brannen 48a6bd6ce7 Polishing 2024-07-11 18:30:52 +02:00
Stéphane Nicoll e15f123486 Remove concourse configuration now that CI is using GitHub Actions 2024-07-11 17:00:29 +02:00
Juergen Hoeller 2bfff7fc37 Retain original URL instance in case of custom URLStreamHandler
Closes gh-33199
2024-07-11 16:15:42 +02:00
Stéphane Nicoll 1880e109c3 Next development version (v6.1.12-SNAPSHOT) 2024-07-11 10:14:04 +02:00
rstoyanchev 611d3e5551 Correct type names in docs on Validation in WebFlux
Closes gh-33061
2024-07-10 17:55:19 +01:00
Sam Brannen fa2a58b9db Ensure varargs component type for MethodHandle is not null in SpEL
This commit ensures that the varargs component type for a MethodHandle
cannot be null in ReflectionHelper's
convertAllMethodHandleArguments(...) method in SpEL.

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

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

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

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

- Invokes the MethodHandle with the new arguments array.

Closes gh-33191
2024-07-10 16:16:41 +02:00
Sam Brannen dc16f3cffb Polish SpEL function invocation support 2024-07-10 16:16:41 +02:00
Juergen Hoeller f2b3263fff Polishing 2024-07-10 15:56:56 +02:00
Simon Baslé 1d890a8952 Make coroutines with custom AOP aspects work with @Transactional
Previous to this change, the transactional aspect would supersed the
user-defined AspectJ aspect, shortcircuiting to calling the original
Kotlin suspending function.

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

Closes gh-33095
2024-07-10 15:35:43 +02:00
Juergen Hoeller 3ccaefe38f Polishing 2024-07-10 15:15:32 +02:00
Juergen Hoeller 300f4585be Update spring.jdbc.getParameterType.ignore note for 6.1.2
See gh-25679
2024-07-10 15:15:26 +02:00
Sam Brannen a0f5c16627 Support MethodHandle function invocation with zero varargs in SpEL
Prior to this commit, the Spring Expression Language (SpEL) could not
invoke a varargs MethodHandle function with zero variable arguments,
even though the variable arguments are not required. Attempting to do
so resulted in a SpelEvaluationException with an
INCORRECT_NUMBER_OF_ARGUMENTS_TO_FUNCTION message.

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

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

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

Instead of:

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

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

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

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

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

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

Closes gh-33179
2024-07-10 10:11:32 +02:00
Stéphane Nicoll 86da45ba15 Upgrade to Reactor 2023.0.8
Closes gh-33169
2024-07-09 15:52:09 +02:00
Stéphane Nicoll 6a60298024 Upgrade to Micrometer 1.12.8
Closes gh-33168
2024-07-09 14:39:10 +02:00
Sébastien Deleuze f8b448e949 Upgrade to Kotlin Serialization 1.6.3
Closes gh-33175
2024-07-09 14:31:56 +02:00
Sébastien Deleuze 52a0e6f900 Upgrade to Kotlin 1.9.24
Closes gh-33177
2024-07-09 14:31:47 +02:00
Stéphane Nicoll 3d2fb3af3d Add verification tests
In preparation for releasing Spring Framework from GitHub actions, this
commit adds a `verify` workflow that validates that the released bits
are correct by running sample projects against them.

Closes gh-33178
2024-07-09 14:23:44 +02:00
Sébastien Deleuze 4f38079042 Throw proper DecodingException in Kotlin Serialization decoders
Closes gh-33138
2024-07-09 12:05:24 +02:00
rstoyanchev 3008d97f93 Polishing contribution
Closes gh-33150
2024-07-09 06:53:14 +01:00
Sébastien NUSSBAUMER f0c758498b Allow validation of Set method parameters
See gh-33150
2024-07-09 06:53:14 +01:00
Juergen Hoeller bc2deef951 Upgrade to JRuby 9.4.8, Rhino 1.7.15, Moneta 1.4.4, JSONassert 1.5.3 2024-07-08 22:55:54 +02:00
Juergen Hoeller 7322a0d3c5 Upgrade to Groovy 4.0.22, Tomcat 10.1.25, Jetty 12.0.11, Undertow 2.3.14 2024-07-08 19:43:19 +02:00
Juergen Hoeller 7227c30917 Allow tests to pass on Windows JVM (non-UTF-8 default encoding)
See gh-33071
2024-07-08 19:42:28 +02:00
Stéphane Nicoll 7e7f55cb23 Merge pull request #33166 from hunhee98
* pr/33166:
  Polish contribution
  Harmonize phrasing in URI Encoding section

Closes gh-33166
2024-07-08 16:51:51 +02:00
Stéphane Nicoll 84f20cd0a7 Polish contribution
See gh-33166
2024-07-08 16:51:23 +02:00
Hunhee Lee 3d8f1fb00f Harmonize phrasing in URI Encoding section
See gh-33166
2024-07-08 16:51:09 +02:00
Stéphane Nicoll e06115c06f Merge pull request #33156 from
* pr/33156:
  Polish "Implement DefaultErrorResponseBuilder#headers(Consumer)"
  Implement DefaultErrorResponseBuilder#headers(Consumer)

Closes gh-33156
2024-07-08 13:15:29 +02:00
Stéphane Nicoll 69850cad27 Polish "Implement DefaultErrorResponseBuilder#headers(Consumer)"
See gh-33156
2024-07-08 13:11:31 +02:00
Harry Yang bbbc95f773 Implement DefaultErrorResponseBuilder#headers(Consumer)
See gh-33156
2024-07-08 13:09:26 +02:00
Sam Brannen 83f7996c79 Polishing 2024-07-05 19:00:39 +02:00
Stéphane Nicoll 0544dfe090 Enable building against Java 23-ea
This commit updates the CI workflow to build against Java 23-ea as
well, using the temurin distribution. For consistency, we're also
building against Java 22.

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

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

See gh-32090
2024-07-05 09:46:45 +02:00
Sam Brannen 89338c91a9 Stop using using legacy locale data for Date/Time formatting tests
Commit 84714fbae9 introduced usage of the
-Djava.locale.providers=COMPAT command-line argument for javac in order
to allow our JDK 20 builds to pass by using legacy locale data.

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

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

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

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

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

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

Closes gh-33127
2024-07-04 15:20:46 +02:00
Stéphane Nicoll dfa6b4bd42 Upgrade to Gradle 8.8
Closes gh-33146
2024-07-04 10:23:15 +02:00
Stéphane Nicoll 099a97740e Downgrade Awaitility to 4.2.0
This is required to build against ea builds

Closes gh-33143
2024-07-04 04:20:43 +02:00
Juergen Hoeller daea3f0eae Apply fallback resolution for non-hierarchical URIs such as "file:."
Includes meaningful exception message for file system resolution.

Closes gh-33124
2024-07-03 16:36:18 +02:00
zizare 8974da2a5a Use error handler for reactive cache aspect
This change ensures that the cache error handler is used in case of
future-based or publisher-based asynchronous caching completing with an
exception.

Closes gh-33073
2024-07-02 11:29:53 +02:00
Brian Clozel ab236c7741 Re-enable async dispatches in Observation Filter
Prior to this commit, the fix for gh-32730 disabled the involvment of
the osbervation filter for async dispatches. Instead of relying on ASYNC
dispatches to close the observation for async requests, this is now
using an async listener instead: async dispatches are not guaranteed to
happen once the async request is handled.

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

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

Fixes gh-33091
2024-07-01 11:42:48 +02:00
Juergen Hoeller 61adf2dd25 Formal null safety for exception message through String.valueOf
See gh-33117
2024-06-28 18:09:39 +02:00
Juergen Hoeller 61894af0bd Expose FactoryBean attribute exception as BeanDefinitionStoreException
Closes gh-33117
2024-06-28 17:55:45 +02:00
rstoyanchev c74666a883 Polishing contribution
Closes gh-33105
2024-06-28 15:32:43 +01:00
vatsal 976b4f3533 Fix return value validation
Fix argument in call to applyReturnValueValidation()
method in MethodValidationInterceptor.java. Method
argument was passed instead of the return value of the
method that was being validated.

See gh-33105
2024-06-28 15:00:11 +01:00
Juergen Hoeller 100da83913 Detect ajc markers in superclasses as well (for weaving check)
Closes gh-33113
2024-06-28 11:36:17 +02:00
Sam Brannen e881c70a93 Upgrade to JUnit 5.10.3 2024-06-27 17:00:43 +02:00
Juergen Hoeller fea237c065 Lazily start and retain HttpClient once resource factory is running
Closes gh-33093
2024-06-27 12:03:10 +02:00
Sam Brannen 8b11ee9ee2 Document that ModelMap is not a supported argument type in WebFlux
Prior to this commit, the "Method Arguments" documentation for WebFlux
in the reference manual stated that WebFlux controller methods can
accept arguments of type Map, Model, or ModelMap to access the model.
However, ModelMap is actually not supported and results in exception
due to a type mismatch.

This commit updates the documentation to reflect this.

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

Closes gh-33107
2024-06-27 11:33:50 +02:00
Sam Brannen 1cf5264163 Polishing 2024-06-27 10:46:00 +02:00
Sam Brannen c68c6faa03 Fix comment in Method Injection example in reference manual
Prior to this commit, the comment in the XML configuration example in
the Method Injection section of the reference manual referred to the
wrong bean names.

Closes gh-33096
2024-06-26 16:45:06 +02:00
Brian Clozel 6dd5c85ed0 Support byte array payloads in ProtobufMessageConverter
Prior to this commit, the `ProtobufMessageConverter` used in messaging
would try and serialize the message payload by calling "toString()" on
it in order to pass it to the Protobuf JSON encoder.
While this works for `String` payloads, this fails for `byte[]` types.

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

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

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

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

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

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

This commit therefore removes the invalid configuration and adds a
comment to explain what's going on.
2024-06-25 16:56:21 +02:00
Juergen Hoeller 4e2fb308f6 Document contentLength() behavior for InputStreamResource and custom subclasses
Closes gh-33089
2024-06-24 12:10:35 +02:00
Sam Brannen 5f765fc8ce Polishing 2024-06-23 13:22:08 +02:00
Sam Brannen 6b456b6157 Upgrade to FreeMarker 2.3.33 2024-06-22 16:55:56 +02:00
Sam Brannen 000b563e83 Use consistent formatting for view name in AbstractView 2024-06-22 16:51:37 +02:00
Sam Brannen c571ee1f95 Fix typo in comment 2024-06-22 16:51:28 +02:00
Stéphane Nicoll 899f6308d9 Fix name of GitHub actions bot
See gh-gh-33076
2024-06-21 14:14:05 +02:00
Juergen Hoeller a580d6d6fc Leniently ignore type mismatch for LoadTimeWeaverAware beans
Closes gh-33082
2024-06-21 11:22:48 +02:00
Juergen Hoeller 66eddf99af Include original exception if cause is null
Closes gh-33080
See gh-32952
2024-06-20 18:56:43 +02:00
Stéphane Nicoll e94ec80df4 Exclude GitHub Actions bot from changelog
Closes gh-33076
2024-06-20 14:15:54 +02:00
Juergen Hoeller 2861e570fd Catch and log LinkageError in getTypeForFactoryMethod
Closes gh-33075
2024-06-20 13:47:43 +02:00
Spring Builds ee7a1e8b7e Next development version (v6.1.11-SNAPSHOT) 2024-06-19 15:37:10 +00:00
Brian Clozel f7307c9e07 Avoid recording RestClient observations twice
Prior to this commit, the fix for gh-32575 introduced cases where the
client observation would be stopped twice.

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

Fixes gh-33068
2024-06-19 12:46:21 +02:00
Brian Clozel 098c4b1dd7 Use Sonatype S01 token in release pipeline 2024-06-18 19:25:20 +02:00
Juergen Hoeller 65dbfd09b4 Defensive PersistenceExceptionTranslator bean retrieval on shutdown
Closes gh-33067
2024-06-18 18:31:15 +02:00
Sam Brannen 203fa75196 Support all "connection reset" phrases in DisconnectedClientHelper
Prior to this commit, the isClientDisconnectedException() method in
DisconnectedClientHelper checked whether the message of the ultimate
exception in an exception chain contained one of the phrases "broken
pipe" or "connection reset by peer". However, that failed to match if
the exception message contained "Connection reset", which is the case
for the SocketException thrown by throwConnectionReset() in
sun.nio.ch.SocketChannelImpl.

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

Closes gh-33064
2024-06-18 16:43:06 +02:00
Juergen Hoeller 9a56a8877f Polishing 2024-06-17 18:42:37 +02:00
Juergen Hoeller e79a9a5bff Correct and consistent event class names in constructor javadoc
Closes gh-33032
2024-06-17 18:42:30 +02:00
Juergen Hoeller 2c3c3831c1 Consistently ignore bridge method on generated subclass for visibility purposes
Closes gh-33030
2024-06-17 18:42:20 +02:00
Arjen Poutsma c38e9896c7 Remove use of ServletException in ModelFactory
This commit changes the use of HttpSessionRequiredException in
ModelFactory::initModel to an IllegalStateException, because the former
extends ServletException and cannot be used in WebFlux.

Closes gh-33043
2024-06-17 14:19:19 +02:00
Stéphane Nicoll 3e0849a566 Fix typo
Closes gh-33050
2024-06-17 13:39:18 +02:00
github-actions[bot] f3a605b92c Update Antora Spring UI to v0.4.16 2024-06-17 10:06:47 +00:00
Stéphane Nicoll 6fdff201e9 Fix property name in Container Extension Points section
Closes gh-33037
2024-06-16 16:47:36 +02:00
Stéphane Nicoll c42778a05b Merge pull request #33036 from tafjwr
* pr/33036:
  Polish "Fix typo in comment"
  Fix typo in comment

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

Closes gh-33031
2024-06-14 18:58:49 +02:00
Stéphane Nicoll d0aa7ad524 Fix invalid character in Javadoc of BeanFactory 2024-06-13 14:06:19 +02:00
Spring Builds 072fc80cdb Next development version (v6.1.10-SNAPSHOT) 2024-06-13 10:27:57 +00:00
Arjen Poutsma 6f32ff489a Use null stream in ReactorNettyClientResponse if no body is available
Closes gh-32805
2024-06-13 11:10:50 +02:00
Juergen Hoeller 24c8dfea1f Remove duplicated javadoc paragraph 2024-06-12 14:23:26 +02:00
Juergen Hoeller cdfe5816c8 Upgrade to Netty 4.1.111 and Awaitility 4.2.1 2024-06-12 14:23:14 +02:00
Juergen Hoeller 0ff200b2f1 Trigger cancellation on context close for non-managed objects only
Specifically for prototype/scoped beans and FactoryBean-exposed objects.

Closes gh-33009
2024-06-12 13:31:00 +02:00
Stéphane Nicoll 261dac87cc Upgrade to Reactor 2023.0.7
Closes gh-33007
2024-06-11 14:42:08 +02:00
Juergen Hoeller fce2f49e46 Polishing (aligned with main) 2024-06-11 09:07:09 +02:00
Juergen Hoeller eca2b9657e Documentation notes for @Bean overriding and bean name matching
Closes gh-32825
2024-06-11 09:06:33 +02:00
Juergen Hoeller e48f37d956 Upgrade to Micrometer 1.12.7
Closes gh-33001
2024-06-11 09:05:48 +02:00
Juergen Hoeller ddc397dd05 Upgrade to spring-javaformat-checkstyle 0.0.42 2024-06-11 09:04:30 +02:00
Stéphane Nicoll 6b7f0bd4b6 Fix typo 2024-06-11 06:47:42 +02:00
Sébastien Deleuze c97a895f09 Add support for double backslashes to StringUtils#cleanPath
Closes gh-32962
2024-06-10 22:25:31 +02:00
rstoyanchev 3b13f2ed38 Update code-of-conduct email 2024-06-10 10:48:06 +01:00
Stéphane Nicoll a0eebca0cf Merge pull request #32993 from hlmg
* pr/32993:
  Fix typo

Closes gh-32993
2024-06-10 10:02:36 +02:00
hlmg c6c64e6fe7 Fix typo
See gh-32993
2024-06-10 10:00:37 +02:00
Brian Clozel 0ca393c0dc Restrict memory allocation in ContentCachingRequestWrapper
Prior to this commit, the `ContentCachingRequestWrapper` could allocate
a `FastByteArrayOutputStream` block that was larger than the content
cache limit given as a consturctor argument. This was due to an
optimization applied in gh-31834 for allocating the right content cache
size when the request size is known.

Fixes gh-32987
2024-06-10 09:46:01 +02:00
Brian Clozel 6681394886 Stop observations for async requests in Servlet filter
Prior to this commit, the `ServerHttpObservationFilter` would support
async dispatches and would do the following:

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

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

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

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

Fixes gh-32730
2024-06-07 19:01:57 +02:00
Sébastien Deleuze 172987c874 Ignore checkpointOnRefresh after restore
Closes gh-32978
2024-06-07 18:41:37 +02:00
Thomas Deblock 47a5ebfde6 Support canEncode() for JAXBElement in Jaxb2XmlEncoder
Commit d7970e4ab8 introduced support for JAXBElement in
Jaxb2XmlEncoder's encodeValue() method; however, canEncode() still
returned false for a JAXBElement element type.

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

See gh-30552
See gh-32972
Closes gh-32977
2024-06-07 14:13:59 +02:00
Sébastien Deleuze 43a113f067 Polishing
See gh-32983
2024-06-07 13:45:09 +02:00
Sébastien Deleuze dc250e1cc1 Remove outdated copyright from index.adoc
Closes gh-32983
2024-06-07 13:35:21 +02:00
Sébastien Deleuze fe74fcfded Exclude node_modules from NoHttp checks
Closes gh-32980
2024-06-07 11:43:45 +02:00
Juergen Hoeller 2451bd62b0 Polishing 2024-06-06 20:43:31 +02:00
Juergen Hoeller 624d6dd167 Expose actual result value for @CacheEvict condition
Closes gh-32960
2024-06-06 20:43:04 +02:00
Juergen Hoeller 0ea96b4806 Skip ajc-compiled aspects for ajc-compiled target classes
Includes defensive ignoring of incompatible aspect types.

Closes gh-32970
2024-06-06 20:42:07 +02:00
Sébastien Deleuze c28a0d5627 Add missing hints for Hibernate @TenantId
Closes gh-32967
2024-06-06 10:04:35 +02:00
Juergen Hoeller 61d045ce52 Polishing 2024-06-06 08:54:37 +02:00
Juergen Hoeller c0bef2c693 Lazily start resources on demand (if necessary outside of lifecycle)
See gh-32945
2024-06-06 08:54:32 +02:00
Stéphane Nicoll c3a0eaa95e Merge pull request #32966 from ypyf
* pr/32966:
  Use HttpStatusCode consistently in reference guide

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

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

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

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

Fixes gh-32964
2024-06-05 20:02:46 +02:00
Juergen Hoeller 7785f94c4c Revise and align Reactor client lifecycle management
Closes gh-32945
2024-06-05 16:32:40 +02:00
Juergen Hoeller 4f6f2c0d41 Revert to separate get/put steps against method cache for concurrency
Closes gh-32958
2024-06-05 16:32:27 +02:00
Stéphane Nicoll e6da2a86fc Merge pull request #32957 from soglad
* pr/32957:
  Fix entity name in MappingSqlQuery example of reference guide

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

See gh-32952
2024-06-04 23:43:10 +02:00
Juergen Hoeller 524da905db Consistently throw IOException from ReactorNettyClientRequest
This commit renames ReactorNettyClientRequestFactoryTests.

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

Closes gh-32945
2024-06-04 22:59:18 +02:00
Sébastien Deleuze f6b608eecb Consistently support Hibernate annotation hint inference on methods
See gh-32842
2024-06-04 16:46:25 +02:00
Sébastien Deleuze 4da1511ed3 Infer hints for Hibernate generators
This commit updates
PersistenceManagedTypesBeanRegistrationAotProcessor
in order to infer hints for Hibernate annotations meta
annotated with `@ValueGenerationType` (like `@CreationTimestamp`)
and `@IdGeneratorType`.

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

Closes gh-32842
2024-06-04 16:46:25 +02:00
Stéphane Nicoll 7102c33661 Add section about using complex data structures with AOT
Closes gh-32273
2024-06-04 15:51:40 +02:00
Sébastien Deleuze 43409b00d0 Refine KotlinDetector.isKotlinType documentation
This commit documents changes in lambda detection
as of Kotlin 2.0.

Closes gh-32905
2024-06-03 18:58:13 +02:00
Sébastien Deleuze d55abc6cf9 Fix RegisterReflectionForBinding Javadoc
Closes gh-32947
2024-06-03 18:26:24 +02:00
Sébastien Deleuze 31806f3a6b Fix MethodValidationPostProcessor refdoc
Closes gh-32929
2024-06-03 18:20:52 +02:00
Juergen Hoeller 8a84241c1e Polishing 2024-06-03 12:46:31 +02:00
Juergen Hoeller 624be6d4e6 Report bean creation failure in sortAdvisors as AopConfigException
Closes gh-32230
2024-06-03 12:46:14 +02:00
Juergen Hoeller b08883b65c Avoid NoSuchMethodException for annotation attribute checks
Closes gh-32921
2024-06-03 12:45:11 +02:00
Cong-Xin Cynthia Qiu 542ba3517f Fix typo in Jakarta validation documentation
Closes gh-32928
2024-05-31 12:22:02 +02:00
Juergen Hoeller 8c6a7799be Upgrade to Checkstyle 10.17 2024-05-28 18:46:22 +02:00
Juergen Hoeller 557dbba585 Remove superfluous addToClassHierarchy call for Enum types
Closes gh-32906
2024-05-28 18:45:05 +02:00
Sam Brannen e9de426eb5 Support compilation of map indexing with primitive in SpEL
Prior to this commit, the Spring Expression Language (SpEL) failed to
compile an expression that indexed into a Map using a primitive literal
(boolean, int, long, float, or double).

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

Closes gh-32903
2024-05-28 10:19:15 +02:00
Sam Brannen cda577d1aa Support compilation of array and list indexing with Integer in SpEL
Prior to this commit, the Spring Expression Language (SpEL) failed to
compile an expression that indexed into any array or list using an
Integer.

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

See gh-32694
Closes gh-32908
2024-05-27 17:06:48 +02:00
Sam Brannen 8feb842df5 Upgrade to AssertJ 3.26.0
See https://github.com/assertj/assertj/issues/3322
2024-05-27 16:43:22 +02:00
Sam Brannen ea2931f24a Use Develocity Gradle plugin API to avoid deprecation warning
Prior to this commit, the Gradle build issued the following warning.

- The deprecated "gradleEnterprise.buildScan.value" API has been
  replaced by "develocity.buildScan.value"
2024-05-24 15:41:58 +02:00
Juergen Hoeller 26d1c38d84 Polishing 2024-05-24 13:05:49 +02:00
Juergen Hoeller 345daaabbc Detect original generic method for CGLIB bridge method
Closes gh-32888
2024-05-24 11:49:10 +02:00
Juergen Hoeller 6c08d93992 Polishing 2024-05-23 17:07:55 +02:00
Juergen Hoeller 6d7cd9c7dc Defensive handling of incompatible advice methods
This covers AspectJ transaction and caching aspects when encountered by Spring AOP.

Closes gh-32882
See gh-32793
2024-05-23 17:07:51 +02:00
Attacktive 73eb6f0660 Complete a Kotlin code snippet in the refdoc
Closes gh-32877
2024-05-23 16:03:34 +02:00
Stéphane Nicoll 31f298b929 Merge pull request #32874 from Seungpang
* pr/32874:
  Polish
  Document using ThreadLocal#remove instead of ThreadLocal#set(null)

Closes gh-32874
2024-05-23 08:14:00 +02:00
Stéphane Nicoll c01aab5850 Polish
See gh-32874
2024-05-23 08:12:30 +02:00
Seungrae 61ef5a8930 Document using ThreadLocal#remove instead of ThreadLocal#set(null)
See gh-32874
2024-05-23 08:10:54 +02:00
Spring Builds 3b53ee7038 Next development version (v6.1.9-SNAPSHOT) 2024-05-22 16:45:49 +00:00
rstoyanchev 89dd247b97 Improve docs on controller method validation
Closes gh-32807
2024-05-22 17:15:54 +01:00
Stéphane Nicoll 39dd1e4049 Remove outdated Javadoc links
Closes gh-32872
2024-05-22 14:40:25 +02:00
Rob Winch 34f4ad3b71 Modernize Antora Build
- Use same playbook as docs-build
- Use Env Variables to cause partial build (same as docs-build)
- Use package.json so that dependencies can be updated with dependabot
2024-05-22 10:20:20 +02:00
Juergen Hoeller ea596aa211 Select most specific advice method in case of override
Closes gh-32865
2024-05-22 10:00:31 +02:00
Juergen Hoeller 58da30cd30 Upgrade to Jetty Reactive HttpClient 4.0.4 2024-05-21 19:22:20 +02:00
Juergen Hoeller cd33b4e35a Polishing 2024-05-21 18:25:57 +02:00
Juergen Hoeller 20dea0dae2 Polishing 2024-05-21 17:39:11 +02:00
Juergen Hoeller fee17e11ba Default fallback parsing for UTC without milliseconds
Closes gh-32856
2024-05-21 17:39:06 +02:00
Juergen Hoeller 65e1337d35 Polishing 2024-05-21 11:16:25 +02:00
Juergen Hoeller a4c2f291d9 Avoid creation of SAXParserFactory for every read operation
Includes JAXBContext locking revision (avoiding synchronization) and consistent treatment of DocumentBuilderFactory (in terms of caching as well as locking).

Closes gh-32851
2024-05-21 11:16:19 +02:00
Stéphane Nicoll f26483d272 Detect deprecated element in generic types
This commit updates Spring AOT to suppress a deprecation warning for
a generic type that has a deprecated element. Previously we only were
checking for the raw class.

Closes gh-32850
2024-05-21 08:53:18 +02:00
Stéphane Nicoll 481d036f7a Avoid reader on empty content to be shared by multiple requests
This commit avoids several instances of MockHttpServletRequest to
have a common reader for empty content as closing it will have an
unwanted side effect on the others.

Closes gh-32820
2024-05-20 13:58:36 +02:00
Sébastien Deleuze 2a2ef443a5 Refine CDS documentation
Closes gh-32843
2024-05-20 10:24:29 +02:00
Juergen Hoeller 617833bec9 Defensively catch and log pointcut parsing exceptions
Closes gh-32838
See gh-32793
2024-05-17 12:27:59 +02:00
Spring Builds 4d633c2ea8 Next development version (v6.1.8-SNAPSHOT) 2024-05-16 09:04:43 +00:00
rstoyanchev 010e8a303b Polishing contribution
Closes gh-32799
2024-05-15 20:06:48 +01:00
Matteo Cristoforo 78549d4963 Fix cookie management in reactive JdkClientHttpRequest
Prevent cookies to be set to empty in the HTTP request if no cookie
is present

See gh-32799
2024-05-15 20:02:04 +01:00
Juergen Hoeller e4e6910122 Polishing 2024-05-15 14:15:52 +02:00
Juergen Hoeller 2270df515b Enforce cleaned URL for root resource from ClassLoader
Closes gh-32828
2024-05-15 14:15:47 +02:00
Juergen Hoeller 70886e32c0 Upgrade to Reactor 2023.0.6
Includes AspectJ 1.9.22.1, Tomcat 10.1.24, Jetty 12.0.9, Mockito 5.12

Closes gh-32786
2024-05-14 22:01:07 +02:00
Juergen Hoeller e509385eae Add InputStreamResource(InputStreamSource) constructor for lambda expressions
Includes notes for reliable InputStream closing, in particular with Spring MVC.

Closes gh-32802
2024-05-14 21:59:42 +02:00
Juergen Hoeller b7aafda872 Polishing 2024-05-14 13:43:35 +02:00
Brian Clozel a89a88d17c Upgrade to Micrometer 1.12.6
Closes gh-32810
2024-05-13 21:25:09 +02:00
Brian Clozel c6b6ccdc89 Close ResponseBodyEmitter in case of write errors
Prior to this commit, the `ReactiveTypeHandler` would handle `Flux`-like
return types from controller methods and adapt them to SSE streams using
the `SseEmitter`/`ResponseBodyEmitter` APIs. In case an `IOException` is
thrown while writing to the HTTP response stream, the
`ReactiveTypeHandler` would rely on the Servlet container to call
`AsyncListener#onError` - this would be the signal for Spring MVC to
complete the async exchange. To prevent racing issues between this
signal and the actual handling of the exception, changes like  gh-20173
were applied. Since then, robust checks were added with gh-32340 in
`StandardServletAsyncWebRequest.LifecycleHttpServletResponse`.

With Jetty 12, `AsyncListener#onError` would not be called as the error
would happen while writing in blocking mode to the response (so, not
using the Servlet WriteListener contract). But still, such `IOException`
would still result in the closing of the HTTP connection. As of Jetty
12.0.4, this is no longer the case and the party managing the async
lifecycle is in charge of completing the exchange, as it should. This
means that the current behavior leaks HTTP connections for these cases
and causes memory issues.

This commit ensures that such exceptions happening during response
writes are caught and result in the completion of the `SSEEmitter` and
the closing of the exchange. Even if other Servlet containers still
propagate the error `AsyncListener#onError`, competing signals are still
managed with gh-32340.

Closes gh-32629
2024-05-13 20:30:13 +02:00
Brian Clozel 09b8feadc2 Document streaming/collecting behavior for Flux return values
Closes gh-32630
2024-05-13 13:12:53 +02:00
rstoyanchev d03ea0bf19 Update docs on HandlerInterceptor
Closes gh-32729
2024-05-13 11:40:32 +01:00
rstoyanchev a5a1ef6b30 Use instance field for ProblemDetail in ErrorResponse's
Closes gh-32644
2024-05-13 11:40:32 +01:00
rstoyanchev 1b60b86bb2 Update MockMvc section on Streaming in the docs
Closes gh-32687
2024-05-13 11:40:32 +01:00
Brian Clozel 89ce63f1f3 Replace RFC7807 by RFC9457 in documentation
This commit updates all references to RFC7807 by RFC9457 since the
former is now obsolete.

Closes gh-32806
2024-05-13 10:42:35 +02:00
Sam Brannen 7536980be9 Fix Dokka links to Spring Framework and Servlet APIs
This commit fixes links from Spring Framework's Dokka HTML to Javadoc
for Spring Framework and Servlet APIs by explicitly configuring the
`element-list` page as the `package-list` in the Dokka Gradle plugin.

Closes gh-32797
2024-05-12 12:29:52 +02:00
Sam Brannen c1229b03a7 Polishing 2024-05-11 16:01:08 +02:00
Juergen Hoeller a4135bac5c Leniently ignore unsupported pointcut expression
See gh-32793
2024-05-10 13:52:39 +02:00
Juergen Hoeller bf08e0c1b4 Polishing 2024-05-10 12:27:29 +02:00
Juergen Hoeller 9202c0ad41 Accept ajc-compiled @Aspect classes for Spring AOP proxy usage
Closes gh-32793
2024-05-10 12:27:12 +02:00
Juergen Hoeller 22b6d66a28 Document @Order behavior on @Configuration classes versus @Bean methods
Includes brief note on self injection (extracted from qualifiers section).

Closes gh-30177
Closes gh-28299
2024-05-08 17:52:02 +02:00
Juergen Hoeller 9376e6322d Revise IoC container introduction for modern configuration styles
Includes @Configuration(proxyBeanMethods=false) documentation.

Closes gh-32429
2024-05-08 17:51:25 +02:00
Juergen Hoeller 0eb937a866 Document limitations of CGLIB proxy class generation in JPMS module setups
Includes extended exception messages with common hints and explanations.

Closes gh-32671
2024-05-08 17:51:17 +02:00
Stéphane Nicoll 6250b64766 Add support for form data in MockHttpServletRequestBuilder
Closes gh-32757
2024-05-08 11:56:16 +02:00
Stéphane Nicoll 5b1278d03c Refine exception message to include bean name
Closes gh-32775
2024-05-08 10:27:34 +02:00
Juergen Hoeller 4f02be263f Polishing 2024-05-07 15:52:13 +02:00
Juergen Hoeller 05d9b52b19 Polishing 2024-05-06 20:10:40 +02:00
Juergen Hoeller 59a125d06f Unwrap raw target Query instance in case of proxy mismatch
Closes gh-32766
2024-05-06 20:09:43 +02:00
Sam Brannen aebc48ee8d Revise contribution
See gh-32704
2024-05-03 17:04:11 +03:00
Mikaël Francoeur f51be0a17e Support varargs invocations in SpEL for varargs array subtype
Closes gh-32704
2024-05-03 17:04:11 +03:00
Sam Brannen 1d2b5a15c3 Polishing 2024-05-03 17:04:11 +03:00
Sam Brannen 4baad16437 Include repeatable annotation container in MergedAnnotations results
A bug has existed in Spring's MergedAnnotations support since it was
introduced in Spring Framework 5.2. Specifically, if the
MergedAnnotations API is used to search for annotations with "standard
repeatable annotation" support enabled (which is the default), it's
possible to search for a repeatable annotation but not for the
repeatable annotation's container annotation.

The reason is that MergedAnnotationFinder.process(Object, int, Object,
Annotation) does not process the container annotation and instead only
processes the "contained" annotations, which prevents a container
annotation from being included in search results.

In #29685, we fixed a bug that prevented the MergedAnnotations support
from recognizing an annotation as a container if the container
annotation declares attributes other than the required `value`
attribute. As a consequence of that bug fix, since Spring Framework
5.3.25, the MergedAnnotations infrastructure considers such an
annotation a container, and due to the aforementioned bug the container
is no longer processed, which results in a regression in behavior for
annotation searches for such a container annotation.

This commit addresses the original bug as well as the regression by
processing container annotations in addition to the contained
repeatable annotations.

See gh-29685
Closes gh-32731
2024-05-03 12:18:04 +03:00
Stéphane Nicoll abcc1dfc6c Review usage of BindingReflectionHintsRegistrar#registerReflectionHints
Closes gh-32753
2024-05-02 16:53:59 +02:00
Brian Clozel 47c5cd208c Add missing "Content-Length: 0" header with HttpComponents
Prior to this commit, HTTP requests sent with the
`HttpComponentsClientHttpRequestFactory` would not set a
"Content-Length" header for empty request bodies. Setting a request
entity is the expected behavior for unsafe HTTP methods, and this would
align the behavior with other HTTP clients.
Developers would often rely on `BufferingClientHttpRequestFactory` to
set this information on the request.

This commit ensures that a `NullEntity` is used for unsafe HTTP methods,
when no body has been set for the request. This result in a
"Content-Length:0" request header.

Fixes gh-32678
2024-05-02 15:42:35 +02:00
Sam Brannen 5a24e94d2e Polish tests 2024-05-02 13:28:48 +03:00
Stéphane Nicoll f90bdbef42 Add noop implementation for ResponseErrorHandler
Closes gh-32750
2024-05-02 11:44:42 +02:00
Sébastien Deleuze f17527a48b Use expectBody<Person>() in WebTestClient documentation
Closes gh-32733
2024-05-02 11:07:36 +02:00
Brian Clozel 64b0283042 Revert "Do not set 0 Content-Length header in BufferingClientHttpRequestFactory"
This reverts commit b3a45670f9.

See gh-32650
2024-05-02 09:11:54 +02:00
Juergen Hoeller 25cedcfb99 Consistently propagate ApplicationStartup to BeanFactory
Closes gh-32747
2024-05-01 18:06:27 +02:00
Juergen Hoeller 610626aec6 Ignore non-String keys in PropertiesPropertySource.getPropertyNames()
Closes gh-32742
2024-05-01 15:41:26 +02:00
Brian Clozel d8afe7a8ad Fix build warnings
See gh-32724
2024-04-30 19:10:31 +02:00
Seungrae Kim 32c80d5ae6 Fix incorrect class reference syntax in Kotlin code sample
Closes gh-32733
2024-04-30 18:09:02 +03:00
Arjen Poutsma 0241a02e66 Fix guard against multiple subscriptions
This commit changes the guard against multiple subscriptions, as the
previously used doOnSubscribe hook could not function as guard in
certain scenarios.

Closes gh-32727
2024-04-30 16:07:03 +02:00
Juergen Hoeller cbda46984c Polishing 2024-04-30 15:46:28 +02:00
Juergen Hoeller 7263771552 Add documentation for CompletableFuture-driven rollback
Closes gh-32709
2024-04-30 15:45:56 +02:00
Juergen Hoeller fab3633c75 Add notes on constructor and factory method overloading
Closes gh-32091
2024-04-30 15:45:46 +02:00
Juergen Hoeller 26706f0039 Upgrade to Groovy 4.0.21, Tomcat 10.1.23, Jetty 12.0.8, Netty 4.1.109, Undertow 2.3.13, Checkstyle 10.16 2024-04-29 18:04:25 +02:00
Juergen Hoeller 3cf2cd70ab Polishing 2024-04-29 18:02:44 +02:00
Juergen Hoeller 0ac04a7f86 Include original exception message in dependency initialization exception
Closes gh-32470
2024-04-29 18:02:39 +02:00
Brian Clozel 370a4ee8b3 Upgrade to gradle-enterprise-conventions 0.0.17
Closes gh-32724
2024-04-29 13:15:05 +02:00
Simon Baslé 55361fa4f6 Release RSocket setup payload when it is not handled
This commit counterbalances the retain in the MessagingRSocket
handleConnectionSetupPayload method with a conditional release on SETUP
frame type in handleNoMatch, preventing Netty buffer leaks.

Closes gh-32424
2024-04-25 10:09:05 +02:00
Sam Brannen 546ca9b834 Polishing 2024-04-24 15:32:57 +03:00
Juergen Hoeller 09b476ac18 Polishing 2024-04-24 13:42:02 +02:00
Juergen Hoeller 387e34d881 Wrap depends-on exception for specifically requested top-level bean
Closes gh-32470
2024-04-24 13:41:48 +02:00
Stéphane Nicoll 4a10bc3288 Refine preDetermineBeanTypes algorithm
This commit refines the preDetermineBeanTypes algorithm that AOT uses
to approximate the order of preInstantiateSingletons more closely.

Previously, the algorithm assumed that all beans where non-lazy
singletons in terms of initialization order, which led to inconsistent
order in CGLIB proxy generation.

We now explicitly park lazy beans so that their types are determined
during a second phase, matching the order of regular initialization
order.

Closes gh-32669

Co-authored-by: Juergen Hoeller <juergen.hoeller@broadcom.com>
2024-04-24 09:23:51 +02:00
Juergen Hoeller 580adfcbed Polishing 2024-04-23 16:07:09 +02:00
Juergen Hoeller d151931f86 Skip close lock if acquired by other thread already
Closes gh-32445
2024-04-23 16:06:48 +02:00
Stéphane Nicoll 16d8d69cf9 Merge pull request #32696 from izeye
* pr/32696:
  Update copyright year of changed files
  Polish

Closes gh-32696
2024-04-23 15:34:44 +02:00
Stéphane Nicoll 95ac0eae4a Update copyright year of changed files
See gh-32696
2024-04-23 15:32:59 +02:00
Johnny Lim cc73ccefef Polish
See gh-32696
2024-04-23 15:31:48 +02:00
Stéphane Nicoll 4d34444a69 Consistent annotation lookup in MvcUriComponentsBuilder
Previously, a UriComponents build based on a method would require the
given method to be the annotated one as method parameter resolution only
applied locally. This was a problem when a controller was specified on
a method whose mapping is defined in a parent.

This commit harmonies the lookup using AnnotatedMethod who provides
support for a synthesized method parameter that takes annotations from
parent parameter into account.

Closes gh-32553
2024-04-23 15:21:27 +02:00
Juergen Hoeller d4ddbd537b Polishing 2024-04-23 13:16:33 +02:00
Juergen Hoeller 0b9b9b4602 Avoid overreading of InputStream in copyRange
Closes gh-32695
2024-04-23 13:16:28 +02:00
Stéphane Nicoll 40596d444c Provide a more explicit link to URI composition examples
Closes gh-32685
2024-04-23 12:43:15 +02:00
Stéphane Nicoll cb5b9dcaed Document AOT limitation of creating beans with custom arguments
Closes gh-32690
2024-04-23 11:03:28 +02:00
Stéphane Nicoll c99e7f8616 Ignore InstanceSupplier for getBean with arguments
Previously, a BeanDefinition that has an instance supplier would be
used irrespective of custom arguments being provided. This commit only
applies the instance supplier if no arguments are provided. With
custom arguments, the regular lookup takes place based on the
information provided in the bean factory.

Closes gh-32657
2024-04-22 16:59:31 +02:00
Stéphane Nicoll 8a8c8fe00e Detect target of factory method with AOT
Previously, if a factory method is defined on a parent, the generated
code would blindly use the method's declaring class for both the target
of the generated code, and the signature of the method.

This commit improves the resolution by considering the factory metadata
in the BeanDefinition.

Closes gh-32609
2024-04-22 15:13:56 +02:00
Stéphane Nicoll f45e7b9b9b Relax scope of DataIntegrityViolationException
This commit updates the Javadoc of DataIntegrityViolationException to
broaden its scope as it was too specific before.

Closes gh-32631
2024-04-22 14:49:17 +02:00
Juergen Hoeller ec1f5ca600 Polishing 2024-04-22 13:43:07 +02:00
Juergen Hoeller 62efdfb89c Try early initialization for all user-declared methods (including interfaces)
Closes gh-32682
2024-04-22 13:43:02 +02:00
Stéphane Nicoll c3da43291b Upgrade to Java 17.0.11 2024-04-22 12:13:01 +02:00
Brian Clozel 5aa576f5c6 Register status handler exceptions in observations
Prior to this commit, `RestClientException` thrown by status handlers
would not be registered as observation errors. This commit ensures that
such exceptions are first caught, registered in the observation and
rethrown as expected.

Closes gh-32575
2024-04-20 19:44:11 +02:00
Brian Clozel 0268180799 Rethrow unhandled JMS listener exceptions
Fixes gh-32666
2024-04-18 21:44:44 +02:00
Brian Clozel da4547a27e Extend observations to RestClient ResponseSpec
Prior to this commit, the `RestClient` observations would be stopped as
soon as the exchange function was called. This means that all errors
related to response decoding or mapping would not be recorded by the
obsevations.

This commit extends the observation recording to the `ResponseSpec` DSL
calls as well as custom exchange functions.

Fixes gh-32575
2024-04-18 21:26:18 +02:00
rstoyanchev 97eddb769a Avoid duplicate subscriptionId's in destinationCache
Closes gh-32625
2024-04-18 14:18:30 +01:00
Juergen Hoeller 0e0397a385 Polishing 2024-04-18 12:18:18 +02:00
Juergen Hoeller fec4f9b8cb Add test for pre-resolved target type on RootBeanDefinition
See gh-32649
2024-04-18 12:17:17 +02:00
Juergen Hoeller 4e20cdeb43 Expand comment on participation in existing transaction
Closes gh-32659
2024-04-18 12:16:33 +02:00
yhao3 7f27ba3902 Update links to HttpOnly documentation at OWASP in ResponseCookie
Closes gh-32663
2024-04-18 11:52:50 +02:00
Brian Clozel b3a45670f9 Do not set 0 Content-Length header in BufferingClientHttpRequestFactory
Prior to this commit, the `BufferingClientHttpRequestFactory`, through
the `AbstractBufferingClientHttpRequest`, would set a "Content-Length"
header value, even if the buffered body was empty.

This behavior is invalid since no request body would be set by the
client code in the first place.

This commit ensures that this header is only set if a request body has
been buffered and is about to be written to the request.

Fixes gh-32650
2024-04-17 22:44:36 +02:00
xumengqi 8ec27438e7 Fix transaction definition setTimeout error message since zero is valid
This commit rephrases the `DefaultTransactionDefinition#setTimeout`
exception message to better reflect the fact that 0 is a valid input
value.

Even though this often leads to a transaction immediately timing out
after opening, there is one notable case where this has another
meaningful effect: in Jakarta transactions (`UserTransaction`), when
passing 0 "the transaction service restores the default value".

Closes gh-32635
2024-04-16 16:39:23 +02:00
xumengqi bf3278596c Include actual cause's message in various parsing exception messages
This change improves the message of several parsing-related exceptions
that would previously entirely swallow the original exception's message
and sometimes have a slightly misleading message as a result.

This is done by appending the cause's `toString` representation to the
IllegalArgumentException messages instead of an hardcoded "cause".

Closes gh-32636
2024-04-16 16:25:42 +02:00
Arjen Poutsma 3971632415 Reintroduce SimpleClientHttpRequestFactory limitations
Closes gh-32641
2024-04-16 11:43:09 +02:00
Simon Baslé 1e54916119 Ensure multipart data is deleted in WebFlux when connection terminates
Before this change temporary files would not consistently be deleted
when the connection which uploads the multipart files closes naturally.

This change uses the usingWhen Reactor operator to ensure that the
termination of the connection doesn't prevent individual file parts
from being deleted due to a cancellation signal.

Closes gh-31217
2024-04-15 14:20:48 +02:00
Brian Clozel 6e20af41bf Upgrade CI image to Java 23ea17 2024-04-11 11:32:48 +02:00
Spring Builds c68c62b6c6 Next development version (v6.1.7-SNAPSHOT) 2024-04-11 08:26:17 +00:00
795 changed files with 16212 additions and 6379 deletions
@@ -0,0 +1,20 @@
name: Await HTTP Resource
description: 'Waits for an HTTP resource to be available (a HEAD request succeeds)'
inputs:
url:
description: 'URL of the resource to await'
required: true
runs:
using: composite
steps:
- name: Await HTTP resource
shell: bash
run: |
url=${{ inputs.url }}
echo "Waiting for $url"
until curl --fail --head --silent ${{ inputs.url }} > /dev/null
do
echo "."
sleep 60
done
echo "$url is available"
+61
View File
@@ -0,0 +1,61 @@
name: 'Build'
description: 'Builds the project, optionally publishing it to a local deployment repository'
inputs:
develocity-access-key:
description: 'Access key for authentication with ge.spring.io'
required: false
java-distribution:
description: 'Java distribution to use'
required: false
default: 'liberica'
java-early-access:
description: 'Whether the Java version is in early access'
required: false
default: 'false'
java-toolchain:
description: 'Whether a Java toolchain should be used'
required: false
default: 'false'
java-version:
description: 'Java version to compile and test with'
required: false
default: '17'
publish:
description: 'Whether to publish artifacts ready for deployment to Artifactory'
required: false
default: 'false'
outputs:
build-scan-url:
description: 'URL, if any, of the build scan produced by the build'
value: ${{ (inputs.publish == 'true' && steps.publish.outputs.build-scan-url) || steps.build.outputs.build-scan-url }}
version:
description: 'Version that was built'
value: ${{ steps.read-version.outputs.version }}
runs:
using: composite
steps:
- name: Prepare Gradle Build
uses: ./.github/actions/prepare-gradle-build
with:
develocity-access-key: ${{ inputs.develocity-access-key }}
java-distribution: ${{ inputs.java-distribution }}
java-early-access: ${{ inputs.java-early-access }}
java-toolchain: ${{ inputs.java-toolchain }}
java-version: ${{ inputs.java-version }}
- name: Build
id: build
if: ${{ inputs.publish == 'false' }}
shell: bash
run: ./gradlew check antora
- name: Publish
id: publish
if: ${{ inputs.publish == 'true' }}
shell: bash
run: ./gradlew -PdeploymentRepository=$(pwd)/deployment-repository build publishAllPublicationsToDeploymentRepository
- name: Read Version From gradle.properties
id: read-version
shell: bash
run: |
version=$(sed -n 's/version=\(.*\)/\1/p' gradle.properties)
echo "Version is $version"
echo "version=$version" >> $GITHUB_OUTPUT
@@ -0,0 +1,23 @@
name: Create GitHub Release
description: 'Create the release on GitHub with a changelog'
inputs:
milestone:
description: 'Name of the GitHub milestone for which a release will be created'
required: true
token:
description: 'Token to use for authentication with GitHub'
required: true
runs:
using: composite
steps:
- name: Generate Changelog
uses: spring-io/github-changelog-generator@86958813a62af8fb223b3fd3b5152035504bcb83 #v0.0.12
with:
config-file: .github/actions/create-github-release/changelog-generator.yml
milestone: ${{ inputs.milestone }}
token: ${{ inputs.token }}
- name: Create GitHub Release
shell: bash
env:
GITHUB_TOKEN: ${{ inputs.token }}
run: gh release create ${{ format('v{0}', inputs.milestone) }} --notes-file changelog.md
@@ -17,4 +17,12 @@ changelog:
- "type: dependency-upgrade"
contributors:
exclude:
names: ["bclozel", "jhoeller", "poutsma", "rstoyanchev", "sbrannen", "sdeleuze", "snicoll", "simonbasle"]
names:
- "bclozel"
- "jhoeller"
- "poutsma"
- "rstoyanchev"
- "sbrannen"
- "sdeleuze"
- "simonbasle"
- "snicoll"
@@ -0,0 +1,53 @@
name: Prepare Gradle Build
description: 'Prepares a Gradle build. Sets up Java and Gradle and configures Gradle properties'
inputs:
develocity-access-key:
description: 'Access key for authentication with ge.spring.io'
required: false
java-distribution:
description: 'Java distribution to use'
required: false
default: 'liberica'
java-early-access:
description: 'Whether the Java version is in early access. When true, forces java-distribution to temurin'
required: false
default: 'false'
java-toolchain:
description: 'Whether a Java toolchain should be used'
required: false
default: 'false'
java-version:
description: 'Java version to use for the build'
required: false
default: '17'
runs:
using: composite
steps:
- name: Set Up Java
uses: actions/setup-java@v4
with:
distribution: ${{ inputs.java-early-access == 'true' && 'temurin' || (inputs.java-distribution || 'liberica') }}
java-version: |
${{ inputs.java-early-access == 'true' && format('{0}-ea', inputs.java-version) || inputs.java-version }}
${{ inputs.java-toolchain == 'true' && '17' || '' }}
- name: Set Up Gradle
uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
with:
cache-read-only: false
develocity-access-key: ${{ inputs.develocity-access-key }}
- name: Configure Gradle Properties
shell: bash
run: |
mkdir -p $HOME/.gradle
echo 'systemProp.user.name=spring-builds+github' >> $HOME/.gradle/gradle.properties
echo 'systemProp.org.gradle.internal.launcher.welcomeMessageEnabled=false' >> $HOME/.gradle/gradle.properties
echo 'org.gradle.daemon=false' >> $HOME/.gradle/gradle.properties
echo 'org.gradle.daemon=4' >> $HOME/.gradle/gradle.properties
- name: Configure Toolchain Properties
if: ${{ inputs.java-toolchain == 'true' }}
shell: bash
run: |
echo toolchainVersion=${{ inputs.java-version }} >> $HOME/.gradle/gradle.properties
echo systemProp.org.gradle.java.installations.auto-detect=false >> $HOME/.gradle/gradle.properties
echo systemProp.org.gradle.java.installations.auto-download=false >> $HOME/.gradle/gradle.properties
echo systemProp.org.gradle.java.installations.paths=${{ format('$JAVA_HOME_{0}_X64', inputs.java-version) }} >> $HOME/.gradle/gradle.properties
@@ -0,0 +1,17 @@
name: Print JVM thread dumps
description: 'Prints a thread dump for all running JVMs'
runs:
using: composite
steps:
- if: ${{ runner.os == 'Linux' }}
shell: bash
run: |
for jvm_pid in $(jps -q -J-XX:+PerfDisableSharedMem); do
jcmd $jvm_pid Thread.print
done
- if: ${{ runner.os == 'Windows' }}
shell: powershell
run: |
foreach ($jvm_pid in $(jps -q -J-XX:+PerfDisableSharedMem)) {
jcmd $jvm_pid Thread.print
}
+20 -14
View File
@@ -1,33 +1,39 @@
name: Send notification
description: Sends a Google Chat message as a notification of the job's outcome
name: Send Notification
description: 'Sends a Google Chat message as a notification of the job''s outcome'
inputs:
webhook-url:
description: 'Google Chat Webhook URL'
required: true
build-scan-url:
description: 'URL of the build scan to include in the notification'
required: false
run-name:
description: 'Name of the run to include in the notification'
required: false
default: ${{ format('{0} {1}', github.ref_name, github.job) }}
status:
description: 'Status of the job'
required: true
build-scan-url:
description: 'URL of the build scan to include in the notification'
run-name:
description: 'Name of the run to include in the notification'
default: ${{ format('{0} {1}', github.ref_name, github.job) }}
webhook-url:
description: 'Google Chat Webhook URL'
required: true
runs:
using: composite
steps:
- shell: bash
- name: Prepare Variables
shell: bash
run: |
echo "BUILD_SCAN=${{ inputs.build-scan-url == '' && ' [build scan unavailable]' || format(' [<{0}|Build Scan>]', inputs.build-scan-url) }}" >> "$GITHUB_ENV"
echo "RUN_URL=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> "$GITHUB_ENV"
- shell: bash
- name: Success Notification
if: ${{ inputs.status == 'success' }}
shell: bash
run: |
curl -X POST '${{ inputs.webhook-url }}' -H 'Content-Type: application/json' -d '{ text: "<${{ env.RUN_URL }}|${{ inputs.run-name }}> was successful ${{ env.BUILD_SCAN }}"}' || true
- shell: bash
- name: Failure Notification
if: ${{ inputs.status == 'failure' }}
shell: bash
run: |
curl -X POST '${{ inputs.webhook-url }}' -H 'Content-Type: application/json' -d '{ text: "<users/all> *<${{ env.RUN_URL }}|${{ inputs.run-name }}> failed* ${{ env.BUILD_SCAN }}"}' || true
- shell: bash
- name: Cancel Notification
if: ${{ inputs.status == 'cancelled' }}
shell: bash
run: |
curl -X POST '${{ inputs.webhook-url }}' -H 'Content-Type: application/json' -d '{ text: "<${{ env.RUN_URL }}|${{ inputs.run-name }}> was cancelled"}' || true
@@ -0,0 +1,43 @@
name: Sync to Maven Central
description: 'Syncs a release to Maven Central and waits for it to be available for use'
inputs:
jfrog-cli-config-token:
description: 'Config token for the JFrog CLI'
required: true
ossrh-s01-staging-profile:
description: 'Staging profile to use when syncing to Central'
required: true
ossrh-s01-token-password:
description: 'Password for authentication with s01.oss.sonatype.org'
required: true
ossrh-s01-token-username:
description: 'Username for authentication with s01.oss.sonatype.org'
required: true
spring-framework-version:
description: 'Version of Spring Framework that is being synced to Central'
required: true
runs:
using: composite
steps:
- name: Set Up JFrog CLI
uses: jfrog/setup-jfrog-cli@9fe0f98bd45b19e6e931d457f4e98f8f84461fb5 # v4.4.1
env:
JF_ENV_SPRING: ${{ inputs.jfrog-cli-config-token }}
- name: Download Release Artifacts
shell: bash
run: jf rt download --spec ${{ format('{0}/artifacts.spec', github.action_path) }} --spec-vars 'buildName=${{ format('spring-framework-{0}', inputs.spring-framework-version) }};buildNumber=${{ github.run_number }}'
- name: Sync
uses: spring-io/nexus-sync-action@42477a2230a2f694f9eaa4643fa9e76b99b7ab84 # v0.0.1
with:
close: true
create: true
generate-checksums: true
password: ${{ inputs.ossrh-s01-token-password }}
release: true
staging-profile-name: ${{ inputs.ossrh-s01-staging-profile }}
upload: true
username: ${{ inputs.ossrh-s01-token-username }}
- name: Await
uses: ./.github/actions/await-http-resource
with:
url: ${{ format('https://repo.maven.apache.org/maven2/org/springframework/spring-context/{0}/spring-context-{0}.jar', inputs.spring-framework-version) }}
@@ -0,0 +1,20 @@
{
"files": [
{
"aql": {
"items.find": {
"$and": [
{
"@build.name": "${buildName}",
"@build.number": "${buildNumber}",
"path": {
"$nmatch": "org/springframework/framework-api/*"
}
}
]
}
},
"target": "nexus/"
}
]
}
+1 -2
View File
@@ -1,5 +1,4 @@
name: Backport Bot
on:
issues:
types: [labeled]
@@ -29,6 +28,6 @@ jobs:
run: wget https://github.com/spring-io/backport-bot/releases/download/latest/backport-bot-0.0.1-SNAPSHOT.jar
- name: Backport
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_EVENT: ${{ toJSON(github.event) }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: java -jar backport-bot-0.0.1-SNAPSHOT.jar --github.accessToken="$GITHUB_TOKEN" --github.event_name "$GITHUB_EVENT_NAME" --github.event "$GITHUB_EVENT"
+36 -42
View File
@@ -1,4 +1,4 @@
name: Build and deploy snapshot
name: Build and Deploy Snapshot
on:
push:
branches:
@@ -7,58 +7,52 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
build-and-deploy-snapshot:
name: Build and Deploy Snapshot
if: ${{ github.repository == 'spring-projects/spring-framework' }}
name: Build and deploy snapshot
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: 'liberica'
java-version: 17
- name: Check out code
- name: Check Out Code
uses: actions/checkout@v4
- name: Set up Gradle
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5
- name: Build and Publish
id: build-and-publish
uses: ./.github/actions/build
with:
cache-read-only: false
- name: Configure Gradle properties
shell: bash
run: |
mkdir -p $HOME/.gradle
echo 'systemProp.user.name=spring-builds+github' >> $HOME/.gradle/gradle.properties
echo 'systemProp.org.gradle.internal.launcher.welcomeMessageEnabled=false' >> $HOME/.gradle/gradle.properties
echo 'org.gradle.daemon=false' >> $HOME/.gradle/gradle.properties
echo 'org.gradle.daemon=4' >> $HOME/.gradle/gradle.properties
- name: Build and publish
id: build
env:
CI: 'true'
GRADLE_ENTERPRISE_URL: 'https://ge.spring.io'
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_SECRET_ACCESS_KEY }}
GRADLE_ENTERPRISE_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USER }}
GRADLE_ENTERPRISE_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }}
run: ./gradlew -PdeploymentRepository=$(pwd)/deployment-repository build publishAllPublicationsToDeploymentRepository
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
publish: true
- name: Deploy
uses: spring-io/artifactory-deploy-action@v0.0.1
uses: spring-io/artifactory-deploy-action@26bbe925a75f4f863e1e529e85be2d0093cac116 # v0.0.1
with:
uri: 'https://repo.spring.io'
username: ${{ secrets.ARTIFACTORY_USERNAME }}
password: ${{ secrets.ARTIFACTORY_PASSWORD }}
build-name: ${{ format('spring-framework-{0}', github.ref_name)}}
repository: 'libs-snapshot-local'
folder: 'deployment-repository'
signing-key: ${{ secrets.GPG_PRIVATE_KEY }}
signing-passphrase: ${{ secrets.GPG_PASSPHRASE }}
artifact-properties: |
/**/framework-api-*.zip::zip.name=spring-framework,zip.deployed=false
/**/framework-api-*-docs.zip::zip.type=docs
/**/framework-api-*-schema.zip::zip.type=schema
- name: Send notification
uses: ./.github/actions/send-notification
build-name: 'spring-framework-6.1.x'
folder: 'deployment-repository'
password: ${{ secrets.ARTIFACTORY_PASSWORD }}
repository: 'libs-snapshot-local'
signing-key: ${{ secrets.GPG_PRIVATE_KEY }}
signing-passphrase: ${{ secrets.GPG_PASSPHRASE }}
uri: 'https://repo.spring.io'
username: ${{ secrets.ARTIFACTORY_USERNAME }}
- name: Send Notification
if: always()
uses: ./.github/actions/send-notification
with:
webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }}
build-scan-url: ${{ steps.build-and-publish.outputs.build-scan-url }}
run-name: ${{ format('{0} | Linux | Java 17', github.ref_name) }}
status: ${{ job.status }}
build-scan-url: ${{ steps.build.outputs.build-scan-url }}
run-name: ${{ format('{0} | Linux | Java 17', github.ref_name) }}
webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }}
outputs:
version: ${{ steps.build-and-publish.outputs.version }}
verify:
name: Verify
needs: build-and-deploy-snapshot
uses: ./.github/workflows/verify.yml
secrets:
google-chat-webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }}
repository-password: ${{ secrets.ARTIFACTORY_PASSWORD }}
repository-username: ${{ secrets.ARTIFACTORY_USERNAME }}
token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
with:
version: ${{ needs.build-and-deploy-snapshot.outputs.version }}
+36
View File
@@ -0,0 +1,36 @@
name: Build Pull Request
on: pull_request
permissions:
contents: read
jobs:
build:
name: Build Pull Request
if: ${{ github.repository == 'spring-projects/spring-framework' }}
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Set Up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'liberica'
java-version: '17'
- name: Check Out
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
- name: Set Up Gradle
uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
- name: Build
env:
CI: 'true'
GRADLE_ENTERPRISE_URL: 'https://ge.spring.io'
run: ./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false --no-daemon --no-parallel --continue build
- name: Print JVM Thread Dumps When Cancelled
if: cancelled()
uses: ./.github/actions/print-jvm-thread-dumps
- name: Upload Build Reports
if: failure()
uses: actions/upload-artifact@v4
with:
name: build-reports
path: '**/build/reports/'
+21 -43
View File
@@ -7,7 +7,10 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
ci:
name: '${{ matrix.os.name}} | Java ${{ matrix.java.version}}'
if: ${{ github.repository == 'spring-projects/spring-framework' }}
runs-on: ${{ matrix.os.id }}
timeout-minutes: 60
strategy:
matrix:
os:
@@ -18,63 +21,38 @@ jobs:
toolchain: false
- version: 21
toolchain: true
- version: 22
toolchain: true
- version: 23
toolchain: true
exclude:
- os:
name: Linux
java:
version: 17
name: '${{ matrix.os.name}} | Java ${{ matrix.java.version}}'
runs-on: ${{ matrix.os.id }}
steps:
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: 'liberica'
java-version: |
${{ matrix.java.version }}
${{ matrix.java.toolchain && '17' || '' }}
- name: Prepare Windows runner
if: ${{ runner.os == 'Windows' }}
run: |
git config --global core.autocrlf true
git config --global core.longPaths true
Stop-Service -name Docker
- name: Check out code
- name: Check Out Code
uses: actions/checkout@v4
- name: Set up Gradle
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5
with:
cache-read-only: false
- name: Configure Gradle properties
shell: bash
run: |
mkdir -p $HOME/.gradle
echo 'systemProp.user.name=spring-builds+github' >> $HOME/.gradle/gradle.properties
echo 'systemProp.org.gradle.internal.launcher.welcomeMessageEnabled=false' >> $HOME/.gradle/gradle.properties
echo 'org.gradle.daemon=false' >> $HOME/.gradle/gradle.properties
echo 'org.gradle.daemon=4' >> $HOME/.gradle/gradle.properties
- name: Configure toolchain properties
if: ${{ matrix.java.toolchain }}
shell: bash
run: |
echo toolchainVersion=${{ matrix.java.version }} >> $HOME/.gradle/gradle.properties
echo systemProp.org.gradle.java.installations.auto-detect=false >> $HOME/.gradle/gradle.properties
echo systemProp.org.gradle.java.installations.auto-download=false >> $HOME/.gradle/gradle.properties
echo systemProp.org.gradle.java.installations.paths=${{ format('$JAVA_HOME_{0}_X64', matrix.java.version) }} >> $HOME/.gradle/gradle.properties
- name: Build
id: build
env:
CI: 'true'
GRADLE_ENTERPRISE_URL: 'https://ge.spring.io'
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_SECRET_ACCESS_KEY }}
GRADLE_ENTERPRISE_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USER }}
GRADLE_ENTERPRISE_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }}
run: ./gradlew check antora
- name: Send notification
uses: ./.github/actions/send-notification
if: always()
uses: ./.github/actions/build
with:
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
java-early-access: ${{ matrix.java.early-access || 'false' }}
java-distribution: ${{ matrix.java.distribution }}
java-toolchain: ${{ matrix.java.toolchain }}
java-version: ${{ matrix.java.version }}
- name: Send Notification
if: always()
uses: ./.github/actions/send-notification
with:
webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }}
status: ${{ job.status }}
build-scan-url: ${{ steps.build.outputs.build-scan-url }}
run-name: ${{ format('{0} | {1} | Java {2}', github.ref_name, matrix.os.name, matrix.java.version) }}
run-name: ${{ format('{0} | {1} | Java {2}', github.ref_name, matrix.os.name, matrix.java.version) }}
status: ${{ job.status }}
webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }}
+3 -2
View File
@@ -14,14 +14,15 @@ permissions:
actions: write
jobs:
build:
name: Dispatch docs deployment
if: ${{ github.repository == 'spring-projects/spring-framework' }}
runs-on: ubuntu-latest
if: github.repository_owner == 'spring-projects'
steps:
- name: Check out code
uses: actions/checkout@v4
with:
ref: docs-build
fetch-depth: 1
ref: docs-build
- name: Dispatch (partial build)
if: github.ref_type == 'branch'
env:
@@ -1,13 +0,0 @@
name: "Validate Gradle Wrapper"
on: [push, pull_request]
permissions:
contents: read
jobs:
validation:
name: "Validation"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: gradle/wrapper-validation-action@v2
+94
View File
@@ -0,0 +1,94 @@
name: Release
on:
push:
tags:
- v6.1.[0-9]+
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
build-and-stage-release:
name: Build and Stage Release
if: ${{ github.repository == 'spring-projects/spring-framework' }}
runs-on: ubuntu-latest
steps:
- name: Check Out Code
uses: actions/checkout@v4
- name: Build and Publish
id: build-and-publish
uses: ./.github/actions/build
with:
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
publish: true
- name: Stage Release
uses: spring-io/artifactory-deploy-action@26bbe925a75f4f863e1e529e85be2d0093cac116 # v0.0.1
with:
artifact-properties: |
/**/framework-api-*.zip::zip.name=spring-framework,zip.deployed=false
/**/framework-api-*-docs.zip::zip.type=docs
/**/framework-api-*-schema.zip::zip.type=schema
build-name: ${{ format('spring-framework-{0}', steps.build-and-publish.outputs.version)}}
folder: 'deployment-repository'
password: ${{ secrets.ARTIFACTORY_PASSWORD }}
repository: 'libs-staging-local'
signing-key: ${{ secrets.GPG_PRIVATE_KEY }}
signing-passphrase: ${{ secrets.GPG_PASSPHRASE }}
uri: 'https://repo.spring.io'
username: ${{ secrets.ARTIFACTORY_USERNAME }}
outputs:
version: ${{ steps.build-and-publish.outputs.version }}
verify:
name: Verify
needs: build-and-stage-release
uses: ./.github/workflows/verify.yml
secrets:
google-chat-webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }}
repository-password: ${{ secrets.ARTIFACTORY_PASSWORD }}
repository-username: ${{ secrets.ARTIFACTORY_USERNAME }}
token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
with:
staging: true
version: ${{ needs.build-and-stage-release.outputs.version }}
sync-to-maven-central:
name: Sync to Maven Central
needs:
- build-and-stage-release
- verify
runs-on: ubuntu-latest
steps:
- name: Check Out Code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Sync to Maven Central
uses: ./.github/actions/sync-to-maven-central
with:
jfrog-cli-config-token: ${{ secrets.JF_ARTIFACTORY_SPRING }}
ossrh-s01-staging-profile: ${{ secrets.OSSRH_S01_STAGING_PROFILE }}
ossrh-s01-token-password: ${{ secrets.OSSRH_S01_TOKEN_PASSWORD }}
ossrh-s01-token-username: ${{ secrets.OSSRH_S01_TOKEN_USERNAME }}
spring-framework-version: ${{ needs.build-and-stage-release.outputs.version }}
promote-release:
name: Promote Release
needs:
- build-and-stage-release
- sync-to-maven-central
runs-on: ubuntu-latest
steps:
- name: Set up JFrog CLI
uses: jfrog/setup-jfrog-cli@9fe0f98bd45b19e6e931d457f4e98f8f84461fb5 # v4.4.1
env:
JF_ENV_SPRING: ${{ secrets.JF_ARTIFACTORY_SPRING }}
- name: Promote build
run: jfrog rt build-promote ${{ format('spring-framework-{0}', needs.build-and-stage-release.outputs.version)}} ${{ github.run_number }} libs-release-local
create-github-release:
name: Create GitHub Release
needs:
- build-and-stage-release
- promote-release
runs-on: ubuntu-latest
steps:
- name: Check Out Code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Create GitHub Release
uses: ./.github/actions/create-github-release
with:
milestone: ${{ needs.build-and-stage-release.outputs.version }}
token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
+77
View File
@@ -0,0 +1,77 @@
name: Verify
on:
workflow_call:
inputs:
staging:
description: 'Whether the release to verify is in the staging repository'
required: false
default: false
type: boolean
version:
description: 'Version to verify'
required: true
type: string
secrets:
google-chat-webhook-url:
description: 'Google Chat Webhook URL'
required: true
repository-password:
description: 'Password for authentication with the repository'
required: false
repository-username:
description: 'Username for authentication with the repository'
required: false
token:
description: 'Token to use for authentication with GitHub'
required: true
jobs:
verify:
name: Verify
runs-on: ubuntu-latest
steps:
- name: Check Out Release Verification Tests
uses: actions/checkout@v4
with:
ref: 'v0.0.2'
repository: spring-projects/spring-framework-release-verification
token: ${{ secrets.token }}
- name: Check Out Send Notification Action
uses: actions/checkout@v4
with:
path: send-notification
sparse-checkout: .github/actions/send-notification
- name: Set Up Java
uses: actions/setup-java@v4
with:
distribution: 'liberica'
java-version: 17
- name: Set Up Gradle
uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
with:
cache-read-only: false
- name: Configure Gradle Properties
shell: bash
run: |
mkdir -p $HOME/.gradle
echo 'org.gradle.daemon=false' >> $HOME/.gradle/gradle.properties
- name: Run Release Verification Tests
env:
RVT_OSS_REPOSITORY_PASSWORD: ${{ secrets.repository-password }}
RVT_OSS_REPOSITORY_USERNAME: ${{ secrets.repository-username }}
RVT_RELEASE_TYPE: oss
RVT_STAGING: ${{ inputs.staging }}
RVT_VERSION: ${{ inputs.version }}
run: ./gradlew spring-framework-release-verification-tests:test
- name: Upload Build Reports on Failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: build-reports
path: '**/build/reports/'
- name: Send Notification
if: failure()
uses: ./send-notification/.github/actions/send-notification
with:
run-name: ${{ format('{0} | Verification | {1}', github.ref_name, inputs.version) }}
status: ${{ job.status }}
webhook-url: ${{ secrets.google-chat-webhook-url }}
+2
View File
@@ -51,3 +51,5 @@ atlassian-ide-plugin.xml
.vscode/
cached-antora-playbook.yml
node_modules
+1 -1
View File
@@ -1,3 +1,3 @@
# Enable auto-env through the sdkman_auto_env config
# Add key=value pairs of SDKs to use below
java=17.0.10-librca
java=17.0.13-librca
-44
View File
@@ -1,44 +0,0 @@
= Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of fostering an open
and welcoming community, we pledge to respect all people who contribute through reporting
issues, posting feature requests, updating documentation, submitting pull requests or
patches, and other activities.
We are committed to making participation in this project a harassment-free experience for
everyone, regardless of level of experience, gender, gender identity and expression,
sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic addresses,
without explicit permission
* Other unethical or unprofessional conduct
Project maintainers have the right and responsibility to remove, edit, or reject comments,
commits, code, wiki edits, issues, and other contributions that are not aligned to this
Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors
that they deem inappropriate, threatening, offensive, or harmful.
By adopting this Code of Conduct, project maintainers commit themselves to fairly and
consistently applying these principles to every aspect of managing this project. Project
maintainers who do not follow or enforce the Code of Conduct may be permanently removed
from the project team.
This Code of Conduct applies both within project spaces and in public spaces when an
individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
contacting a project maintainer at spring-code-of-conduct@pivotal.io . All complaints will
be reviewed and investigated and will result in a response that is deemed necessary and
appropriate to the circumstances. Maintainers are obligated to maintain confidentiality
with regard to the reporter of an incident.
This Code of Conduct is adapted from the
https://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
https://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]
+1 -1
View File
@@ -18,7 +18,7 @@ First off, thank you for taking the time to contribute! :+1: :tada:
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc).
By participating you are expected to uphold this code.
Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
Please report unacceptable behavior to spring-code-of-conduct@spring.io.
### How to Contribute
+1 -1
View File
@@ -6,7 +6,7 @@ Spring provides everything required beyond the Java programming language for cre
## Code of Conduct
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc). By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc). By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to spring-code-of-conduct@spring.io.
## Access to Binaries
+4 -6
View File
@@ -3,10 +3,10 @@ plugins {
// kotlinVersion is managed in gradle.properties
id 'org.jetbrains.kotlin.plugin.serialization' version "${kotlinVersion}" apply false
id 'org.jetbrains.dokka' version '1.8.20'
id 'org.unbroken-dome.xjc' version '2.0.0' apply false
id 'com.github.ben-manes.versions' version '0.51.0'
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
id 'com.github.bjornvester.xjc' version '1.8.2' apply false
id 'de.undercouch.download' version '5.4.0'
id 'io.github.goooler.shadow' version '8.1.8' apply false
id 'me.champeau.jmh' version '0.7.2' apply false
id 'me.champeau.mrjar' version '0.1.1'
}
@@ -89,21 +89,19 @@ configure([rootProject] + javaProjects) { project ->
ext.javadocLinks = [
"https://docs.oracle.com/en/java/javase/17/docs/api/",
"https://jakarta.ee/specifications/platform/9/apidocs/",
"https://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/", // CommonJ and weblogic.* packages
"https://docs.jboss.org/jbossas/javadoc/4.0.5/connector/", // org.jboss.resource.*
"https://docs.jboss.org/hibernate/orm/5.6/javadocs/",
"https://eclipse.dev/aspectj/doc/released/aspectj5rt-api",
"https://www.quartz-scheduler.org/api/2.3.0/",
"https://fasterxml.github.io/jackson-core/javadoc/2.14/",
"https://fasterxml.github.io/jackson-databind/javadoc/2.14/",
"https://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.14/",
"https://hc.apache.org/httpcomponents-client-5.2.x/current/httpclient5/apidocs/",
"https://hc.apache.org/httpcomponents-client-5.4.x/current/httpclient5/apidocs/",
"https://projectreactor.io/docs/test/release/api/",
"https://junit.org/junit4/javadoc/4.13.2/",
// TODO Uncomment link to JUnit 5 docs once we execute Gradle with Java 18+.
// See https://github.com/spring-projects/spring-framework/issues/27497
//
// "https://junit.org/junit5/docs/5.10.2/api/",
// "https://junit.org/junit5/docs/5.10.4/api/",
"https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/",
//"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/",
"https://r2dbc.io/spec/1.0.0.RELEASE/api/",
+1 -1
View File
@@ -1,2 +1,2 @@
org.gradle.caching=true
javaFormatVersion=0.0.41
javaFormatVersion=0.0.42
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,7 +50,7 @@ public class CheckstyleConventions {
project.getPlugins().apply(CheckstylePlugin.class);
project.getTasks().withType(Checkstyle.class).forEach(checkstyle -> checkstyle.getMaxHeapSize().set("1g"));
CheckstyleExtension checkstyle = project.getExtensions().getByType(CheckstyleExtension.class);
checkstyle.setToolVersion("10.15.0");
checkstyle.setToolVersion("10.22.0");
checkstyle.getConfigDirectory().set(project.getRootProject().file("src/checkstyle"));
String version = SpringJavaFormatPlugin.class.getPackage().getImplementationVersion();
DependencySet checkstyleDependencies = project.getConfigurations().getByName("checkstyle").getDependencies();
@@ -64,7 +64,7 @@ public class CheckstyleConventions {
NoHttpExtension noHttp = project.getExtensions().getByType(NoHttpExtension.class);
noHttp.setAllowlistFile(project.file("src/nohttp/allowlist.lines"));
noHttp.getSource().exclude("**/test-output/**", "**/.settings/**",
"**/.classpath", "**/.project", "**/.gradle/**");
"**/.classpath", "**/.project", "**/.gradle/**", "**/node_modules/**", "buildSrc/build/**");
List<String> buildFolders = List.of("bin", "build", "out");
project.allprojects(subproject -> {
Path rootPath = project.getRootDir().toPath();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,9 +62,11 @@ class TestConventions {
if (project.hasProperty("testGroups")) {
test.systemProperty("testGroups", project.getProperties().get("testGroups"));
}
test.jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED",
test.jvmArgs(
"--add-opens=java.base/java.lang=ALL-UNNAMED",
"--add-opens=java.base/java.util=ALL-UNNAMED",
"-Djava.locale.providers=COMPAT");
"-Xshare:off"
);
}
private void configureTestRetryPlugin(Project project, Test test) {
@@ -26,7 +26,9 @@ import org.gradle.api.attributes.LibraryElements;
import org.gradle.api.attributes.Usage;
import org.gradle.api.attributes.java.TargetJvmVersion;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.jvm.JvmTestSuite;
import org.gradle.api.tasks.testing.Test;
import org.gradle.testing.base.TestingExtension;
import java.util.Collections;
@@ -47,6 +49,8 @@ public class RuntimeHintsAgentPlugin implements Plugin<Project> {
public void apply(Project project) {
project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
TestingExtension testing = project.getExtensions().getByType(TestingExtension.class);
JvmTestSuite jvmTestSuite = (JvmTestSuite) testing.getSuites().getByName("test");
RuntimeHintsAgentExtension agentExtension = createRuntimeHintsAgentExtension(project);
Test agentTest = project.getTasks().create(RUNTIMEHINTS_TEST_TASK, Test.class, test -> {
test.useJUnitPlatform(options -> {
@@ -55,6 +59,8 @@ public class RuntimeHintsAgentPlugin implements Plugin<Project> {
test.include("**/*Tests.class", "**/*Test.class");
test.systemProperty("java.awt.headless", "true");
test.systemProperty("org.graalvm.nativeimage.imagecode", "runtime");
test.setTestClassesDirs(jvmTestSuite.getSources().getOutput().getClassesDirs());
test.setClasspath(jvmTestSuite.getSources().getRuntimeClasspath());
test.getJvmArgumentProviders().add(createRuntimeHintsAgentArgumentProvider(project, agentExtension));
});
project.getTasks().getByName("check", task -> task.dependsOn(agentTest));
-59
View File
@@ -1,59 +0,0 @@
== Spring Framework Concourse pipeline
NOTE: CI is being migrated to GitHub Actions.
The Spring Framework uses https://concourse-ci.org/[Concourse] for its CI build and other automated tasks.
The Spring team has a dedicated Concourse instance available at https://ci.spring.io with a build pipeline
for https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-6.1.x[Spring Framework 6.1.x].
=== Setting up your development environment
If you're part of the Spring Framework project on GitHub, you can get access to CI management features.
First, you need to go to https://ci.spring.io and install the client CLI for your platform (see bottom right of the screen).
You can then login with the instance using:
[source]
----
$ fly -t spring login -n spring-framework -c https://ci.spring.io
----
Once logged in, you should get something like:
[source]
----
$ fly ts
name url team expiry
spring https://ci.spring.io spring-framework Wed, 25 Mar 2020 17:45:26 UTC
----
=== Pipeline configuration and structure
The build pipelines are described in `pipeline.yml` file.
This file is listing Concourse resources, i.e. build inputs and outputs such as container images, artifact repositories, source repositories, notification services, etc.
It also describes jobs (a job is a sequence of inputs, tasks and outputs); jobs are organized by groups.
The `pipeline.yml` definition contains `((parameters))` which are loaded from the `parameters.yml` file or from our https://docs.cloudfoundry.org/credhub/[credhub instance].
You'll find in this folder the following resources:
* `pipeline.yml` the build pipeline
* `parameters.yml` the build parameters used for the pipeline
* `images/` holds the container images definitions used in this pipeline
* `scripts/` holds the build scripts that ship within the CI container images
* `tasks` contains the task definitions used in the main `pipeline.yml`
=== Updating the build pipeline
Updating files on the repository is not enough to update the build pipeline, as changes need to be applied.
The pipeline can be deployed using the following command:
[source]
----
$ fly -t spring set-pipeline -p spring-framework-6.1.x -c ci/pipeline.yml -l ci/parameters.yml
----
NOTE: This assumes that you have credhub integration configured with the appropriate secrets.
-10
View File
@@ -1,10 +0,0 @@
logging:
level:
io.spring.concourse: DEBUG
spring:
main:
banner-mode: off
sonatype:
exclude:
- 'build-info\.json'
- '.*\.zip'
-21
View File
@@ -1,21 +0,0 @@
== CI Images
These images are used by CI to run the actual builds.
To build the image locally run the following from this directory:
----
$ docker build --no-cache -f <image-folder>/Dockerfile .
----
For example
----
$ docker build --no-cache -f spring-framework-ci-image/Dockerfile .
----
To test run:
----
$ docker run -it --entrypoint /bin/bash <SHA>
----
-12
View File
@@ -1,12 +0,0 @@
FROM ubuntu:jammy-20240125
ADD setup.sh /setup.sh
ADD get-jdk-url.sh /get-jdk-url.sh
RUN ./setup.sh
ENV JAVA_HOME /opt/openjdk/java17
ENV JDK17 /opt/openjdk/java17
ENV JDK21 /opt/openjdk/java21
ENV JDK23 /opt/openjdk/java23
ENV PATH $JAVA_HOME/bin:$PATH
-17
View File
@@ -1,17 +0,0 @@
#!/bin/bash
set -e
case "$1" in
java17)
echo "https://github.com/bell-sw/Liberica/releases/download/17.0.10%2B13/bellsoft-jdk17.0.10+13-linux-amd64.tar.gz"
;;
java21)
echo "https://github.com/bell-sw/Liberica/releases/download/21.0.2%2B14/bellsoft-jdk21.0.2+14-linux-amd64.tar.gz"
;;
java23)
echo "https://download.java.net/java/early_access/jdk23/10/GPL/openjdk-23-ea+10_linux-x64_bin.tar.gz"
;;
*)
echo $"Unknown java version"
exit 1
esac
-40
View File
@@ -1,40 +0,0 @@
#!/bin/bash
set -ex
###########################################################
# UTILS
###########################################################
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install --no-install-recommends -y tzdata ca-certificates net-tools libxml2-utils git curl libudev1 libxml2-utils iptables iproute2 jq fontconfig
ln -fs /usr/share/zoneinfo/UTC /etc/localtime
dpkg-reconfigure --frontend noninteractive tzdata
rm -rf /var/lib/apt/lists/*
curl https://raw.githubusercontent.com/spring-io/concourse-java-scripts/v0.0.4/concourse-java.sh > /opt/concourse-java.sh
###########################################################
# JAVA
###########################################################
mkdir -p /opt/openjdk
pushd /opt/openjdk > /dev/null
for jdk in java17 java21 java22
do
JDK_URL=$( /get-jdk-url.sh $jdk )
mkdir $jdk
pushd $jdk > /dev/null
curl -L ${JDK_URL} | tar zx --strip-components=1
test -f bin/java
test -f bin/javac
popd > /dev/null
done
popd
###########################################################
# GRADLE ENTERPRISE
###########################################################
cd /
mkdir ~/.gradle
echo 'systemProp.user.name=concourse' > ~/.gradle/gradle.properties
-10
View File
@@ -1,10 +0,0 @@
github-repo: "https://github.com/spring-projects/spring-framework.git"
github-repo-name: "spring-projects/spring-framework"
sonatype-staging-profile: "org.springframework"
docker-hub-organization: "springci"
artifactory-server: "https://repo.spring.io"
branch: "6.1.x"
milestone: "6.1.x"
build-name: "spring-framework"
pipeline-name: "spring-framework"
concourse-url: "https://ci.spring.io"
-295
View File
@@ -1,295 +0,0 @@
anchors:
git-repo-resource-source: &git-repo-resource-source
uri: ((github-repo))
username: ((github-username))
password: ((github-ci-release-token))
branch: ((branch))
gradle-enterprise-task-params: &gradle-enterprise-task-params
GRADLE_ENTERPRISE_ACCESS_KEY: ((gradle_enterprise_secret_access_key))
GRADLE_ENTERPRISE_CACHE_USERNAME: ((gradle_enterprise_cache_user.username))
GRADLE_ENTERPRISE_CACHE_PASSWORD: ((gradle_enterprise_cache_user.password))
sonatype-task-params: &sonatype-task-params
SONATYPE_USERNAME: ((sonatype-username))
SONATYPE_PASSWORD: ((sonatype-password))
SONATYPE_URL: ((sonatype-url))
SONATYPE_STAGING_PROFILE: ((sonatype-staging-profile))
artifactory-task-params: &artifactory-task-params
ARTIFACTORY_SERVER: ((artifactory-server))
ARTIFACTORY_USERNAME: ((artifactory-username))
ARTIFACTORY_PASSWORD: ((artifactory-password))
build-project-task-params: &build-project-task-params
BRANCH: ((branch))
<<: *gradle-enterprise-task-params
docker-resource-source: &docker-resource-source
username: ((docker-hub-username))
password: ((docker-hub-password))
changelog-task-params: &changelog-task-params
name: generated-changelog/tag
tag: generated-changelog/tag
body: generated-changelog/changelog.md
github-task-params: &github-task-params
GITHUB_USERNAME: ((github-username))
GITHUB_TOKEN: ((github-ci-release-token))
resource_types:
- name: registry-image
type: registry-image
source:
<<: *docker-resource-source
repository: concourse/registry-image-resource
tag: 1.8.0
- name: artifactory-resource
type: registry-image
source:
<<: *docker-resource-source
repository: springio/artifactory-resource
tag: 0.0.18
- name: github-release
type: registry-image
source:
<<: *docker-resource-source
repository: concourse/github-release-resource
tag: 1.8.0
- name: github-status-resource
type: registry-image
source:
<<: *docker-resource-source
repository: dpb587/github-status-resource
tag: master
resources:
- name: git-repo
type: git
icon: github
source:
<<: *git-repo-resource-source
- name: ci-images-git-repo
type: git
icon: github
source:
uri: ((github-repo))
branch: ((branch))
paths: ["ci/images/*"]
- name: ci-image
type: registry-image
icon: docker
source:
<<: *docker-resource-source
repository: ((docker-hub-organization))/spring-framework-ci
tag: ((milestone))
- name: artifactory-repo
type: artifactory-resource
icon: package-variant
source:
uri: ((artifactory-server))
username: ((artifactory-username))
password: ((artifactory-password))
build_name: ((build-name))
- name: github-pre-release
type: github-release
icon: briefcase-download-outline
source:
owner: spring-projects
repository: spring-framework
access_token: ((github-ci-release-token))
pre_release: true
release: false
- name: github-release
type: github-release
icon: briefcase-download
source:
owner: spring-projects
repository: spring-framework
access_token: ((github-ci-release-token))
pre_release: false
jobs:
- name: build-ci-images
plan:
- get: git-repo
- get: ci-images-git-repo
trigger: true
- task: build-ci-image
privileged: true
file: git-repo/ci/tasks/build-ci-image.yml
output_mapping:
image: ci-image
vars:
ci-image-name: ci-image
<<: *docker-resource-source
- put: ci-image
params:
image: ci-image/image.tar
- name: stage-milestone
serial: true
plan:
- get: ci-image
- get: git-repo
trigger: false
- task: stage
image: ci-image
file: git-repo/ci/tasks/stage-version.yml
params:
RELEASE_TYPE: M
<<: *gradle-enterprise-task-params
- put: artifactory-repo
params: &artifactory-params
signing_key: ((signing-key))
signing_passphrase: ((signing-passphrase))
repo: libs-staging-local
folder: distribution-repository
build_uri: "https://ci.spring.io/teams/${BUILD_TEAM_NAME}/pipelines/${BUILD_PIPELINE_NAME}/jobs/${BUILD_JOB_NAME}/builds/${BUILD_NAME}"
build_number: "${BUILD_PIPELINE_NAME}-${BUILD_JOB_NAME}-${BUILD_NAME}"
disable_checksum_uploads: true
threads: 8
artifact_set:
- include:
- "/**/framework-api-*.zip"
properties:
"zip.name": "spring-framework"
"zip.displayname": "Spring Framework"
"zip.deployed": "false"
- include:
- "/**/framework-api-*-docs.zip"
properties:
"zip.type": "docs"
- include:
- "/**/framework-api-*-schema.zip"
properties:
"zip.type": "schema"
get_params:
threads: 8
- put: git-repo
params:
repository: stage-git-repo
- name: promote-milestone
serial: true
plan:
- get: ci-image
- get: git-repo
trigger: false
- get: artifactory-repo
trigger: false
passed: [stage-milestone]
params:
download_artifacts: false
save_build_info: true
- task: promote
file: git-repo/ci/tasks/promote-version.yml
params:
RELEASE_TYPE: M
<<: *artifactory-task-params
- task: generate-changelog
file: git-repo/ci/tasks/generate-changelog.yml
params:
RELEASE_TYPE: M
<<: *github-task-params
<<: *docker-resource-source
- put: github-pre-release
params:
<<: *changelog-task-params
- name: stage-rc
serial: true
plan:
- get: ci-image
- get: git-repo
trigger: false
- task: stage
image: ci-image
file: git-repo/ci/tasks/stage-version.yml
params:
RELEASE_TYPE: RC
<<: *gradle-enterprise-task-params
- put: artifactory-repo
params:
<<: *artifactory-params
- put: git-repo
params:
repository: stage-git-repo
- name: promote-rc
serial: true
plan:
- get: ci-image
- get: git-repo
trigger: false
- get: artifactory-repo
trigger: false
passed: [stage-rc]
params:
download_artifacts: false
save_build_info: true
- task: promote
file: git-repo/ci/tasks/promote-version.yml
params:
RELEASE_TYPE: RC
<<: *docker-resource-source
<<: *artifactory-task-params
- task: generate-changelog
file: git-repo/ci/tasks/generate-changelog.yml
params:
RELEASE_TYPE: RC
<<: *github-task-params
- put: github-pre-release
params:
<<: *changelog-task-params
- name: stage-release
serial: true
plan:
- get: ci-image
- get: git-repo
trigger: false
- task: stage
image: ci-image
file: git-repo/ci/tasks/stage-version.yml
params:
RELEASE_TYPE: RELEASE
<<: *gradle-enterprise-task-params
- put: artifactory-repo
params:
<<: *artifactory-params
- put: git-repo
params:
repository: stage-git-repo
- name: promote-release
serial: true
plan:
- get: ci-image
- get: git-repo
trigger: false
- get: artifactory-repo
trigger: false
passed: [stage-release]
params:
download_artifacts: true
save_build_info: true
- task: promote
file: git-repo/ci/tasks/promote-version.yml
params:
RELEASE_TYPE: RELEASE
<<: *docker-resource-source
<<: *artifactory-task-params
<<: *sonatype-task-params
- name: create-github-release
serial: true
plan:
- get: ci-image
- get: git-repo
- get: artifactory-repo
trigger: true
passed: [promote-release]
params:
download_artifacts: false
save_build_info: true
- task: generate-changelog
file: git-repo/ci/tasks/generate-changelog.yml
params:
RELEASE_TYPE: RELEASE
<<: *docker-resource-source
<<: *github-task-params
- put: github-release
params:
<<: *changelog-task-params
groups:
- name: "releases"
jobs: ["stage-milestone", "stage-rc", "stage-release", "promote-milestone", "promote-rc", "promote-release", "create-github-release"]
- name: "ci-images"
jobs: ["build-ci-images"]
-2
View File
@@ -1,2 +0,0 @@
source /opt/concourse-java.sh
setup_symlinks
-12
View File
@@ -1,12 +0,0 @@
#!/bin/bash
set -e
CONFIG_DIR=git-repo/ci/config
version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
java -jar /github-changelog-generator.jar \
--spring.config.location=${CONFIG_DIR}/changelog-generator.yml \
${version} generated-changelog/changelog.md
echo ${version} > generated-changelog/version
echo v${version} > generated-changelog/tag
-17
View File
@@ -1,17 +0,0 @@
#!/bin/bash
CONFIG_DIR=git-repo/ci/config
version=$( cat artifactory-repo/build-info.json | jq -r '.buildInfo.modules[0].id' | sed 's/.*:.*:\(.*\)/\1/' )
export BUILD_INFO_LOCATION=$(pwd)/artifactory-repo/build-info.json
java -jar /concourse-release-scripts.jar \
--spring.config.location=${CONFIG_DIR}/release-scripts.yml \
publishToCentral $RELEASE_TYPE $BUILD_INFO_LOCATION artifactory-repo || { exit 1; }
java -jar /concourse-release-scripts.jar \
--spring.config.location=${CONFIG_DIR}/release-scripts.yml \
promote $RELEASE_TYPE $BUILD_INFO_LOCATION || { exit 1; }
echo "Promotion complete"
echo $version > version/version
-51
View File
@@ -1,51 +0,0 @@
#!/bin/bash
set -e
source $(dirname $0)/common.sh
repository=$(pwd)/distribution-repository
pushd git-repo > /dev/null
git fetch --tags --all > /dev/null
popd > /dev/null
git clone git-repo stage-git-repo > /dev/null
pushd stage-git-repo > /dev/null
snapshotVersion=$( awk -F '=' '$1 == "version" { print $2 }' gradle.properties )
if [[ $RELEASE_TYPE = "M" ]]; then
stageVersion=$( get_next_milestone_release $snapshotVersion)
nextVersion=$snapshotVersion
elif [[ $RELEASE_TYPE = "RC" ]]; then
stageVersion=$( get_next_rc_release $snapshotVersion)
nextVersion=$snapshotVersion
elif [[ $RELEASE_TYPE = "RELEASE" ]]; then
stageVersion=$( get_next_release $snapshotVersion)
nextVersion=$( bump_version_number $snapshotVersion)
else
echo "Unknown release type $RELEASE_TYPE" >&2; exit 1;
fi
echo "Staging $stageVersion (next version will be $nextVersion)"
sed -i "s/version=$snapshotVersion/version=$stageVersion/" gradle.properties
git config user.name "Spring Builds" > /dev/null
git config user.email "spring-builds@users.noreply.github.com" > /dev/null
git add gradle.properties > /dev/null
git commit -m"Release v$stageVersion" > /dev/null
git tag -a "v$stageVersion" -m"Release v$stageVersion" > /dev/null
./gradlew --no-daemon --max-workers=4 -PdeploymentRepository=${repository} -Porg.gradle.java.installations.fromEnv=JDK17,JDK21 \
build publishAllPublicationsToDeploymentRepository
git reset --hard HEAD^ > /dev/null
if [[ $nextVersion != $snapshotVersion ]]; then
echo "Setting next development version (v$nextVersion)"
sed -i "s/version=$snapshotVersion/version=$nextVersion/" gradle.properties
git add gradle.properties > /dev/null
git commit -m"Next development version (v$nextVersion)" > /dev/null
fi;
echo "Staging Complete"
popd > /dev/null
-30
View File
@@ -1,30 +0,0 @@
---
platform: linux
image_resource:
type: registry-image
source:
repository: concourse/oci-build-task
tag: 0.10.0
username: ((docker-hub-username))
password: ((docker-hub-password))
inputs:
- name: ci-images-git-repo
outputs:
- name: image
caches:
- path: ci-image-cache
params:
CONTEXT: ci-images-git-repo/ci/images
DOCKERFILE: ci-images-git-repo/ci/images/ci-image/Dockerfile
DOCKER_HUB_AUTH: ((docker-hub-auth))
run:
path: /bin/sh
args:
- "-c"
- |
mkdir -p /root/.docker
cat > /root/.docker/config.json <<EOF
{ "auths": { "https://index.docker.io/v1/": { "auth": "$DOCKER_HUB_AUTH" }}}
EOF
build
-22
View File
@@ -1,22 +0,0 @@
---
platform: linux
image_resource:
type: registry-image
source:
repository: springio/github-changelog-generator
tag: '0.0.8'
username: ((docker-hub-username))
password: ((docker-hub-password))
inputs:
- name: git-repo
- name: artifactory-repo
outputs:
- name: generated-changelog
params:
GITHUB_ORGANIZATION:
GITHUB_REPO:
GITHUB_USERNAME:
GITHUB_TOKEN:
RELEASE_TYPE:
run:
path: git-repo/ci/scripts/generate-changelog.sh
-25
View File
@@ -1,25 +0,0 @@
---
platform: linux
image_resource:
type: registry-image
source:
repository: springio/concourse-release-scripts
tag: '0.4.0'
username: ((docker-hub-username))
password: ((docker-hub-password))
inputs:
- name: git-repo
- name: artifactory-repo
outputs:
- name: version
params:
RELEASE_TYPE:
ARTIFACTORY_SERVER:
ARTIFACTORY_USERNAME:
ARTIFACTORY_PASSWORD:
SONATYPE_USER:
SONATYPE_PASSWORD:
SONATYPE_URL:
SONATYPE_STAGING_PROFILE:
run:
path: git-repo/ci/scripts/promote-version.sh
-17
View File
@@ -1,17 +0,0 @@
---
platform: linux
inputs:
- name: git-repo
outputs:
- name: stage-git-repo
- name: distribution-repository
params:
RELEASE_TYPE:
CI: true
GRADLE_ENTERPRISE_CACHE_USERNAME:
GRADLE_ENTERPRISE_CACHE_PASSWORD:
GRADLE_ENTERPRISE_URL: https://ge.spring.io
caches:
- path: gradle
run:
path: git-repo/ci/scripts/stage-version.sh
+2 -2
View File
@@ -28,7 +28,7 @@ javadoc {
header = rootProject.description
use = true
overview = project.relativePath("$rootProject.rootDir/framework-docs/src/docs/api/overview.html")
destinationDir = file("$project.docsDir/javadoc-api")
destinationDir = project.java.docsDir.dir("javadoc-api").get().asFile
splitIndex = true
links(rootProject.ext.javadocLinks)
addBooleanOption('Xdoclint:syntax,reference', true) // only check syntax and reference with doclint
@@ -52,7 +52,7 @@ rootProject.tasks.dokkaHtmlMultiModule.configure {
tasks.named("javadoc")
}
moduleName.set("spring-framework")
outputDirectory.set(file("$docsDir/kdoc-api"))
outputDirectory.set(project.java.docsDir.dir("kdoc-api").get().asFile)
includes.from("$rootProject.rootDir/framework-docs/src/docs/api/dokka-overview.md")
}
+39
View File
@@ -0,0 +1,39 @@
antora:
extensions:
- require: '@springio/antora-extensions'
root_component_name: 'framework'
site:
title: Spring Framework
url: https://docs.spring.io/spring-framework/reference
robots: allow
git:
ensure_git_suffix: false
content:
sources:
- url: https://github.com/spring-projects/spring-framework
# Refname matching:
# https://docs.antora.org/antora/latest/playbook/content-refname-matching/
branches: ['main', '{6..9}.+({1..9}).x']
tags: ['v{6..9}.+({0..9}).+({0..9})?(-{RC,M}*)', '!(v6.0.{0..8})', '!(v6.0.0-{RC,M}{0..9})']
start_path: framework-docs
asciidoc:
extensions:
- '@asciidoctor/tabs'
- '@springio/asciidoctor-extensions'
- '@springio/asciidoctor-extensions/include-code-extension'
attributes:
page-stackoverflow-url: https://stackoverflow.com/questions/tagged/spring
page-pagination: ''
hide-uri-scheme: '@'
tabs-sync-option: '@'
include-java: 'example$docs-src/main/java/org/springframework/docs'
urls:
latest_version_segment_strategy: redirect:to
latest_version_segment: ''
redirect_facility: httpd
runtime:
log:
failure_level: warn
ui:
bundle:
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.18/ui-bundle.zip
+6 -1
View File
@@ -20,6 +20,7 @@ asciidoc:
fold: 'all'
table-stripes: 'odd'
include-java: 'example$docs-src/main/java/org/springframework/docs'
include-kotlin: 'example$docs-src/main/kotlin/org/springframework/docs'
spring-site: 'https://spring.io'
spring-site-blog: '{spring-site}/blog'
spring-site-cve: "{spring-site}/security"
@@ -70,6 +71,9 @@ asciidoc:
kotlin-coroutines-api: '{kotlin-site}/api/kotlinx.coroutines'
kotlin-github-org: 'https://github.com/Kotlin'
kotlin-issues: 'https://youtrack.jetbrains.com/issue'
micrometer-docs: 'https://docs.micrometer.io/micrometer/reference'
micrometer-context-propagation-docs: 'https://docs.micrometer.io/context-propagation/reference'
petclinic-github-org: 'https://github.com/spring-petclinic'
reactive-streams-site: 'https://www.reactive-streams.org'
reactive-streams-spec: 'https://github.com/reactive-streams/reactive-streams-jvm/blob/master/README.md#specification'
reactor-github-org: 'https://github.com/reactor'
@@ -87,4 +91,5 @@ asciidoc:
stackoverflow-questions: '{stackoverflow-site}/questions'
stackoverflow-spring-tag: "{stackoverflow-questions}/tagged/spring"
stackoverflow-spring-kotlin-tags: "{stackoverflow-spring-tag}+kotlin"
testcontainers-site: 'https://www.testcontainers.org'
testcontainers-site: 'https://www.testcontainers.org'
vavr-docs: 'https://vavr-io.github.io/vavr-docs'
+8 -20
View File
@@ -10,27 +10,10 @@ apply from: "${rootDir}/gradle/ide.gradle"
apply from: "${rootDir}/gradle/publications.gradle"
antora {
version = '3.2.0-alpha.2'
playbook = 'cached-antora-playbook.yml'
playbookProvider {
repository = 'spring-projects/spring-framework'
branch = 'docs-build'
path = 'lib/antora/templates/per-branch-antora-playbook.yml'
checkLocalBranch = true
}
options = ['--clean', '--stacktrace']
options = [clean: true, fetch: !project.gradle.startParameter.offline, stacktrace: true]
environment = [
'ALGOLIA_API_KEY': '82c7ead946afbac3cf98c32446154691',
'ALGOLIA_APP_ID': '244V8V9FGG',
'ALGOLIA_INDEX_NAME': 'framework-docs'
]
dependencies = [
'@antora/atlas-extension': '1.0.0-alpha.1',
'@antora/collector-extension': '1.0.0-alpha.3',
'@asciidoctor/tabs': '1.0.0-beta.3',
'@opendevise/antora-release-line-extension': '1.0.0',
'@springio/antora-extensions': '1.8.2',
'@springio/asciidoctor-extensions': '1.0.0-alpha.9'
'BUILD_REFNAME': 'HEAD',
'BUILD_VERSION': project.version,
]
}
@@ -60,10 +43,15 @@ repositories {
dependencies {
api(project(":spring-context"))
api(project(":spring-jdbc"))
api(project(":spring-jms"))
api(project(":spring-web"))
api(project(":spring-webflux"))
api("com.oracle.database.jdbc:ojdbc11")
api("jakarta.jms:jakarta.jms-api")
api("jakarta.servlet:jakarta.servlet-api")
api("org.jetbrains.kotlin:kotlin-stdlib")
implementation(project(":spring-core-test"))
implementation("org.assertj:assertj-core")
@@ -23,6 +23,12 @@ The following table lists all currently supported Spring properties.
|===
| Name | Description
| `spring.aop.ajc.ignore`
| Instructs Spring to ignore ajc-compiled aspects for Spring AOP proxying, restoring traditional
Spring behavior for scenarios where both weaving and AspectJ auto-proxying are enabled. See
{spring-framework-api}++/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.html#IGNORE_AJC_PROPERTY_NAME++[`AbstractAspectJAdvisorFactory`]
for details.
| `spring.aot.enabled`
| Indicates the application should run with AOT generated artifacts. See
xref:core/aot.adoc[Ahead of Time Optimizations] and
@@ -32,7 +38,7 @@ for details.
| `spring.beaninfo.ignore`
| Instructs Spring to use the `Introspector.IGNORE_ALL_BEANINFO` mode when calling the
JavaBeans `Introspector`. See
{spring-framework-api}++/beans/StandardBeanInfoFactory.html#IGNORE_BEANINFO_PROPERTY_NAME++[`CachedIntrospectionResults`]
{spring-framework-api}++/beans/StandardBeanInfoFactory.html#IGNORE_BEANINFO_PROPERTY_NAME++[`StandardBeanInfoFactory`]
for details.
| `spring.cache.reactivestreams.ignore`
@@ -49,15 +55,13 @@ for details.
| `spring.context.checkpoint`
| Property that specifies a common context checkpoint. See
xref:integration/checkpoint-restore.adoc#_automatic_checkpointrestore_at_startup[Automatic
checkpoint/restore at startup] and
xref:integration/checkpoint-restore.adoc#_automatic_checkpointrestore_at_startup[Automatic checkpoint/restore at startup] and
{spring-framework-api}++/context/support/DefaultLifecycleProcessor.html#CHECKPOINT_PROPERTY_NAME++[`DefaultLifecycleProcessor`]
for details.
| `spring.context.exit`
| Property for terminating the JVM when the context reaches a specific phase. See
xref:integration/checkpoint-restore.adoc#_automatic_checkpointrestore_at_startup[Automatic
checkpoint/restore at startup] and
xref:integration/checkpoint-restore.adoc#_automatic_checkpointrestore_at_startup[Automatic checkpoint/restore at startup] and
{spring-framework-api}++/context/support/DefaultLifecycleProcessor.html#EXIT_PROPERTY_NAME++[`DefaultLifecycleProcessor`]
for details.
@@ -221,8 +221,8 @@ NOTE: `ThreadLocal` instances come with serious issues (potentially resulting in
incorrectly using them in multi-threaded and multi-classloader environments. You
should always consider wrapping a `ThreadLocal` in some other class and never directly use
the `ThreadLocal` itself (except in the wrapper class). Also, you should
always remember to correctly set and unset (where the latter simply involves a call to
`ThreadLocal.set(null)`) the resource local to the thread. Unsetting should be done in
always remember to correctly set and unset (where the latter involves a call to
`ThreadLocal.remove()`) the resource local to the thread. Unsetting should be done in
any case, since not unsetting it might result in problematic behavior. Spring's
`ThreadLocal` support does this for you and should always be considered in favor of using
`ThreadLocal` instances without other proper handling code.
@@ -19,6 +19,10 @@ you can do so. However, you should consider the following issues:
since the CGLIB proxy instance is created through Objenesis. Only if your JVM does
not allow for constructor bypassing, you might see double invocations and
corresponding debug log entries from Spring's AOP support.
* Your CGLIB proxy usage may face limitations with the JDK 9+ platform module system.
As a typical case, you cannot create a CGLIB proxy for a class from the `java.lang`
package when deploying on the module path. Such cases require a JVM bootstrap flag
`--add-opens=java.base/java.lang=ALL-UNNAMED` which is not available for modules.
To force the use of CGLIB proxies, set the value of the `proxy-target-class` attribute
of the `<aop:config>` element to true, as follows:
@@ -420,7 +420,7 @@ who typically are in charge of the deployment configuration, such as the launch
Now that the sales pitch is over, let us first walk through a quick example of AspectJ
LTW that uses Spring, followed by detailed specifics about elements introduced in the
example. For a complete example, see the
{spring-github-org}/spring-petclinic[Petclinic sample application].
{petclinic-github-org}/spring-framework-petclinic[Petclinic sample application based on Spring Framework].
[[aop-aj-ltw-first-example]]
@@ -36,7 +36,7 @@ NOTE: At the moment, AOT is focused on allowing Spring applications to be deploy
We intend to support more JVM-based use cases in future generations.
[[aot.basics]]
== AOT engine overview
== AOT Engine Overview
The entry point of the AOT engine for processing an `ApplicationContext` is `ApplicationContextAotGenerator`. It takes care of the following steps, based on a `GenericApplicationContext` that represents the application to optimize and a {spring-framework-api}/aot/generate/GenerationContext.html[`GenerationContext`]:
@@ -225,7 +225,7 @@ When a `datasource` instance is required, a `BeanInstanceSupplier` is called.
This supplier invokes the `dataSource()` method on the `dataSourceConfiguration` bean.
[[aot.running]]
== Running with AOT optimizations
== Running with AOT Optimizations
AOT is a mandatory step to transform a Spring application to a native executable, so it
is automatically enabled when running in this mode. It is possible to use those optimizations
@@ -244,7 +244,7 @@ However, keep in mind that some optimizations are made at build time based on a
This section lists the best practices that make sure your application is ready for AOT.
[[aot.bestpractices.bean-registration]]
== Programmatic bean registration
=== Programmatic Bean Registration
The AOT engine takes care of the `@Configuration` model and any callback that might be
invoked as part of processing your configuration. If you need to register additional
@@ -266,7 +266,7 @@ notion of a classpath. For cases like this, it is crucial that the scanning happ
build time.
[[aot.bestpractices.bean-type]]
=== Expose The Most Precise Bean Type
=== Expose the Most Precise Bean Type
While your application may interact with an interface that a bean implements, it is still very important to declare the most precise type.
The AOT engine performs additional checks on the bean type, such as detecting the presence of `@Autowired` members or lifecycle callback methods.
@@ -326,6 +326,46 @@ However, this is not a best practice and flagging the preferred constructor with
In case you are working on a code base that you cannot modify, you can set the {spring-framework-api}/beans/factory/support/AbstractBeanDefinition.html#PREFERRED_CONSTRUCTORS_ATTRIBUTE[`preferredConstructors` attribute] on the related bean definition to indicate which constructor should be used.
[[aot.bestpractices.complex-data-structures]]
=== Avoid Complex Data Structures for Constructor Parameters and Properties
When crafting a `RootBeanDefinition` programmatically, you are not constrained in terms of types that you can use.
For instance, you may have a custom `record` with several properties that your bean takes as a constructor argument.
While this works fine with the regular runtime, AOT does not know how to generate the code of your custom data structure.
A good rule of thumb is to keep in mind that bean definitions are an abstraction on top of several models.
Rather than using such structures, decomposing to simple types or referring to a bean that is built as such is recommended.
As a last resort, you can implement your own `org.springframework.aot.generate.ValueCodeGenerator$Delegate`.
To use it, register its fully qualified name in `META-INF/spring/aot.factories` using the `Delegate` as the key.
[[aot.bestpractices.custom-arguments]]
=== Avoid Creating Beans with Custom Arguments
Spring AOT detects what needs to be done to create a bean and translates that in generated code using an instance supplier.
The container also supports creating a bean with {spring-framework-api}++/beans/factory/BeanFactory.html#getBean(java.lang.String,java.lang.Object...)++[custom arguments] that leads to several issues with AOT:
. The custom arguments require dynamic introspection of a matching constructor or factory method.
Those arguments cannot be detected by AOT, so the necessary reflection hints will have to be provided manually.
. By-passing the instance supplier means that all other optimizations after creation are skipped as well.
For instance, autowiring on fields and methods will be skipped as they are handled in the instance supplier.
Rather than having prototype-scoped beans created with custom arguments, we recommend a manual factory pattern where a bean is responsible for the creation of the instance.
[[aot.bestpractices.circular-dependencies]]
=== Avoid Circular Dependencies
Certain use cases can result in circular dependencies between one or more beans. With the
regular runtime, it may be possible to wire those circular dependencies via `@Autowired`
on setter methods or fields. However, an AOT-optimized context will fail to start with
explicit circular dependencies.
In an AOT-optimized application, you should therefore strive to avoid circular
dependencies. If that is not possible, you can use `@Lazy` injection points or
`ObjectProvider` to lazily access or retrieve the necessary collaborating beans. See
xref:core/beans/classpath-scanning.adoc#beans-factorybeans-annotations-lazy-injection-points[this tip]
for further information.
[[aot.bestpractices.factory-bean]]
=== FactoryBean
@@ -1,33 +1,16 @@
[[beans-annotation-config]]
= Annotation-based Container Configuration
.Are annotations better than XML for configuring Spring?
****
The introduction of annotation-based configuration raised the question of whether this
approach is "`better`" than XML. The short answer is "`it depends.`" The long answer is
that each approach has its pros and cons, and, usually, it is up to the developer to
decide which strategy suits them better. Due to the way they are defined, annotations
provide a lot of context in their declaration, leading to shorter and more concise
configuration. However, XML excels at wiring up components without touching their source
code or recompiling them. Some developers prefer having the wiring close to the source
while others argue that annotated classes are no longer POJOs and, furthermore, that the
configuration becomes decentralized and harder to control.
Spring provides comprehensive support for annotation-based configuration, operating on
metadata in the component class itself by using annotations on the relevant class,
method, or field declaration. As mentioned in
xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp-examples-aabpp[Example: The `AutowiredAnnotationBeanPostProcessor`],
Spring uses `BeanPostProcessors` in conjunction with annotations to make the core IOC
container aware of specific annotations.
No matter the choice, Spring can accommodate both styles and even mix them together.
It is worth pointing out that through its xref:core/beans/java.adoc[JavaConfig] option, Spring lets
annotations be used in a non-invasive way, without touching the target components'
source code and that, in terms of tooling, all configuration styles are supported by
{spring-site-tools}[Spring Tools] for Eclipse, Visual Studio Code, and Theia.
****
An alternative to XML setup is provided by annotation-based configuration, which relies
on bytecode metadata for wiring up components instead of XML declarations. Instead of
using XML to describe a bean wiring, the developer moves the configuration into the
component class itself by using annotations on the relevant class, method, or field
declaration. As mentioned in xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp-examples-aabpp[Example: The `AutowiredAnnotationBeanPostProcessor`], using a
`BeanPostProcessor` in conjunction with annotations is a common means of extending the
Spring IoC container. For example, the xref:core/beans/annotation-config/autowired.adoc[`@Autowired`]
annotation provides the same capabilities as described in xref:core/beans/dependencies/factory-autowire.adoc[Autowiring Collaborators] but
For example, the xref:core/beans/annotation-config/autowired.adoc[`@Autowired`]
annotation provides the same capabilities as described in
xref:core/beans/dependencies/factory-autowire.adoc[Autowiring Collaborators] but
with more fine-grained control and wider applicability. In addition, Spring provides
support for JSR-250 annotations, such as `@PostConstruct` and `@PreDestroy`, as well as
support for JSR-330 (Dependency Injection for Java) annotations contained in the
@@ -36,13 +19,16 @@ can be found in the xref:core/beans/standard-annotations.adoc[relevant section].
[NOTE]
====
Annotation injection is performed before XML injection. Thus, the XML configuration
overrides the annotations for properties wired through both approaches.
Annotation injection is performed before external property injection. Thus, external
configuration (e.g. XML-specified bean properties) effectively overrides the annotations
for properties when wired through mixed approaches.
====
As always, you can register the post-processors as individual bean definitions, but they
can also be implicitly registered by including the following tag in an XML-based Spring
configuration (notice the inclusion of the `context` namespace):
Technically, you can register the post-processors as individual bean definitions, but they
are implicitly registered in an `AnnotationConfigApplicationContext` already.
In an XML-based Spring setup, you may include the following configuration tag to enable
mixing and matching with annotation-based configuration:
[source,xml,indent=0,subs="verbatim,quotes"]
----
@@ -153,17 +153,15 @@ Letting qualifier values select against target bean names, within the type-match
candidates, does not require a `@Qualifier` annotation at the injection point.
If there is no other resolution indicator (such as a qualifier or a primary marker),
for a non-unique dependency situation, Spring matches the injection point name
(that is, the field name or parameter name) against the target bean names and chooses the
same-named candidate, if any.
(that is, the field name or parameter name) against the target bean names and chooses
the same-named candidate, if any (either by bean name or by associated alias).
Since version 6.1, this requires the `-parameters` Java compiler flag to be present.
====
That said, if you intend to express annotation-driven injection by name, do not
primarily use `@Autowired`, even if it is capable of selecting by bean name among
type-matching candidates. Instead, use the JSR-250 `@Resource` annotation, which is
semantically defined to identify a specific target component by its unique name, with
the declared type being irrelevant for the matching process. `@Autowired` has rather
As an alternative for injection by name, consider the JSR-250 `@Resource` annotation
which is semantically defined to identify a specific target component by its unique name,
with the declared type being irrelevant for the matching process. `@Autowired` has rather
different semantics: After selecting candidate beans by type, the specified `String`
qualifier value is considered within those type-selected candidates only (for example,
matching an `account` qualifier against beans marked with the same qualifier label).
@@ -186,6 +186,15 @@ implementation type, consider declaring the most specific return type on your fa
method (at least as specific as required by the injection points referring to your bean).
====
[NOTE]
====
As of 4.3, `@Autowired` also considers self references for injection (that is, references
back to the bean that is currently injected). Note that self injection is a fallback.
In practice, you should use self references as a last resort only (for example, for
calling other methods on the same instance through the bean's transactional proxy).
Consider factoring out the affected methods to a separate delegate bean in such a scenario.
====
You can also instruct Spring to provide all beans of a particular type from the
`ApplicationContext` by adding the `@Autowired` annotation to a field or method that
expects an array of that type, as the following example shows:
@@ -268,6 +277,12 @@ use the same bean class). `@Order` values may influence priorities at injection
but be aware that they do not influence singleton startup order, which is an
orthogonal concern determined by dependency relationships and `@DependsOn` declarations.
Note that `@Order` annotations on configuration classes just influence the evaluation
order within the overall set of configuration classes on startup. Such configuration-level
order values do not affect the contained `@Bean` methods at all. For bean-level ordering,
each `@Bean` method needs to have its own `@Order` annotation which applies within a
set of multiple matches for the specific bean type (as returned by the factory method).
Note that the standard `jakarta.annotation.Priority` annotation is not available at the
`@Bean` level, since it cannot be declared on methods. Its semantics can be modeled
through `@Order` values in combination with `@Primary` on a single bean for each type.
@@ -2,36 +2,28 @@
= Container Overview
The `org.springframework.context.ApplicationContext` interface represents the Spring IoC
container and is responsible for instantiating, configuring, and assembling the
beans. The container gets its instructions on what objects to
instantiate, configure, and assemble by reading configuration metadata. The
configuration metadata is represented in XML, Java annotations, or Java code. It lets
you express the objects that compose your application and the rich interdependencies
between those objects.
container and is responsible for instantiating, configuring, and assembling the beans.
The container gets its instructions on the components to instantiate, configure, and
assemble by reading configuration metadata. The configuration metadata can be represented
as annotated component classes, configuration classes with factory methods, or external
XML files or Groovy scripts. With either format, you may compose your application and the
rich interdependencies between those components.
Several implementations of the `ApplicationContext` interface are supplied
with Spring. In stand-alone applications, it is common to create an
instance of
{spring-framework-api}/context/support/ClassPathXmlApplicationContext.html[`ClassPathXmlApplicationContext`]
or {spring-framework-api}/context/support/FileSystemXmlApplicationContext.html[`FileSystemXmlApplicationContext`].
While XML has been the traditional format for defining configuration metadata, you can
instruct the container to use Java annotations or code as the metadata format by
providing a small amount of XML configuration to declaratively enable support for these
additional metadata formats.
Several implementations of the `ApplicationContext` interface are part of core Spring.
In stand-alone applications, it is common to create an instance of
{spring-framework-api}/context/annotation/AnnotationConfigApplicationContext.html[`AnnotationConfigApplicationContext`]
or {spring-framework-api}/context/support/ClassPathXmlApplicationContext.html[`ClassPathXmlApplicationContext`].
In most application scenarios, explicit user code is not required to instantiate one or
more instances of a Spring IoC container. For example, in a web application scenario, a
simple eight (or so) lines of boilerplate web descriptor XML in the `web.xml` file
of the application typically suffices (see
more instances of a Spring IoC container. For example, in a plain web application scenario,
a simple boilerplate web descriptor XML in the `web.xml` file of the application suffices (see
xref:core/beans/context-introduction.adoc#context-create[Convenient ApplicationContext Instantiation for Web Applications]).
If you use the {spring-site-tools}[Spring Tools for Eclipse] (an Eclipse-powered
development environment), you can easily create this boilerplate configuration with a
few mouse clicks or keystrokes.
In a Spring Boot scenario, the application context is implicitly bootstrapped for you
based on common setup conventions.
The following diagram shows a high-level view of how Spring works. Your application classes
are combined with configuration metadata so that, after the `ApplicationContext` is
created and initialized, you have a fully configured and executable system or
application.
created and initialized, you have a fully configured and executable system or application.
.The Spring IoC container
image::container-magic.png[]
@@ -43,33 +35,25 @@ image::container-magic.png[]
As the preceding diagram shows, the Spring IoC container consumes a form of
configuration metadata. This configuration metadata represents how you, as an
application developer, tell the Spring container to instantiate, configure, and assemble
the objects in your application.
application developer, tell the Spring container to instantiate, configure,
and assemble the components in your application.
Configuration metadata is traditionally supplied in a simple and intuitive XML format,
which is what most of this chapter uses to convey key concepts and features of the
Spring IoC container.
NOTE: XML-based metadata is not the only allowed form of configuration metadata.
The Spring IoC container itself is totally decoupled from the format in which this
configuration metadata is actually written. These days, many developers choose
xref:core/beans/java.adoc[Java-based configuration] for their Spring applications.
For information about using other forms of metadata with the Spring container, see:
xref:core/beans/java.adoc[Java-based configuration] for their Spring applications:
* xref:core/beans/annotation-config.adoc[Annotation-based configuration]: define beans using
annotation-based configuration metadata.
annotation-based configuration metadata on your application's component classes.
* xref:core/beans/java.adoc[Java-based configuration]: define beans external to your application
classes by using Java rather than XML files. To use these features, see the
classes by using Java-based configuration classes. To use these features, see the
{spring-framework-api}/context/annotation/Configuration.html[`@Configuration`],
{spring-framework-api}/context/annotation/Bean.html[`@Bean`],
{spring-framework-api}/context/annotation/Import.html[`@Import`],
and {spring-framework-api}/context/annotation/DependsOn.html[`@DependsOn`] annotations.
Spring configuration consists of at least one and typically more than one bean
definition that the container must manage. XML-based configuration metadata configures these
beans as `<bean/>` elements inside a top-level `<beans/>` element. Java
configuration typically uses `@Bean`-annotated methods within a `@Configuration` class.
Spring configuration consists of at least one and typically more than one bean definition
that the container must manage. Java configuration typically uses `@Bean`-annotated
methods within a `@Configuration` class, each corresponding to one bean definition.
These bean definitions correspond to the actual objects that make up your application.
Typically, you define service layer objects, persistence layer objects such as
@@ -79,7 +63,14 @@ Typically, one does not configure fine-grained domain objects in the container,
it is usually the responsibility of repositories and business logic to create and load
domain objects.
The following example shows the basic structure of XML-based configuration metadata:
[[beans-factory-xml]]
=== XML as an External Configuration DSL
XML-based configuration metadata configures these beans as `<bean/>` elements inside
a top-level `<beans/>` element. The following example shows the basic structure of
XML-based configuration metadata:
[source,xml,indent=0,subs="verbatim,quotes"]
----
@@ -110,14 +101,9 @@ The value of the `id` attribute can be used to refer to collaborating objects. T
for referring to collaborating objects is not shown in this example. See
xref:core/beans/dependencies.adoc[Dependencies] for more information.
[[beans-factory-instantiation]]
== Instantiating a Container
The location path or paths
supplied to an `ApplicationContext` constructor are resource strings that let
the container load configuration metadata from a variety of external resources, such
For instantiating a container, the location path or paths to the XML resource files
need to be supplied to a `ClassPathXmlApplicationContext` constructor that let the
container load configuration metadata from a variety of external resources, such
as the local file system, the Java `CLASSPATH`, and so on.
[tabs]
@@ -209,9 +195,9 @@ xref:core/beans/dependencies.adoc[Dependencies].
It can be useful to have bean definitions span multiple XML files. Often, each individual
XML configuration file represents a logical layer or module in your architecture.
You can use the application context constructor to load bean definitions from all these
You can use the `ClassPathXmlApplicationContext` constructor to load bean definitions from
XML fragments. This constructor takes multiple `Resource` locations, as was shown in the
xref:core/beans/basics.adoc#beans-factory-instantiation[previous section]. Alternatively,
xref:core/beans/basics.adoc#beans-factory-xml[previous section]. Alternatively,
use one or more occurrences of the `<import/>` element to load bean definitions from
another file or files. The following example shows how to do so:
@@ -259,7 +245,7 @@ configuration features beyond plain bean definitions are available in a selectio
of XML namespaces provided by Spring -- for example, the `context` and `util` namespaces.
[[groovy-bean-definition-dsl]]
[[beans-factory-groovy]]
=== The Groovy Bean Definition DSL
As a further example for externalized configuration metadata, bean definitions can also
@@ -420,4 +406,3 @@ a dependency on a specific bean through metadata (such as an autowiring annotati
@@ -317,8 +317,8 @@ exposed based on security policies in some environments -- for example, standalo
JDK 1.7.0_45 and higher (which requires 'Trusted-Library' setup in your manifests -- see
{stackoverflow-questions}/19394570/java-jre-7u45-breaks-classloader-getresources).
On JDK 9's module path (Jigsaw), Spring's classpath scanning generally works as expected.
However, make sure that your component classes are exported in your `module-info`
On the module path (Java Module System), Spring's classpath scanning generally works as
expected. However, make sure that your component classes are exported in your `module-info`
descriptors. If you expect Spring to invoke non-public members of your classes, make
sure that they are 'opened' (that is, that they use an `opens` declaration instead of an
`exports` declaration in your `module-info` descriptor).
@@ -480,11 +480,15 @@ factory method and other bean definition properties, such as a qualifier value t
the `@Qualifier` annotation. Other method-level annotations that can be specified are
`@Scope`, `@Lazy`, and custom qualifier annotations.
TIP: In addition to its role for component initialization, you can also place the `@Lazy`
[[beans-factorybeans-annotations-lazy-injection-points]]
[TIP]
====
In addition to its role for component initialization, you can also place the `@Lazy`
annotation on injection points marked with `@Autowired` or `@Inject`. In this context,
it leads to the injection of a lazy-resolution proxy. However, such a proxy approach
is rather limited. For sophisticated lazy interactions, in particular in combination
with optional dependencies, we recommend `ObjectProvider<MyTargetBean>` instead.
====
Autowired fields and methods are supported, as previously discussed, with additional
support for autowiring of `@Bean` methods. The following example shows how to do so:
@@ -751,7 +755,7 @@ and bean definition show.
TIP: If you run into naming conflicts due to multiple autodetected components having the
same non-qualified class name (i.e., classes with identical names but residing in
different packages), you may need to configure a `BeanNameGenerator` that defaults to the
fully qualified class name for the generated bean name. As of Spring Framework 5.2.3, the
fully qualified class name for the generated bean name. The
`FullyQualifiedAnnotationBeanNameGenerator` located in package
`org.springframework.context.annotation` can be used for such purposes.
@@ -920,7 +924,8 @@ Kotlin::
[[beans-scanning-qualifiers]]
== Providing Qualifier Metadata with Annotations
The `@Qualifier` annotation is discussed in xref:core/beans/annotation-config/autowired-qualifiers.adoc[Fine-tuning Annotation-based Autowiring with Qualifiers].
The `@Qualifier` annotation is discussed in
xref:core/beans/annotation-config/autowired-qualifiers.adoc[Fine-tuning Annotation-based Autowiring with Qualifiers].
The examples in that section demonstrate the use of the `@Qualifier` annotation and
custom qualifier annotations to provide fine-grained control when you resolve autowire
candidates. Because those examples were based on XML bean definitions, the qualifier
@@ -1,7 +1,7 @@
[[context-introduction]]
= Additional Capabilities of the `ApplicationContext`
As discussed in the xref:web/webmvc-view/mvc-xslt.adoc#mvc-view-xslt-beandefs[chapter introduction], the `org.springframework.beans.factory`
As discussed in the xref:core/beans/introduction.adoc[chapter introduction], the `org.springframework.beans.factory`
package provides basic functionality for managing and manipulating beans, including in a
programmatic way. The `org.springframework.context` package adds the
{spring-framework-api}/context/ApplicationContext.html[`ApplicationContext`]
@@ -644,7 +644,7 @@ Each `SpEL` expression evaluates against a dedicated context. The following tabl
items made available to the context so that you can use them for conditional event processing:
[[context-functionality-events-annotation-tbl]]
.Event SpEL available metadata
.Event metadata available in SpEL expressions
|===
| Name| Location| Description| Example
@@ -660,8 +660,8 @@ items made available to the context so that you can use them for conditional eve
| __Argument name__
| evaluation context
| The name of any of the method arguments. If, for some reason, the names are not available
(for example, because there is no debug information in the compiled byte code), individual
| The name of a particular method argument. If the names are not available
(for example, because the code was compiled without the `-parameters` flag), individual
arguments are also available using the `#a<#arg>` syntax where `<#arg>` stands for the
argument index (starting from 0).
| `#blEvent` or `#a0` (you can also use `#p0` or `#p<#arg>` parameter notation as an alias)
@@ -883,11 +883,12 @@ e.g. for processing all events asynchronously and/or for handling listener excep
== Convenient Access to Low-level Resources
For optimal usage and understanding of application contexts, you should familiarize
yourself with Spring's `Resource` abstraction, as described in xref:web/webflux-webclient/client-builder.adoc#webflux-client-builder-reactor-resources[Resources].
yourself with Spring's `Resource` abstraction, as described in
xref:core/resources.adoc[Resources].
An application context is a `ResourceLoader`, which can be used to load `Resource` objects.
A `Resource` is essentially a more feature rich version of the JDK `java.net.URL` class.
In fact, the implementations of the `Resource` wrap an instance of `java.net.URL`, where
In fact, implementations of `Resource` wrap an instance of `java.net.URL`, where
appropriate. A `Resource` can obtain low-level resources from almost any location in a
transparent fashion, including from the classpath, a filesystem location, anywhere
describable with a standard URL, and some other variations. If the resource location
@@ -75,6 +75,31 @@ lead to concurrent access exceptions, inconsistent state in the bean container,
[[beans-definition-overriding]]
== Overriding Beans
Bean overriding is happening when a bean is registered using an identifier that is
already allocated. While bean overriding is possible, it makes the configuration harder
to read and this feature will be deprecated in a future release.
To disable bean overriding altogether, you can set the `allowBeanDefinitionOverriding`
flag to `false` on the `ApplicationContext` before it is refreshed. In such setup, an
exception is thrown if bean overriding is used.
By default, the container logs every bean overriding at `INFO` level so that you can
adapt your configuration accordingly. While not recommended, you can silence those logs
by setting the `allowBeanDefinitionOverriding` flag to `true`.
.Java-configuration
****
If you use Java Configuration, a corresponding `@Bean` method always silently overrides
a scanned bean class with the same component name as long as the return type of the
`@Bean` method matches that bean class. This simply means that the container will call
the `@Bean` factory method in favor of any pre-declared constructor on the bean class.
****
[[beans-beanname]]
== Naming Beans
@@ -234,6 +259,10 @@ For details about the mechanism for supplying arguments to the constructor (if r
and setting object instance properties after the object is constructed, see
xref:core/beans/dependencies/factory-collaborators.adoc[Injecting Dependencies].
NOTE: In the case of constructor arguments, the container can select a corresponding
constructor among several overloaded constructors. That said, to avoid ambiguities,
it is recommended to keep your constructor signatures as straightforward as possible.
[[beans-factory-class-static-factory-method]]
=== Instantiation with a Static Factory Method
@@ -294,6 +323,24 @@ For details about the mechanism for supplying (optional) arguments to the factor
and setting object instance properties after the object is returned from the factory,
see xref:core/beans/dependencies/factory-properties-detailed.adoc[Dependencies and Configuration in Detail].
NOTE: In the case of factory method arguments, the container can select a corresponding
method among several overloaded methods of the same name. That said, to avoid ambiguities,
it is recommended to keep your factory method signatures as straightforward as possible.
[TIP]
====
A typical problematic case with factory method overloading is Mockito with its many
overloads of the `mock` method. Choose the most specific variant of `mock` possible:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="clientService" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg type="java.lang.Class" value="examples.ClientService"/>
<constructor-arg type="java.lang.String" value="clientService"/>
</bean>
----
====
[[beans-factory-class-instance-factory-method]]
=== Instantiation by Using an Instance Factory Method
@@ -416,8 +463,8 @@ Kotlin::
======
This approach shows that the factory bean itself can be managed and configured through
dependency injection (DI). See xref:core/beans/dependencies/factory-properties-detailed.adoc[Dependencies and Configuration in Detail]
.
dependency injection (DI).
See xref:core/beans/dependencies/factory-properties-detailed.adoc[Dependencies and Configuration in Detail].
NOTE: In Spring documentation, "factory bean" refers to a bean that is configured in the
Spring container and that creates objects through an
@@ -444,5 +491,3 @@ cases into account and returns the type of object that a `BeanFactory.getBean` c
going to return for the same bean name.
@@ -60,6 +60,7 @@ instance's values consist of all bean instances that match the expected type, an
`Map` instance's keys contain the corresponding bean names.
[[beans-autowired-exceptions]]
== Limitations and Disadvantages of Autowiring
@@ -101,10 +102,10 @@ In the latter scenario, you have several options:
== Excluding a Bean from Autowiring
On a per-bean basis, you can exclude a bean from autowiring. In Spring's XML format, set
the `autowire-candidate` attribute of the `<bean/>` element to `false`. The container
makes that specific bean definition unavailable to the autowiring infrastructure
(including annotation style configurations such as xref:core/beans/annotation-config/autowired.adoc[`@Autowired`]
).
the `autowire-candidate` attribute of the `<bean/>` element to `false`; with the `@Bean`
annotation, the attribute is named `autowireCandidate`. The container makes that specific
bean definition unavailable to the autowiring infrastructure, including annotation-based
injection points such as xref:core/beans/annotation-config/autowired.adoc[`@Autowired`].
NOTE: The `autowire-candidate` attribute is designed to only affect type-based autowiring.
It does not affect explicit references by name, which get resolved even if the
@@ -119,8 +120,8 @@ provide multiple patterns, define them in a comma-separated list. An explicit va
`true` or `false` for a bean definition's `autowire-candidate` attribute always takes
precedence. For such beans, the pattern matching rules do not apply.
These techniques are useful for beans that you never want to be injected into other
beans by autowiring. It does not mean that an excluded bean cannot itself be configured by
These techniques are useful for beans that you never want to be injected into other beans
by autowiring. It does not mean that an excluded bean cannot itself be configured by
using autowiring. Rather, the bean itself is not a candidate for autowiring other beans.
@@ -159,10 +159,12 @@ Kotlin::
----
======
.[[beans-factory-ctor-arguments-type]]Constructor argument type matching
--
[discrete]
[[beans-factory-ctor-arguments-type]]
==== Constructor argument type matching
In the preceding scenario, the container can use type matching with simple types if
you explicitly specify the type of the constructor argument by using the `type` attribute,
you explicitly specify the type of the constructor argument via the `type` attribute,
as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
@@ -172,10 +174,11 @@ as the following example shows:
<constructor-arg type="java.lang.String" value="42"/>
</bean>
----
--
.[[beans-factory-ctor-arguments-index]]Constructor argument index
--
[discrete]
[[beans-factory-ctor-arguments-index]]
==== Constructor argument index
You can use the `index` attribute to specify explicitly the index of constructor arguments,
as the following example shows:
@@ -191,10 +194,11 @@ In addition to resolving the ambiguity of multiple simple values, specifying an
resolves ambiguity where a constructor has two arguments of the same type.
NOTE: The index is 0-based.
--
.[[beans-factory-ctor-arguments-name]]Constructor argument name
--
[discrete]
[[beans-factory-ctor-arguments-name]]
==== Constructor argument name
You can also use the constructor parameter name for value disambiguation, as the following
example shows:
@@ -207,8 +211,8 @@ example shows:
----
Keep in mind that, to make this work out of the box, your code must be compiled with the
debug flag enabled so that Spring can look up the parameter name from the constructor.
If you cannot or do not want to compile your code with the debug flag, you can use the
`-parameters` flag enabled so that Spring can look up the parameter name from the constructor.
If you cannot or do not want to compile your code with the `-parameters` flag, you can use the
https://download.oracle.com/javase/8/docs/api/java/beans/ConstructorProperties.html[@ConstructorProperties]
JDK annotation to explicitly name your constructor arguments. The sample class would
then have to look as follows:
@@ -244,7 +248,6 @@ Kotlin::
constructor(val years: Int, val ultimateAnswer: String)
----
======
--
[[beans-setter-injection]]
@@ -2,13 +2,15 @@
= Using `depends-on`
If a bean is a dependency of another bean, that usually means that one bean is set as a
property of another. Typically you accomplish this with the <<beans-ref-element, `<ref/>`
element>> in XML-based configuration metadata. However, sometimes dependencies between
beans are less direct. An example is when a static initializer in a class needs to be
triggered, such as for database driver registration. The `depends-on` attribute can
explicitly force one or more beans to be initialized before the bean using this element
is initialized. The following example uses the `depends-on` attribute to express a
dependency on a single bean:
property of another. Typically you accomplish this with the
xref:core/beans/dependencies/factory-properties-detailed.adoc#beans-ref-element[`<ref/>` element>]
in XML-based metadata or through xref:core/beans/dependencies/factory-autowire.adoc[autowiring].
However, sometimes dependencies between beans are less direct. An example is when a static
initializer in a class needs to be triggered, such as for database driver registration.
The `depends-on` attribute or `@DependsOn` annotation can explicitly force one or more beans
to be initialized before the bean using this element is initialized. The following example
uses the `depends-on` attribute to express a dependency on a single bean:
[source,xml,indent=0,subs="verbatim,quotes"]
----
@@ -31,10 +33,10 @@ delimiters):
----
NOTE: The `depends-on` attribute can specify both an initialization-time dependency and,
in the case of xref:core/beans/factory-scopes.adoc#beans-factory-scopes-singleton[singleton] beans only, a corresponding
destruction-time dependency. Dependent beans that define a `depends-on` relationship
with a given bean are destroyed first, prior to the given bean itself being destroyed.
Thus, `depends-on` can also control shutdown order.
in the case of xref:core/beans/factory-scopes.adoc#beans-factory-scopes-singleton[singleton]
beans only, a corresponding destruction-time dependency. Dependent beans that define a
`depends-on` relationship with a given bean are destroyed first, prior to the given bean
itself being destroyed. Thus, `depends-on` can also control shutdown order.
@@ -120,8 +120,6 @@ dynamically generate a subclass that overrides the method.
subclasses cannot be `final`, and the method to be overridden cannot be `final`, either.
* Unit-testing a class that has an `abstract` method requires you to subclass the class
yourself and to supply a stub implementation of the `abstract` method.
* Concrete methods are also necessary for component scanning, which requires concrete
classes to pick up.
* A further key limitation is that lookup methods do not work with factory methods and
in particular not with `@Bean` methods in configuration classes, since, in that case,
the container is not in charge of creating the instance and therefore cannot create
@@ -201,7 +199,7 @@ the original class. Consider the following example:
<!-- inject dependencies here as required -->
</bean>
<!-- commandProcessor uses statefulCommandHelper -->
<!-- commandManager uses myCommand prototype bean -->
<bean id="commandManager" class="fiona.apple.CommandManager">
<lookup-method name="createCommand" bean="myCommand"/>
</bean>
@@ -293,11 +291,6 @@ Kotlin::
----
======
Note that you should typically declare such annotated lookup methods with a concrete
stub implementation, in order for them to be compatible with Spring's component
scanning rules where abstract classes get ignored by default. This limitation does not
apply to explicitly registered or explicitly imported bean classes.
[TIP]
====
Another way of accessing differently scoped target beans is an `ObjectFactory`/
@@ -102,8 +102,8 @@ following snippet:
----
<bean id="theTargetBean" class="..." />
<bean id="client" class="...">
<property name="targetName" value="theTargetBean"/>
<bean id="theClientBean" class="...">
<property name="targetName" ref="theTargetBean"/>
</bean>
----
@@ -582,7 +582,7 @@ it needs to be declared in the XML file even though it is not defined in an XSD
(it exists inside the Spring core).
For the rare cases where the constructor argument names are not available (usually if
the bytecode was compiled without debugging information), you can use fallback to the
the bytecode was compiled without the `-parameters` flag), you can fall back to the
argument indexes, as follows:
[source,xml,indent=0,subs="verbatim,quotes"]
@@ -439,7 +439,7 @@ dataSource.url=jdbc:mysql:mydb
----
This example file can be used with a container definition that contains a bean called
`dataSource` that has `driver` and `url` properties.
`dataSource` that has `driverClassName` and `url` properties.
Compound property names are also supported, as long as every component of the path
except the final property being overridden is already non-null (presumably initialized
@@ -55,33 +55,34 @@ The preceding `AppConfig` class is equivalent to the following Spring `<beans/>`
</beans>
----
.Full @Configuration vs "`lite`" @Bean mode?
.@Configuration classes with or without local calls between @Bean methods?
****
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 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.
In such scenarios, `@Bean` methods are a general-purpose factory method mechanism.
Unlike full `@Configuration`, lite `@Bean` methods cannot declare inter-bean dependencies.
Instead, they operate on their containing component's internal state and, optionally, on
arguments that they may declare. Such a `@Bean` method should therefore not invoke other
`@Bean` methods. Each such method is literally only a factory method for a particular
bean reference, without any special runtime semantics. The positive side-effect here is
that no CGLIB subclassing has to be applied at runtime, so there are no limitations in
terms of class design (that is, the containing class may be `final` and so forth).
In common scenarios, `@Bean` methods are to be declared within `@Configuration` classes,
ensuring that "`full`" mode is always used and that cross-method references therefore
get redirected to the container's lifecycle management. This prevents the same
`@Bean` method from accidentally being invoked through a regular Java call, which helps
to reduce subtle bugs that can be hard to track down when operating in "`lite`" mode.
ensuring that full configuration class processing applies and that cross-method
references therefore get redirected to the container's lifecycle management.
This prevents the same `@Bean` method from accidentally being invoked through a regular
Java method call, which helps to reduce subtle bugs that can be hard to track down.
When `@Bean` methods are declared within classes that are not annotated with
`@Configuration` - or when `@Configuration(proxyBeanMethods=false)` is declared -,
they are referred to as being processed in a "lite" mode. In such scenarios,
`@Bean` methods are effectively a general-purpose factory method mechanism without
special runtime processing (that is, without generating a CGLIB subclass for it).
A custom Java call to such a method will not get intercepted by the container and
therefore behaves just like a regular method call, creating a new instance every time
rather than reusing an existing singleton (or scoped) instance for the given bean.
As a consequence, `@Bean` methods on classes without runtime proxying are not meant to
declare inter-bean dependencies at all. Instead, they are expected to operate on their
containing component's fields and, optionally, on arguments that a factory method may
declare in order to receive autowired collaborators. Such a `@Bean` method therefore
never needs to invoke other `@Bean` methods; every such call can be expressed through
a factory method argument instead. The positive side-effect here is that no CGLIB
subclassing has to be applied at runtime, reducing the overhead and the footprint.
****
The `@Bean` and `@Configuration` annotations are discussed in depth in the following sections.
First, however, we cover the various ways of creating a spring container by using
First, however, we cover the various ways of creating a Spring container by using
Java-based configuration.
@@ -116,7 +116,7 @@ the configuration model, in that references to other beans must be valid Java sy
Fortunately, solving this problem is simple. As
xref:core/beans/java/bean-annotation.adoc#beans-java-dependencies[we already discussed],
a `@Bean` method can have an arbitrary number of parameters that describe the bean
dependencies. Consider the following more real-world scenario with several `@Configuration`
dependencies. Consider the following more realistic scenario with several `@Configuration`
classes, each depending on beans declared in the others:
[tabs]
@@ -331,8 +331,10 @@ TIP: Constructor injection in `@Configuration` classes is only supported as of S
Framework 4.3. Note also that there is no need to specify `@Autowired` if the target
bean defines only one constructor.
.[[beans-java-injecting-imported-beans-fq]]Fully-qualifying imported beans for ease of navigation
--
[discrete]
[[beans-java-injecting-imported-beans-fq]]
==== Fully-qualifying imported beans for ease of navigation
In the preceding scenario, using `@Autowired` works well and provides the desired
modularity, but determining exactly where the autowired bean definitions are declared is
still somewhat ambiguous. For example, as a developer looking at `ServiceConfig`, how do
@@ -501,7 +503,6 @@ Now `ServiceConfig` is loosely coupled with respect to the concrete
get a type hierarchy of `RepositoryConfig` implementations. In this
way, navigating `@Configuration` classes and their dependencies becomes no different
than the usual process of navigating interface-based code.
--
TIP: If you want to influence the startup creation order of certain beans, consider
declaring some of them as `@Lazy` (for creation on first access instead of on startup)
@@ -540,7 +541,7 @@ Java::
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
for (Object value : attrs.get("value")) {
if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
if (context.getEnvironment().matchesProfiles((String[]) value)) {
return true;
}
}
@@ -559,7 +560,7 @@ Kotlin::
val attrs = metadata.getAllAnnotationAttributes(Profile::class.java.name)
if (attrs != null) {
for (value in attrs["value"]!!) {
if (context.environment.acceptsProfiles(Profiles.of(*value as Array<String>))) {
if (context.environment.matchesProfiles(*value as Array<String>)) {
return true
}
}
@@ -594,16 +595,18 @@ that uses Spring XML, it is easier to create `@Configuration` classes on an
as-needed basis and include them from the existing XML files. Later in this section, we cover the
options for using `@Configuration` classes in this kind of "`XML-centric`" situation.
.[[beans-java-combining-xml-centric-declare-as-bean]]Declaring `@Configuration` classes as plain Spring `<bean/>` elements
--
Remember that `@Configuration` classes are ultimately bean definitions in the
container. In this series examples, we create a `@Configuration` class named `AppConfig` and
[discrete]
[[beans-java-combining-xml-centric-declare-as-bean]]
==== Declaring `@Configuration` classes as plain Spring `<bean/>` elements
Remember that `@Configuration` classes are ultimately bean definitions in the container.
In this series of examples, we create a `@Configuration` class named `AppConfig` and
include it within `system-test-config.xml` as a `<bean/>` definition. Because
`<context:annotation-config/>` is switched on, the container recognizes the
`@Configuration` annotation and processes the `@Bean` methods declared in `AppConfig`
properly.
The following example shows an ordinary configuration class in Java:
The following example shows the `AppConfig` configuration class in Java and Kotlin:
[tabs]
======
@@ -624,7 +627,7 @@ Java::
@Bean
public TransferService transferService() {
return new TransferService(accountRepository());
return new TransferServiceImpl(accountRepository());
}
}
----
@@ -657,6 +660,7 @@ The following example shows part of a sample `system-test-config.xml` file:
<beans>
<!-- enable processing of annotations such as @Autowired and @Configuration -->
<context:annotation-config/>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
<bean class="com.acme.AppConfig"/>
@@ -703,20 +707,20 @@ Kotlin::
----
======
NOTE: In `system-test-config.xml` file, the `AppConfig` `<bean/>` does not declare an `id`
element. While it would be acceptable to do so, it is unnecessary, given that no other bean
NOTE: In the `system-test-config.xml` file, the `AppConfig` `<bean/>` does not declare an `id`
attribute. While it would be acceptable to do so, it is unnecessary, given that no other bean
ever refers to it, and it is unlikely to be explicitly fetched from the container by name.
Similarly, the `DataSource` bean is only ever autowired by type, so an explicit bean `id`
is not strictly required.
--
.[[beans-java-combining-xml-centric-component-scan]] Using <context:component-scan/> to pick up `@Configuration` classes
--
[discrete]
[[beans-java-combining-xml-centric-component-scan]]
==== Using <context:component-scan/> to pick up `@Configuration` classes
Because `@Configuration` is meta-annotated with `@Component`, `@Configuration`-annotated
classes are automatically candidates for component scanning. Using the same scenario as
described in the previous example, we can redefine `system-test-config.xml` to take advantage of component-scanning.
Note that, in this case, we need not explicitly declare
described in the previous example, we can redefine `system-test-config.xml` to take
advantage of component-scanning. Note that, in this case, we need not explicitly declare
`<context:annotation-config/>`, because `<context:component-scan/>` enables the same
functionality.
@@ -727,6 +731,7 @@ The following example shows the modified `system-test-config.xml` file:
<beans>
<!-- picks up and registers AppConfig as a bean definition -->
<context:component-scan base-package="com.acme"/>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
@@ -736,19 +741,17 @@ The following example shows the modified `system-test-config.xml` file:
</bean>
</beans>
----
--
[[beans-java-combining-java-centric]]
=== `@Configuration` Class-centric Use of XML with `@ImportResource`
In applications where `@Configuration` classes are the primary mechanism for configuring
the container, it is still likely necessary to use at least some XML. In these
scenarios, you can use `@ImportResource` and define only as much XML as you need. Doing
so achieves a "`Java-centric`" approach to configuring the container and keeps XML to a
bare minimum. The following example (which includes a configuration class, an XML file
that defines a bean, a properties file, and the `main` class) shows how to use
the `@ImportResource` annotation to achieve "`Java-centric`" configuration that uses XML
as needed:
the container, it may still be necessary to use at least some XML. In such scenarios, you
can use `@ImportResource` and define only as much XML as you need. Doing so achieves a
"`Java-centric`" approach to configuring the container and keeps XML to a bare minimum.
The following example (which includes a configuration class, an XML file that defines a
bean, a properties file, and the `main()` method) shows how to use the `@ImportResource`
annotation to achieve "`Java-centric`" configuration that uses XML as needed:
[tabs]
======
@@ -773,6 +776,17 @@ Java::
public DataSource dataSource() {
return new DriverManagerDataSource(url, username, password);
}
@Bean
public AccountRepository accountRepository(DataSource dataSource) {
return new JdbcAccountRepository(dataSource);
}
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
----
@@ -797,21 +811,32 @@ Kotlin::
fun dataSource(): DataSource {
return DriverManagerDataSource(url, username, password)
}
@Bean
fun accountRepository(dataSource: DataSource): AccountRepository {
return JdbcAccountRepository(dataSource)
}
@Bean
fun transferService(accountRepository: AccountRepository): TransferService {
return TransferServiceImpl(accountRepository)
}
}
----
======
.properties-config.xml
[source,xml,indent=0,subs="verbatim,quotes"]
----
properties-config.xml
<beans>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
</beans>
----
.jdbc.properties
[literal,subs="verbatim,quotes"]
----
jdbc.properties
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
jdbc.username=sa
jdbc.password=
@@ -844,5 +869,3 @@ Kotlin::
----
======
@@ -222,29 +222,38 @@ Kotlin::
[[expressions-evaluation-context]]
== Understanding `EvaluationContext`
The `EvaluationContext` interface is used when evaluating an expression to resolve
properties, methods, or fields and to help perform type conversion. Spring provides two
The `EvaluationContext` API is used when evaluating an expression to resolve properties,
methods, or fields and to help perform type conversion. Spring provides two
implementations.
* `SimpleEvaluationContext`: Exposes a subset of essential SpEL language features and
configuration options, for categories of expressions that do not require the full extent
of the SpEL language syntax and should be meaningfully restricted. Examples include but
are not limited to data binding expressions and property-based filters.
`SimpleEvaluationContext`::
Exposes a subset of essential SpEL language features and configuration options, for
categories of expressions that do not require the full extent of the SpEL language
syntax and should be meaningfully restricted. Examples include but are not limited to
data binding expressions and property-based filters.
* `StandardEvaluationContext`: Exposes the full set of SpEL language features and
configuration options. You can use it to specify a default root object and to configure
every available evaluation-related strategy.
`StandardEvaluationContext`::
Exposes the full set of SpEL language features and configuration options. You can use
it to specify a default root object and to configure every available evaluation-related
strategy.
`SimpleEvaluationContext` is designed to support only a subset of the SpEL language syntax.
It excludes Java type references, constructors, and bean references. It also requires
you to explicitly choose the level of support for properties and methods in expressions.
By default, the `create()` static factory method enables only read access to properties.
You can also obtain a builder to configure the exact level of support needed, targeting
one or some combination of the following.
`SimpleEvaluationContext` is designed to support only a subset of the SpEL language
syntax. For example, it excludes Java type references, constructors, and bean references.
It also requires you to explicitly choose the level of support for properties and methods
in expressions. When creating a `SimpleEvaluationContext` you need to choose the level of
support that you need for data binding in SpEL expressions:
* Custom `PropertyAccessor` only (no reflection)
* Data binding properties for read-only access
* Data binding properties for read and write
* Data binding for read-only access
* Data binding for read and write access
* A custom `PropertyAccessor` (typically not reflection-based), potentially combined with
a `DataBindingPropertyAccessor`
Conveniently, `SimpleEvaluationContext.forReadOnlyDataBinding()` enables read-only access
to properties via `DataBindingPropertyAccessor`. Similarly,
`SimpleEvaluationContext.forReadWriteDataBinding()` enables read and write access to
properties. Alternatively, configure custom accessors via
`SimpleEvaluationContext.forPropertyAccessors(...)`, potentially disable assignment, and
optionally activate method resolution and/or a type converter through the builder.
[[expressions-type-conversion]]
@@ -314,17 +323,17 @@ Kotlin::
It is possible to configure the SpEL expression parser by using a parser configuration
object (`org.springframework.expression.spel.SpelParserConfiguration`). The configuration
object controls the behavior of some of the expression components. For example, if you
index into an array or collection and the element at the specified index is `null`, SpEL
can automatically create the element. This is useful when using expressions made up of a
chain of property references. If you index into an array or list and specify an index
that is beyond the end of the current size of the array or list, SpEL can automatically
grow the array or list to accommodate that index. In order to add an element at the
index into a collection and the element at the specified index is `null`, SpEL can
automatically create the element. This is useful when using expressions made up of a
chain of property references. Similarly, if you index into a collection and specify an
index that is greater than the current size of the collection, SpEL can automatically
grow the collection to accommodate that index. In order to add an element at the
specified index, SpEL will try to create the element using the element type's default
constructor before setting the specified value. If the element type does not have a
default constructor, `null` will be added to the array or list. If there is no built-in
or custom converter that knows how to set the value, `null` will remain in the array or
list at the specified index. The following example demonstrates how to automatically grow
the list.
default constructor, `null` will be added to the collection. If there is no built-in
converter or custom converter that knows how to set the value, `null` will remain in the
collection at the specified index. The following example demonstrates how to
automatically grow a `List`.
[tabs]
======
@@ -12,27 +12,27 @@ Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
Inventor einstein = p.parseExpression(
"new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')")
Inventor einstein = parser.parseExpression(
"new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')")
.getValue(Inventor.class);
// create new Inventor instance within the add() method of List
p.parseExpression(
"Members.add(new org.spring.samples.spel.inventor.Inventor(
'Albert Einstein', 'German'))").getValue(societyContext);
parser.parseExpression(
"Members.add(new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German'))")
.getValue(societyContext);
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
val einstein = p.parseExpression(
"new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')")
val einstein = parser.parseExpression(
"new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')")
.getValue(Inventor::class.java)
// create new Inventor instance within the add() method of List
p.parseExpression(
"Members.add(new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German'))")
parser.parseExpression(
"Members.add(new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German'))")
.getValue(societyContext)
----
======
@@ -110,8 +110,8 @@ potentially more efficient use cases if the `MethodHandle` target and parameters
been fully bound prior to registration; however, 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.
Consider the `String#formatted(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:
@@ -151,10 +151,10 @@ Kotlin::
----
======
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:
As mentioned 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]
======
@@ -168,9 +168,10 @@ Java::
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))
MethodType.methodType(String.class, Object[].class))
.bindTo(template)
.bindTo(varargs); //here we have to provide arguments in a single array binding
// Here we have to provide the arguments in a single array binding:
.bindTo(varargs);
context.setVariable("message", mh);
// evaluates to "This is a prerecorded message with 3 words: <Oh Hello World!>"
@@ -189,9 +190,10 @@ Kotlin::
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))
MethodType.methodType(String::class.java, Array<Any>::class.java))
.bindTo(template)
.bindTo(varargs) //here we have to provide arguments in a single array binding
// Here we have to provide the arguments in a single array binding:
.bindTo(varargs)
context.setVariable("message", mh)
// evaluates to "This is a prerecorded message with 3 words: <Oh Hello World!>"
@@ -196,7 +196,7 @@ 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
``ConstraintViolation``s to ``FieldError``s, and registers them with the `Errors` object
passed into the `validate` method.
@@ -299,7 +299,7 @@ Java::
public class AppConfig {
@Bean
public MethodValidationPostProcessor validationPostProcessor() {
public static MethodValidationPostProcessor validationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
@@ -341,7 +341,7 @@ xref:web/webflux/ann-rest-exceptions.adoc[Error Responses] sections.
=== Method Validation Exceptions
By default, `jakarta.validation.ConstraintViolationException` is raised with the set of
``ConstraintViolation``s returned by `jakarata.validation.Validator`. As an alternative,
``ConstraintViolation``s returned by `jakarta.validation.Validator`. As an alternative,
you can have `MethodValidationException` raised instead with ``ConstraintViolation``s
adapted to `MessageSourceResolvable` errors. To enable set the following flag:
@@ -357,7 +357,7 @@ Java::
public class AppConfig {
@Bean
public MethodValidationPostProcessor validationPostProcessor() {
public static MethodValidationPostProcessor validationPostProcessor() {
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
processor.setAdaptConstraintViolations(true);
return processor;
@@ -431,7 +431,7 @@ Kotlin::
A `ConstraintViolation` on `Person.name()` is adapted to a `FieldError` with the following:
- Error codes `"Size.student.name"`, `"Size.name"`, `"Size.java.lang.String"`, and `"Size"`
- Error codes `"Size.person.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"
@@ -439,14 +439,14 @@ 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:
`"person.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
Size.person.name=Please, provide a {0} that is between {2} and {1} characters long
person.name=username
----
A `ConstraintViolation` on the `degrees` method parameter is adapted to a
@@ -280,10 +280,11 @@ Kotlin::
A portable format annotation API exists in the `org.springframework.format.annotation`
package. You can use `@NumberFormat` to format `Number` fields such as `Double` and
`Long`, and `@DateTimeFormat` to format `java.util.Date`, `java.util.Calendar`, `Long`
(for millisecond timestamps) as well as JSR-310 `java.time`.
`Long`, and `@DateTimeFormat` to format fields such as `java.util.Date`,
`java.util.Calendar`, and `Long` (for millisecond timestamps) as well as JSR-310
`java.time` types.
The following example uses `@DateTimeFormat` to format a `java.util.Date` as an ISO Date
The following example uses `@DateTimeFormat` to format a `java.util.Date` as an ISO date
(yyyy-MM-dd):
[tabs]
@@ -309,6 +310,28 @@ Kotlin::
----
======
For further details, see the javadoc for
{spring-framework-api}/format/annotation/DateTimeFormat.html[`@DateTimeFormat`] and
{spring-framework-api}/format/annotation/NumberFormat.html[`@NumberFormat`].
[WARNING]
====
Style-based formatting and parsing rely on locale-sensitive patterns which may change
depending on the Java runtime. Specifically, applications that rely on date, time, or
number parsing and formatting may encounter incompatible changes in behavior when running
on JDK 20 or higher.
Using an ISO standardized format or a concrete pattern that you control allows for
reliable system-independent and locale-independent parsing and formatting of date, time,
and number values.
For `@DateTimeFormat`, the use of fallback patterns can also help to address
compatibility issues.
For further details, see the
https://github.com/spring-projects/spring-framework/wiki/Date-and-Time-Formatting-with-JDK-20-and-higher[Date and Time Formatting with JDK 20 and higher]
page in the Spring Framework wiki.
====
[[format-FormatterRegistry-SPI]]
== The `FormatterRegistry` SPI
@@ -198,7 +198,7 @@ methods it offers can be found in the {spring-framework-api}/validation/Errors.h
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()`
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)`).
@@ -211,19 +211,28 @@ the JDBC driver. If the count is not available, the JDBC driver returns a value
====
In such a scenario, with automatic setting of values on an underlying `PreparedStatement`,
the corresponding JDBC type for each value needs to be derived from the given Java type.
While this usually works well, there is a potential for issues (for example, with Map-contained
`null` values). Spring, by default, calls `ParameterMetaData.getParameterType` in such a
case, which can be expensive with your JDBC driver. You should use a recent driver
While this usually works well, there is a potential for issues (for example, with
Map-contained `null` values). Spring, by default, calls `ParameterMetaData.getParameterType`
in such a case, which can be expensive with your JDBC driver. You should use a recent driver
version and consider setting the `spring.jdbc.getParameterType.ignore` property to `true`
(as a JVM system property or via the
xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism) if you encounter
a performance issue (as reported on Oracle 12c, JBoss, and PostgreSQL).
xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism)
if you encounter a specific performance issue for your application.
Alternatively, you might consider specifying the corresponding JDBC types explicitly,
either through a `BatchPreparedStatementSetter` (as shown earlier), through an explicit type
array given to a `List<Object[]>` based call, through `registerSqlType` calls on a
custom `MapSqlParameterSource` instance, or through a `BeanPropertySqlParameterSource`
that derives the SQL type from the Java-declared property type even for a null value.
As of 6.1.2, Spring bypasses the default `getParameterType` resolution on PostgreSQL and
MS SQL Server. This is a common optimization to avoid further roundtrips to the DBMS just
for parameter type resolution which is known to make a very significant difference on
PostgreSQL and MS SQL Server specifically, in particular for batch operations. If you
happen to see a side effect e.g. when setting a byte array to null without specific type
indication, you may explicitly set the `spring.jdbc.getParameterType.ignore=false` flag
as a system property (see above) to restore full `getParameterType` resolution.
Alternatively, you could consider specifying the corresponding JDBC types explicitly,
either through a `BatchPreparedStatementSetter` (as shown earlier), through an explicit
type array given to a `List<Object[]>` based call, through `registerSqlType` calls on a
custom `MapSqlParameterSource` instance, through a `BeanPropertySqlParameterSource`
that derives the SQL type from the Java-declared property type even for a null value, or
through providing individual `SqlParameterValue` instances instead of plain null values.
====
@@ -112,7 +112,7 @@ Java::
this.actorMappingQuery = new ActorMappingQuery(dataSource);
}
public Customer getCustomer(Long id) {
public Actor getActor(Long id) {
return actorMappingQuery.findObject(id);
}
----
@@ -123,11 +123,11 @@ Kotlin::
----
private val actorMappingQuery = ActorMappingQuery(dataSource)
fun getCustomer(id: Long) = actorMappingQuery.findObject(id)
fun getActor(id: Long) = actorMappingQuery.findObject(id)
----
======
The method in the preceding example retrieves the customer with the `id` that is passed in as the
The method in the preceding example retrieves the actor with the `id` that is passed in as the
only parameter. Since we want only one object to be returned, we call the `findObject` convenience
method with the `id` as the parameter. If we had instead a query that returned a
list of objects and took additional parameters, we would use one of the `execute`
@@ -209,141 +209,26 @@ are passed in as a parameter to the stored procedure.
The `SqlReturnType` interface has a single method (named `getTypeValue`) that must be
implemented. This interface is used as part of the declaration of an `SqlOutParameter`.
The following example shows returning the value of an Oracle `STRUCT` object of the user
The following example shows returning the value of a `java.sql.Struct` object of the user
declared type `ITEM_TYPE`:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public class TestItemStoredProcedure extends StoredProcedure {
public TestItemStoredProcedure(DataSource dataSource) {
// ...
declareParameter(new SqlOutParameter("item", OracleTypes.STRUCT, "ITEM_TYPE",
(CallableStatement cs, int colIndx, int sqlType, String typeName) -> {
STRUCT struct = (STRUCT) cs.getObject(colIndx);
Object[] attr = struct.getAttributes();
TestItem item = new TestItem();
item.setId(((Number) attr[0]).longValue());
item.setDescription((String) attr[1]);
item.setExpirationDate((java.util.Date) attr[2]);
return item;
}));
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class TestItemStoredProcedure(dataSource: DataSource) : StoredProcedure() {
init {
// ...
declareParameter(SqlOutParameter("item", OracleTypes.STRUCT, "ITEM_TYPE") { cs, colIndx, sqlType, typeName ->
val struct = cs.getObject(colIndx) as STRUCT
val attr = struct.getAttributes()
TestItem((attr[0] as Long, attr[1] as String, attr[2] as Date)
})
// ...
}
}
----
======
include-code::./TestItemStoredProcedure[]
You can use `SqlTypeValue` to pass the value of a Java object (such as `TestItem`) to a
stored procedure. The `SqlTypeValue` interface has a single method (named
`createTypeValue`) that you must implement. The active connection is passed in, and you
can use it to create database-specific objects, such as `StructDescriptor` instances
or `ArrayDescriptor` instances. The following example creates a `StructDescriptor` instance:
can use it to create database-specific objects, such as `java.sql.Struct` instances
or `java.sql.Array` instances. The following example creates a `java.sql.Struct` instance:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
final TestItem testItem = new TestItem(123L, "A test item",
new SimpleDateFormat("yyyy-M-d").parse("2010-12-31"));
SqlTypeValue value = new AbstractSqlTypeValue() {
protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException {
StructDescriptor itemDescriptor = new StructDescriptor(typeName, conn);
Struct item = new STRUCT(itemDescriptor, conn,
new Object[] {
testItem.getId(),
testItem.getDescription(),
new java.sql.Date(testItem.getExpirationDate().getTime())
});
return item;
}
};
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
val (id, description, expirationDate) = TestItem(123L, "A test item",
SimpleDateFormat("yyyy-M-d").parse("2010-12-31"))
val value = object : AbstractSqlTypeValue() {
override fun createTypeValue(conn: Connection, sqlType: Int, typeName: String?): Any {
val itemDescriptor = StructDescriptor(typeName, conn)
return STRUCT(itemDescriptor, conn,
arrayOf(id, description, java.sql.Date(expirationDate.time)))
}
}
----
======
include-code::./SqlTypeValueFactory[tag=struct,indent=0]
You can now add this `SqlTypeValue` to the `Map` that contains the input parameters for the
`execute` call of the stored procedure.
Another use for the `SqlTypeValue` is passing in an array of values to an Oracle stored
procedure. Oracle has its own internal `ARRAY` class that must be used in this case, and
you can use the `SqlTypeValue` to create an instance of the Oracle `ARRAY` and populate
it with values from the Java `ARRAY`, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
final Long[] ids = new Long[] {1L, 2L};
SqlTypeValue value = new AbstractSqlTypeValue() {
protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException {
ArrayDescriptor arrayDescriptor = new ArrayDescriptor(typeName, conn);
ARRAY idArray = new ARRAY(arrayDescriptor, conn, ids);
return idArray;
}
};
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
class TestItemStoredProcedure(dataSource: DataSource) : StoredProcedure() {
init {
val ids = arrayOf(1L, 2L)
val value = object : AbstractSqlTypeValue() {
override fun createTypeValue(conn: Connection, sqlType: Int, typeName: String?): Any {
val arrayDescriptor = ArrayDescriptor(typeName, conn)
return ARRAY(arrayDescriptor, conn, ids)
}
}
}
}
----
======
procedure. Oracle has an `createOracleArray` method on `OracleConnection` that you can
access by unwrapping it. You can use the `SqlTypeValue` to create an array and populate
it with values from the Java `java.sql.Array`, as the following example shows:
include-code::./SqlTypeValueFactory[tag=oracle-array,indent=0]
@@ -323,12 +323,12 @@ use these alternative input classes.
The `SimpleJdbcCall` class uses metadata in the database to look up names of `in`
and `out` parameters so that you do not have to explicitly declare them. You can
declare parameters if you prefer to do that or if you have parameters (such as `ARRAY`
or `STRUCT`) that do not have an automatic mapping to a Java class. The first example
shows a simple procedure that returns only scalar values in `VARCHAR` and `DATE` format
from a MySQL database. The example procedure reads a specified actor entry and returns
`first_name`, `last_name`, and `birth_date` columns in the form of `out` parameters.
The following listing shows the first example:
declare parameters if you prefer to do that or if you have parameters that do not
have an automatic mapping to a Java class. The first example shows a simple procedure
that returns only scalar values in `VARCHAR` and `DATE` format from a MySQL database.
The example procedure reads a specified actor entry and returns `first_name`,
`last_name`, and `birth_date` columns in the form of `out` parameters. The following
listing shows the first example:
[source,sql,indent=0,subs="verbatim,quotes"]
----
@@ -74,10 +74,11 @@ Kotlin::
----
======
Used at the class level as above, the annotation indicates a default for all methods of
the declaring class (as well as its subclasses). Alternatively, each method can be
annotated individually. See xref:data-access/transaction/declarative/annotations.adoc#transaction-declarative-annotations-method-visibility[method visibility] for
further details on which methods Spring considers transactional. Note that a class-level
Used at the class level as above, the annotation indicates a default for all methods
of the declaring class (as well as its subclasses). Alternatively, each method can be
annotated individually. See
xref:data-access/transaction/declarative/annotations.adoc#transaction-declarative-annotations-method-visibility[method visibility]
for further details on which methods Spring considers transactional. Note that a class-level
annotation does not apply to ancestor classes up the class hierarchy; in such a scenario,
inherited methods need to be locally redeclared in order to participate in a
subclass-level annotation.
@@ -436,9 +437,10 @@ properties of the `@Transactional` annotation:
| Optional array of exception name patterns that must not cause rollback.
|===
TIP: See xref:data-access/transaction/declarative/rolling-back.adoc#transaction-declarative-rollback-rules[Rollback rules] for further details
on rollback rule semantics, patterns, and warnings regarding possible unintentional
matches for pattern-based rollback rules.
TIP: See
xref:data-access/transaction/declarative/rolling-back.adoc#transaction-declarative-rollback-rules[Rollback rules]
for further details on rollback rule semantics, patterns, and warnings
regarding possible unintentional matches for pattern-based rollback rules.
Currently, you cannot have explicit control over the name of a transaction, where 'name'
means the transaction name that appears in a transaction monitor and in logging output.
@@ -23,9 +23,9 @@ As of Spring Framework 5.2, the default configuration also provides support for
Vavr's `Try` method to trigger transaction rollbacks when it returns a 'Failure'.
This allows you to handle functional-style errors using Try and have the transaction
automatically rolled back in case of a failure. For more information on Vavr's Try,
refer to the https://docs.vavr.io/#_try[official Vavr documentation].
refer to the {vavr-docs}/#_try[official Vavr documentation].
Here's an example of how to use Vavr's Try with a transactional method:
[tabs]
======
Java::
@@ -42,6 +42,32 @@ Java::
----
======
As of Spring Framework 6.1, there is also special treatment of `CompletableFuture`
(and general `Future`) return values, triggering a rollback for such a handle if it
was exceptionally completed at the time of being returned from the original method.
This is intended for `@Async` methods where the actual method implementation may
need to comply with a `CompletableFuture` signature (auto-adapted to an actual
asynchronous handle for a call to the proxy by `@Async` processing at runtime),
preferring exposure in the returned handle rather than rethrowing an exception:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Transactional @Async
public CompletableFuture<String> myTransactionalMethod() {
try {
return CompletableFuture.completedFuture(delegate.myDataAccessOperation());
}
catch (DataAccessException ex) {
return CompletableFuture.failedFuture(ex);
}
}
----
======
Checked exceptions that are thrown from a transactional method do not result in a rollback
in the default configuration. You can configure exactly which `Exception` types mark a
transaction for rollback, including checked exceptions by specifying _rollback rules_.
+1 -3
View File
@@ -29,8 +29,6 @@ Brannen, Ramnivas Laddad, Arjen Poutsma, Chris Beams, Tareq Abedrabbo, Andy Clem
Syer, Oliver Gierke, Rossen Stoyanchev, Phillip Webb, Rob Winch, Brian Clozel, Stephane
Nicoll, Sebastien Deleuze, Jay Bryant, Mark Paluch
Copyright © 2002 - 2024 VMware, Inc. All Rights Reserved.
Copies of this document may be made for your own use and for distribution to others,
provided that you do not charge any fee for such copies and further provided that each
copy contains this Copyright Notice, whether distributed in print or electronically.
copy contains the Copyright Notice, whether distributed in print or electronically.
@@ -332,7 +332,7 @@ metadata, such as the argument names. The following table describes the items ma
available to the context so that you can use them for key and conditional computations:
[[cache-spel-context-tbl]]
.Cache SpEL available metadata
.Cache metadata available in SpEL expressions
|===
| Name| Location| Description| Example
@@ -358,7 +358,7 @@ available to the context so that you can use them for key and conditional comput
| `args`
| Root object
| The arguments (as array) used for invoking the target
| The arguments (as an object array) used for invoking the target
| `#root.args[0]`
| `caches`
@@ -368,9 +368,10 @@ available to the context so that you can use them for key and conditional comput
| Argument name
| Evaluation context
| Name of any of the method arguments. If the names are not available
(perhaps due to having no debug information), the argument names are also available under the `#a<#arg>`
where `#arg` stands for the argument index (starting from `0`).
| The name of a particular method argument. If the names are not available
(for example, because the code was compiled without the `-parameters` flag), individual
arguments are also available using the `#a<#arg>` syntax where `<#arg>` stands for the
argument index (starting from 0).
| `#iban` or `#a0` (you can also use `#p0` or `#p<#arg>` notation as an alias).
| `result`
@@ -524,7 +525,7 @@ To enable caching annotations add the annotation `@EnableCaching` to one of your
----
@Configuration
@EnableCaching
public class AppConfig {
class AppConfig {
@Bean
CacheManager cacheManager() {
@@ -24,7 +24,7 @@ To create the archive, two additional JVM flags must be specified:
* `-Dspring.context.exit=onRefresh`: starts and then immediately exits your Spring
application as described above
To create a CDS archive, your JDK must have a base image. If you add the flags above to
To create a CDS archive, your JDK/JRE must have a base image. If you add the flags above to
your startup script, you may get a warning that looks like this:
[source,shell,indent=0,subs="verbatim"]
@@ -32,7 +32,8 @@ your startup script, you may get a warning that looks like this:
-XX:ArchiveClassesAtExit is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info.
----
The base CDS archive can be created by issuing the following command:
The base CDS archive is usually provided out-of-the-box, but can also be created if needed by issuing the following
command:
[source,shell,indent=0,subs="verbatim"]
----
@@ -44,6 +45,9 @@ The base CDS archive can be created by issuing the following command:
Once the archive is available, add `-XX:SharedArchiveFile=application.jsa` to your startup
script to use it, assuming an `application.jsa` file in the working directory.
To check if the CDS cache is effective, you can use (for testing purposes only, not in production) `-Xshare:on` which
prints an error message and exits if CDS can't be enabled.
To figure out how effective the cache is, you can enable class loading logs by adding
an extra attribute: `-Xlog:class+load:file=cds.log`. This creates a `cds.log` with every
attempt to load a class and its source. Classes that are loaded from the cache should have
@@ -58,8 +62,11 @@ a "shared objects file" source, as shown in the following example:
[0.065s][info][class,load] org.springframework.context.MessageSource source: shared objects file (top)
----
TIP: If you have a large number of classes that are not loaded from the cache, make sure that
the JDK and classpath used by the commands that create the archive and start the application
are identical. Note also that to effectively cache classes, the classpath should be specified
as a list of JARs containing those classes, and avoid the usage of directories and `*`
wildcard characters.
If CDS can't be enabled or if you have a large number of classes that are not loaded from the cache, make sure that
the following conditions are fulfilled when creating and using the archive:
- The very same JVM must be used.
- The classpath must be specified as a list of JARs, and avoid the usage of directories and `*` wildcard characters.
- The timestamps of the JARs must be preserved.
- When using the archive, the classpath must be the same than the one used to create the archive, in the same order.
Additional JARs or directories can be specified *at the end* (but won't be cached).
@@ -19,6 +19,8 @@ A checkpoint can be created on demand, for example using a command like `jcmd ap
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.
WARNING: Be aware that when defining scheduling tasks at a fixed rate, for example with an annotation like `@Scheduled(fixedRate = 5000)`, all missed executions between checkpoint and restore will be performed when the JVM is restored with on-demand checkpoint/restore. If this is not the behavior you want, it is recommended to schedule tasks at a fixed delay (for example with `@Scheduled(fixedDelay = 5000)`) or with a cron expression as those are calculated after every task execution.
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
@@ -58,7 +58,7 @@ your `@Configuration` classes, as the following example shows:
By default, the infrastructure looks for a bean named `jmsListenerContainerFactory`
as the source for the factory to use to create message listener containers. In this
case (and ignoring the JMS infrastructure setup), you can invoke the `processOrder`
method with a core poll size of three threads and a maximum pool size of ten threads.
method with a core pool size of three threads and a maximum pool size of ten threads.
You can customize the listener container factory to use for each annotation or you can
configure an explicit default by implementing the `JmsListenerConfigurer` interface.
@@ -1,7 +1,7 @@
[[observability]]
= Observability Support
Micrometer defines an https://micrometer.io/docs/observation[Observation concept that enables both Metrics and Traces] in applications.
Micrometer defines an {micrometer-docs}/observation.html[Observation concept that enables both Metrics and Traces] in applications.
Metrics support offers a way to create timers, gauges, or counters for collecting statistics about the runtime behavior of your application.
Metrics can help you to track error rates, usage patterns, performance, and more.
Traces provide a holistic view of an entire system, crossing application boundaries; you can zoom in on particular user requests and follow their entire completion across applications.
@@ -38,7 +38,7 @@ As outlined xref:integration/observability.adoc[at the beginning of this section
|===
NOTE: Observations are using Micrometer's official naming convention, but Metrics names will be automatically converted
https://micrometer.io/docs/concepts#_naming_meters[to the format preferred by the monitoring system backend]
{micrometer-docs}/concepts/naming.html[to the format preferred by the monitoring system backend]
(Prometheus, Atlas, Graphite, InfluxDB...).
@@ -162,6 +162,8 @@ include-code::./JmsTemplatePublish[]
It uses the `io.micrometer.jakarta9.instrument.jms.DefaultJmsPublishObservationConvention` by default, backed by the `io.micrometer.jakarta9.instrument.jms.JmsPublishObservationContext`.
Similar observations are recorded with `@JmsListener` annotated methods when response messages are returned from the listener method.
[[observability.jms.process]]
=== JMS message Processing instrumentation
@@ -366,7 +368,7 @@ This means that during the execution of that task, the ThreadLocals and logging
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.
In these cases, the {micrometer-context-propagation-docs}/[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:
@@ -71,8 +71,34 @@ This can be done with `method(HttpMethod)` or with the convenience methods `get(
Next, the request URI can be specified with the `uri` methods.
This step is optional and can be skipped if the `RestClient` is configured with a default URI.
The URL is typically specified as a `String`, with optional URI template variables.
String URLs are encoded by default, but this can be changed by building a client with a custom `uriBuilderFactory`.
The following example configures a GET request to `https://example.com/orders/42`:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
int id = 42;
restClient.get()
.uri("https://example.com/orders/{id}", id)
....
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
val id = 42
restClient.get()
.uri("https://example.com/orders/{id}", id)
...
----
======
A function can also be used for more controls, such as specifying xref:web/webmvc/mvc-uri-building.adoc[request parameters].
String URLs are encoded by default, but this can be changed by building a client with a custom `uriBuilderFactory`.
The URL can also be provided with a function or as a `java.net.URI`, both of which are not encoded.
For more details on working with and encoding URIs, see xref:web/webmvc/mvc-uri-building.adoc[URI Links].
@@ -263,7 +289,7 @@ String result = restClient.get() <1>
.uri("https://example.com/this-url-does-not-exist") <1>
.retrieve()
.onStatus(HttpStatusCode::is4xxClientError, (request, response) -> { <2>
throw new MyCustomRuntimeException(response.getStatusCode(), response.getHeaders()) <3>
throw new MyCustomRuntimeException(response.getStatusCode(), response.getHeaders()); <3>
})
.body(String.class);
----
@@ -468,6 +494,9 @@ If no request factory is specified when the `RestClient` was built, it will use
Otherwise, if the `java.net.http` module is loaded, it will use Java's `HttpClient`.
Finally, it will resort to the simple default.
TIP: Note that the `SimpleClientHttpRequestFactory` may raise an exception when accessing the status of a response that represents an error (e.g. 401).
If this is an issue, use any of the alternative request factories.
[[rest-webclient]]
== `WebClient`
@@ -733,7 +733,7 @@ reached, does the executor create a new thread beyond the core size. If the max
has also been reached, then the executor rejects the task.
By default, the queue is unbounded, but this is rarely the desired configuration,
because it can lead to `OutOfMemoryErrors` if enough tasks are added to that queue while
because it can lead to `OutOfMemoryError` if enough tasks are added to that queue while
all pool threads are busy. Furthermore, if the queue is unbounded, the max size has
no effect at all. Since the executor always tries the queue before creating a new
thread beyond the core size, a queue must have a finite capacity for the thread pool to
@@ -8,7 +8,7 @@ existing Java application.
The Spring Framework provides a dedicated `ApplicationContext` that supports a Groovy-based
Bean Definition DSL. For more details, see
xref:core/beans/basics.adoc#groovy-bean-definition-dsl[The Groovy Bean Definition DSL].
xref:core/beans/basics.adoc#beans-factory-groovy[The Groovy Bean Definition DSL].
Further support for Groovy, including beans written in Groovy, refreshable script beans,
and more is available in xref:languages/dynamic.adoc[Dynamic Language Support].
@@ -166,7 +166,7 @@ public class SampleConfiguration {
@Bean
@NotNull
public SampleBean sampleBean$demo_kotlin_internal_test() {
return new SampleBean();
return new SampleBean();
}
}
----
@@ -111,7 +111,8 @@ a mock service with Mockito:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="accountService" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="org.example.AccountService"/>
<constructor-arg type="java.lang.Class" value="org.example.AccountService"/>
<constructor-arg type="java.lang.String" value="accountService"/>
</bean>
----
@@ -1,7 +1,7 @@
[[spring-mvc-test-vs-end-to-end-integration-tests]]
= MockMvc vs End-to-End Tests
MockMVc is built on Servlet API mock implementations from the
MockMvc is built on Servlet API mock implementations from the
`spring-test` module and does not rely on a running container. Therefore, there are
some differences when compared to full end-to-end integration tests with an actual
client and a live server running.
@@ -1,38 +1,16 @@
[[spring-mvc-test-vs-streaming-response]]
= Streaming Responses
The best way to test streaming responses such as Server-Sent Events is through the
<<WebTestClient>> which can be used as a test client to connect to a `MockMvc` instance
to perform tests on Spring MVC controllers without a running server. For example:
You can use `WebTestClient` to test xref:testing/webtestclient.adoc#webtestclient-stream[streaming responses]
such as Server-Sent Events. However, `MockMvcWebTestClient` doesn't support infinite
streams because there is no way to cancel the server stream from the client side.
To test infinite streams, you'll need to
xref:testing/webtestclient.adoc#webtestclient-server-config[bind to] a running server,
or when using Spring Boot,
{spring-boot-docs}/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-with-running-server[test with a running server].
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
WebTestClient client = MockMvcWebTestClient.bindToController(new SseController()).build();
FluxExchangeResult<Person> exchangeResult = client.get()
.uri("/persons")
.exchange()
.expectStatus().isOk()
.expectHeader().contentType("text/event-stream")
.returnResult(Person.class);
// Use StepVerifier from Project Reactor to test the streaming response
StepVerifier.create(exchangeResult.getResponseBody())
.expectNext(new Person("N0"), new Person("N1"), new Person("N2"))
.expectNextCount(4)
.consumeNextWith(person -> assertThat(person.getName()).endsWith("7"))
.thenCancel()
.verify();
----
======
`WebTestClient` can also connect to a live server and perform full end-to-end integration
tests. This is also supported in Spring Boot where you can
{spring-boot-docs}/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-with-running-server[test a running server].
`MockMvcWebTestClient` does support asynchronous responses, and even streaming responses.
The limitation is that it can't influence the server to stop, and therefore the server
must finish writing the response on its own.
@@ -31,5 +31,5 @@ provide convenience methods that delegate to the aforementioned methods in
The `spring-jdbc` module provides support for configuring and launching an embedded
database, which you can use in integration tests that interact with a database.
For details, see xref:data-access/jdbc/embedded-database-support.adoc[Embedded Database Support]
and <<data-access.adoc#jdbc-embedded-database-dao-testing, Testing Data Access
Logic with an Embedded Database>>.
and xref:data-access/jdbc/embedded-database-support.adoc#jdbc-embedded-database-dao-testing[Testing Data Access
Logic with an Embedded Database].
@@ -2,7 +2,7 @@
= Context Configuration with Groovy Scripts
To load an `ApplicationContext` for your tests by using Groovy scripts that use the
xref:core/beans/basics.adoc#groovy-bean-definition-dsl[Groovy Bean Definition DSL], you can annotate
xref:core/beans/basics.adoc#beans-factory-groovy[Groovy Bean Definition DSL], you can annotate
your test class with `@ContextConfiguration` and configure the `locations` or `value`
attribute with an array that contains the resource locations of Groovy scripts. Resource
lookup semantics for Groovy scripts are the same as those described for
@@ -193,7 +193,7 @@ Kotlin::
[[webtestclient-fn-config]]
=== Bind to Router Function
This setup allows you to test <<web-reactive.adoc#webflux-fn, functional endpoints>> via
This setup allows you to test xref:web/webflux-functional.adoc[functional endpoints] via
mock request and response objects, without a running server.
For WebFlux, use the following which delegates to `RouterFunctions.toWebHandler` to
@@ -339,6 +339,19 @@ Java::
spec -> spec.expectHeader().contentType(MediaType.APPLICATION_JSON)
);
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
client.get().uri("/persons/1")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectAll(
{ spec -> spec.expectStatus().isOk() },
{ spec -> spec.expectHeader().contentType(MediaType.APPLICATION_JSON) }
)
----
======
You can then choose to decode the response body through one of the following:
@@ -672,13 +685,13 @@ Kotlin::
val result = client.get().uri("/persons/1")
.exchange()
.expectStatus().isOk()
.expectBody(Person.class)
.returnResult();
.expectBody<Person>()
.returnResult()
// For a response without a body
val result = client.get().uri("/path")
.exchange()
.expectBody().isEmpty();
.expectBody().isEmpty()
----
======
@@ -704,4 +717,3 @@ Kotlin::
.andExpect(model().attribute("string", "a string value"));
----
======
@@ -1,5 +1,6 @@
[[webflux-cors]]
= CORS
[.small]#xref:web/webmvc-cors.adoc[See equivalent in the Servlet stack]#
Spring WebFlux lets you handle CORS (Cross-Origin Resource Sharing). This section
@@ -364,7 +365,7 @@ Kotlin::
You can apply CORS support through the built-in
{spring-framework-api}/web/cors/reactive/CorsWebFilter.html[`CorsWebFilter`], which is a
good fit with <<webflux-fn, functional endpoints>>.
good fit with xref:web/webflux-functional.adoc[functional endpoints].
NOTE: If you try to use the `CorsFilter` with Spring Security, keep in mind that Spring
Security has {docs-spring-security}/servlet/integrations/cors.html[built-in support] for
@@ -1,5 +1,6 @@
[[webflux-fn]]
= Functional Endpoints
[.small]#xref:web/webmvc-functional.adoc[See equivalent in the Servlet stack]#
Spring WebFlux includes WebFlux.fn, a lightweight functional programming model in which functions
@@ -4,10 +4,13 @@
`spring-webflux` depends on `reactor-core` and uses it internally to compose asynchronous
logic and to provide Reactive Streams support. Generally, WebFlux APIs return `Flux` or
`Mono` (since those are used internally) and leniently accept any Reactive Streams
`Publisher` implementation as input. The use of `Flux` versus `Mono` is important, because
it helps to express cardinality -- for example, whether a single or multiple asynchronous
values are expected, and that can be essential for making decisions (for example, when
encoding or decoding HTTP messages).
`Publisher` implementation as input.
When a `Publisher` is provided, it can be treated only as a stream with unknown semantics (0..N).
If, however, the semantics are known, you should wrap it with `Flux` or `Mono.from(Publisher)` instead
of passing the raw `Publisher`.
The use of `Flux` versus `Mono` is important, because it helps to express cardinality --
for example, whether a single or multiple asynchronous values are expected,
and that can be essential for making decisions (for example, when encoding or decoding HTTP messages).
For annotated controllers, WebFlux transparently adapts to the reactive library chosen by
the application. This is done with the help of the
@@ -15,15 +18,3 @@ the application. This is done with the help of the
provides pluggable support for reactive library and other asynchronous types. The registry
has built-in support for RxJava 3, Kotlin coroutines and SmallRye Mutiny, but you can
register others, too.
For functional APIs (such as <<webflux-fn>>, the `WebClient`, and others), the general rules
for WebFlux APIs apply -- `Flux` and `Mono` as return values and a Reactive Streams
`Publisher` as input. When a `Publisher`, whether custom or from another reactive library,
is provided, it can be treated only as a stream with unknown semantics (0..N). If, however,
the semantics are known, you can wrap it with `Flux` or `Mono.from(Publisher)` instead
of passing the raw `Publisher`.
For example, given a `Publisher` that is not a `Mono`, the Jackson JSON message writer
expects multiple values. If the media type implies an infinite stream (for example,
`application/json+stream`), values are written and flushed individually. Otherwise,
values are buffered into a list and rendered as a JSON array.
@@ -97,8 +97,8 @@ Java::
Mono<Person> result = client.get()
.uri("/persons/{id}", id).accept(MediaType.APPLICATION_JSON)
.retrieve()
.onStatus(HttpStatus::is4xxClientError, response -> ...)
.onStatus(HttpStatus::is5xxServerError, response -> ...)
.onStatus(HttpStatusCode::is4xxClientError, response -> ...)
.onStatus(HttpStatusCode::is5xxServerError, response -> ...)
.bodyToMono(Person.class);
----
@@ -109,8 +109,8 @@ Kotlin::
val result = client.get()
.uri("/persons/{id}", id).accept(MediaType.APPLICATION_JSON)
.retrieve()
.onStatus(HttpStatus::is4xxClientError) { ... }
.onStatus(HttpStatus::is5xxServerError) { ... }
.onStatus(HttpStatusCode::is4xxClientError) { ... }
.onStatus(HttpStatusCode::is5xxServerError) { ... }
.awaitBody<Person>()
----
======
@@ -1,5 +1,6 @@
[[webflux-websocket]]
= WebSockets
[.small]#xref:web/websocket.adoc[See equivalent in the Servlet stack]#
This part of the reference documentation covers support for reactive-stack WebSocket

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