Specifically, the documentation update reflects that:
- Initially, it was mentioned that only the `BeanFactoryAware`
interface is ignored by default.
- The updated documentation now correctly states that `BeanNameAware`,
`BeanFactoryAware`, and `BeanClassLoaderAware` interfaces are all
ignored by default.
This change ensures a more accurate representation of the default
behavior regarding which dependency interfaces are automatically
ignored during autowiring in the context of Spring's bean factory
mechanism.
Closes gh-34747
Signed-off-by: lituizi <2811328244@qq.com>
Includes spring.locking.strict revision to differentiate between true, false, not set.
Includes checkFlag accessor on SpringProperties, also used in StatementCreatorUtils.
Closes gh-34729
See gh-34303
This commit provides first-class support for Bean Overrides
(@MockitoBean, @MockitoSpyBean, @TestBean, etc.) with
@ContextHierarchy.
Specifically, bean overrides can now specify which ApplicationContext
they target within the context hierarchy by configuring the
`contextName` attribute in the annotation. The `contextName` must match
a corresponding `name` configured via @ContextConfiguration.
For example, the following test class configures the name of the second
hierarchy level to be "child" and simultaneously specifies that the
ExampleService should be wrapped in a Mockito spy in the context named
"child". Consequently, Spring will only attempt to create the spy in
the "child" context and will not attempt to create the spy in the
parent context.
@ExtendWith(SpringExtension.class)
@ContextHierarchy({
@ContextConfiguration(classes = Config1.class),
@ContextConfiguration(classes = Config2.class, name = "child")
})
class MockitoSpyBeanContextHierarchyTests {
@MockitoSpyBean(contextName = "child")
ExampleService service;
// ...
}
See gh-33293
See gh-34597
See gh-34726
Closes gh-34723
Signed-off-by: Sam Brannen <104798+sbrannen@users.noreply.github.com>
For bean override support (@MockitoBean, @TestBean, etc.), the logic
for field injection previously resided in the BeanOverrideRegistry
which resulted in a strange mixture of concerns.
To address that, this commit moves the field injection logic to the
BeanOverrideTestExecutionListener, and the BeanOverrideRegistry now
serves a single role, namely the role of a registry.
Closes gh-34726
- ClassUtils.isAssignable(): Avoid Map lookup when the type is not a
primitive.
- AnnotationsScanner: Perform low cost array length check before String
comparisons.
- BeanFactoryUtils: Use char comparison instead of String comparison.
The bean factory prefix is '&', so we can use a char comparison
instead of more heavyweight String.startsWith("&").
- AbstractBeanFactory.getMergedBeanDefinition(): Perform the low cost
check first. Map lookup, while cheap, is still more expensive than
instanceof.
Closes gh-34717
Signed-off-by: Olivier Bourgain <olivierbourgain02@gmail.com>
Prior to this commit, the `DefaultWebClient` observability
instrumentation would create the observation context before the reactive
pipeline is fully materialized. In case of errors and retries (with the
`retry(long)` operator), the observation context would be reused for
separate observations, which is incorrect.
This commit ensures that a new observation context is created for each
subscription.
Fixes gh-34671
This commit is a follow-up to gh-34592. It introduces
recursive boxing of Kotlin nested value classes in CoroutinesUtils.
Signed-off-by: Dmitry Sulman <dmitry.sulman@gmail.com>
Closes gh-34682
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
This commit fixes a minor typo in the "Java Bean Validation - Customizing
Validation Errors" section of the reference manual.
Closes gh-34686
Signed-off-by: Tobias Hänel <contact@tobias-haenel.de>
Prior to this commit, the Test Bean Override feature provided support
for overriding beans based on qualifier annotations in several
scenarios; however, qualifier annotations got lost if they were
declared on the return type of the @Bean method for the bean being
overridden and the @BeanOverride (such as @MockitoBean) was based on
a supertype of that return type.
To address that, this commit sets the @BeanOverride field as the
"qualified element" in the RootBeanDefinition to ensure that qualifier
annotations are available for subsequent autowiring candidate
resolution.
Closes gh-34646
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-34659
Before RfcUriParser we expected opaque URI's to not have ":/"
after the scheme while the new parser expect opaque URI's to
not have a slash anywhere after the scheme. This commit
restores the previous behavior.
Closes gh-34588
This commit replaces use of the deprecated Gradle `task` method with
the new `tasks.register` method.
Closes gh-34617
Signed-off-by: Dmitry Sulman <dmitry.sulman@gmail.com>
This commit removes the BDDMockito Checkstyle rule, since it did not
actually enforce the use of BDDMockito.
This commit also updates static imports to use Mockito instead of
BDDMockito where appropriate (automated via the Eclipse IDE Organize
Imports clean-up task).
Closes gh-34616
FormHttpMessageConverter could throw a more specific
HttpMessageNotReadableException instead of an IllegalArgumentException
when the http form data is invalid.
See gh-34594
Signed-off-by: Russell Bolles <rbolles@netflix.com>
Prior to this commit, MockCookie.parse() failed with an
IllegalArgumentException when attempting to parse a custom attribute
with a value, such as "Version=1". This is a regression that was
inadvertently introduced in 7fc4937199
when adding support for the "Partitioned" attribute which does not
support a value.
This commit addresses this regression by parsing both the name and the
value from an optional, custom attribute.
See gh-31454
Closes gh-34575
This commit introduces a new loadContextForAotProcessing(...) variant
in AotContextLoader which accepts a RuntimeHints argument. This new
method is an interface default method which delegates to the existing
loadContextForAotProcessing(MergedContextConfiguration) variant for
backward compatibility.
In addition, the original loadContextForAotProcessing(...) variant is
now deprecated and has been converted to an interface default method
which throws an UnsupportedOperationException.
Note, however, that the framework now only invokes the new
loadContextForAotProcessing(...) variant within TestContextAotGenerator.
Closes gh-34513
This commit adds support for the Partitioned cookie attribute in the
reactive HTTP clients that support this: Reactor and HttpComponents.
Closes gh-34521
Signed-off-by: Rhett CfZhuang <dark.momo985@gmail.com>
[brian.clozel@broadcom.com: rework tests and support HttpComponents]
Signed-off-by: Brian Clozel <brian.clozel@broadcom.com>
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-34488
Prior to this commit, the `DispatcherServlet` would try and reset the
response buffer in case of errors, if the response is not committed
already. This allows for more flexible error handling, even if the
response was being handled already when it errored.
Resetting the response buffer clears the body but leaves HTTP response
headers intact. This is done on purpose as to not clear headers
previously added by Servlet Filters. By leaving in place some headers
like "Content-Type", this does not take into account the fact that the
response body was cleared and that error handling will perform another
round of content negotiation. While this isn't a problem for some
Servlet containers which enforce a single "Content-Type" header value,
this can cause multiple/duplicate values for some others.
This commit ensures that the "Content-Type" response header is removed
at the same time as we clear the "producible media types" attribute:
another pass of content negotiation will be performed for error
handling.
Fixes gh-34366
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-34460
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-34464
This commit adds an onRequest() hook to request more data from
the source in order to avoid hung uploads in MultipartParser.
Closes gh-34388
Signed-off-by: Gang Cheng <chenggangpro@gmail.com>
This commit adds missing `@since` tags for formField() and formFields in
MockHttpServletRequestDsl. See gh-34412 related issue.
Closes gh-34448
Signed-off-by: Johnny Lim <izeye@naver.com>
In order to avoid Gradle build warnings about @SuppressFBWarnings, this
commit introduces a testCompileOnly dependency on `findbugs` in the
spring-webmvc module so that the class file for @SuppressFBWarnings is
available to the compileTestJava task.
Closes gh-34418
Prior to this commit, @MockitoSpyBean could only be declared on fields
within test classes, which prevented developers from being able to
easily reuse spy configuration across a test suite.
With this commit, @MockitoSpyBean is now supported at the type level
on test classes, their superclasses, and interfaces implemented by
those classes. @MockitoSpyBean is also supported on enclosing classes
for @Nested test classes, their superclasses, and interfaces
implemented by those classes, while honoring @NestedTestConfiguration
semantics.
In addition, @MockitoSpyBean:
- has a new `types` attribute that can be used to declare the type or
types to spy when @MockitoSpyBean is declared at the type level
- can be declared as a repeatable annotation at the type level
- can be declared as a meta-annotation on a custom composed annotation
which can be reused across a test suite (see the @SharedSpies
example in the reference manual)
To support these new features, this commit also includes the following
changes.
- MockitoSpyBeanOverrideProcessor has been revised to support
@MockitoSpyBean at the type level.
- The "Bean Overriding in Tests" and "@MockitoBean and
@MockitoSpyBean" sections of the reference manual have been fully
revised.
See gh-34408
Closes gh-33925
Prior to this commit, if an appropriate Converter was registered with
the ConversionService that converts from a POJO to an array and that
ConversionService was registered with the Spring Expression Language
(SpEL) TypeConverter, an attempt to invoke a varargs method in a SpEL
expression with such a POJO would fail because the ConversionService
was not used to convert the POJO to an array suitable for the varargs
method invocation.
This commit revises the implementations of convertArguments(...) and
convertAllMethodHandleArguments(...) in ReflectionHelper to support
such use cases.
Closes gh-34371
Prior to this commit, the order values of TestExecutionListener
implementations were hard-coded in their getOrder() methods.
To benefit users and integrators, this commit exposes those order values
as an ORDER constant in each TestExecutionListener.
See gh-34225
Closes gh-34404
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
If the Servlet container delegates a disconnected client error via
AsyncListener#onError, wrap it as AsyncRequestNotUsableException
for more targeted and consistent handling of such errors.
Closes gh-34363
This commit ensures that `ContentDisposition` parses attributes like
"filename" and "filename*" in a case insensitive fashion, per RFC 6266.
Closes gh-34383
Signed-off-by: Andras Dobrosi <dobrosi@gmail.com>
[brian.clozel@broadcom.com: apply code conventions]
Signed-off-by: Brian Clozel <brian.clozel@broadcom.com>
Changes made to the Bean Override search algorithms in commit
9181cce65f resulted in a regression that caused tests to start failing
due to duplicate BeanOverrideHandlers under the following circumstances.
- An enclosing class (typically a top-level test class) declares a
@BeanOverride such as @MockitoBean.
- An inner class is declared in that enclosing class.
- A @Nested test class which extends that inner class is declared in
the same enclosing class.
The reason for the duplicate detection is that the current search
algorithm visits the common enclosing class twice.
To address that, this commit revises the search algorithm in
BeanOverrideHandler so that enclosing classes are only visited once.
See gh-33925
Closes gh-34324
Prior to this commit, test bean overrides (for example, @MockitoBean,
@TestBean, etc.) eagerly honored the name of the annotated field as a
fallback qualifier, effectively ignoring @Primary and @Fallback
semantics for certain use cases.
This led to situations where a bean override for a test would select a
different bean than the core container would for the same autowiring
metadata.
To address that, this commit revises the implementation of
BeanOverrideBeanFactoryPostProcessor so that @Primary and @Fallback
semantics are consistently honored before attempting to use the
annotated field's name as a fallback qualifier.
Closes gh-34374
Ensure the original instance is always the one returned no matter how
many times the HandlerMethod is re-created.
Make the constructor protected to allow subclasses to re-create the
HandlerMethod as the concrete subclass.
See gh-34375
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-34360
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
As of Spring Framework 6.2, the `RestClient.retrieve()` method is a
no-op and developers must invoke a terminal operation on the returned
`ResponseSpec` to have any side effect.
This has been documented in the Javadoc and the wiki release notes, but
this commit highlights this as well in the reference documentation.
Closes gh-34334
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
Prior to this commit, several common HTTP headers were ignored from the
data binding process when collecting property values, in gh-34039 and
gh-34182.
This commit completes the initial enhancement by ensuring that the
default header predicate is also considering cases where constructor
binding is applied and the Java type has a lowercase variant of the HTTP
header name to filter.
Fixes gh-34292
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.
This commit adds support for Kotlin properties in Spring WebMVC
controllers, supported for reasons explained in gh-31856, with
kotlinx.serialization converters.
Closes gh-34284
This commit adds support for Kotlin properties in Spring WebFlux
controllers, supported for reasons explained in gh-31856, with
kotlinx.serialization codecs.
See gh-34284
getFlag() returns true when the property is equal, ignoring case, to the
string "true", not just "true"; "TrUe" also means true.
Closes gh-34295
Signed-off-by: Mengqi Xu <2663479778@qq.com>
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
This commit harmonizes how a candidate value is parsed to extract its
key and default, if any. Rather than returning {@code null} if no
default is available, `splitKeyAndValue` now consistently returns a
non-null array.
This prevents an escaped separator character to be mistakenly identified
as a placeholder in certain cases.
Closes gh-34289
This commit adds a reference documentation section explaining how
applications can use custom `HttpServiceArgumentResolver`
implementations to support complex application types as method
parameters in HTTP interfaces.
Closes gh-34227
For ComandLineArgs, supplying the same option multiple times with
different values is valid, and the values will be stored in a List.
This commit also updates the Javadoc for SimpleCommandLineArgsParser.
See gh-34282
Signed-off-by: puppy4c <puppy4c@foxmail.com>
Prior to this commit, @MockitoBean could only be declared on fields
within test classes, which prevented developers from being able to
easily reuse mock configuration across a test suite.
With this commit, @MockitoBean is now supported at the type level on
test classes, their superclasses, and interfaces implemented by those
classes. @MockitoBean is also supported on enclosing classes for
@Nested test classes, their superclasses, and interfaces implemented
by those classes, while honoring @NestedTestConfiguration semantics.
In addition, @MockitoBean:
- has a new `types` attribute that can be used to declare the type or
types to mock when @MockitoBean is declared at the type level
- can be declared as a repeatable annotation at the type level
- can be declared as a meta-annotation on a custom composed annotation
which can be reused across a test suite (see the @SharedMocks
example in the reference manual)
To support these new features, this commit also includes the following
changes.
- The `field` property in BeanOverrideHandler is now @Nullable.
- BeanOverrideProcessor has a new `default` createHandlers() method
which is invoked when a @BeanOverride annotation is found at the
type level.
- MockitoBeanOverrideProcessor implements the new createHandlers()
method.
- The internal findHandlers() method in BeanOverrideHandler has been
completely overhauled.
- The @MockitoBean and @MockitoSpyBean section of the reference
manual has been completely overhauled.
Closes gh-33925
This commit ensures that checks for PathResource locations are skipped
because this resource implementation will always resolve under the
current location.
Closes gh-34167
Prior to this commit, HTTP request data binding had been improved to
filter out by default the "Priority" header in #34039.
This commit extends the set of filtered header names with:
"Accept", "Authorization", "Connection", "Cookie", "From", "Host",
"Origin", "Priority", "Range", "Referer", "Upgrade".
If an application wishes to let those header be bound, it will need to
configure the binder and replace the default header predicate by calling
`setHeaderPredicate`.
Closes gh-34182
Prior to this commit, the search algorithm used to locate a @TestBean
factory method within a test class hierarchy incorrectly found factory
methods declared in subclasses or nested test classes "below" the class
in which the @TestBean field was declared. This resulted in "duplicate
bean override" failures for @TestBean overrides which are clearly not
duplicates but rather "overrides of an override".
This commit ensures that @TestBean factory method resolution is
consistent in type hierarchies as well as in enclosing class
hierarchies (for @Nested test classes) by beginning the search for a
factory method in the class which declares the @TestBean field.
Closes gh-34204
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
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
Prior to this commit, a @BeanOverride (such as @TestBean) for a
specific target bean which was declared in a superclass always took
precedence over a bean override for the same target bean in a subclass,
thereby rendering the bean override configuration in the subclass
useless. In other words, there was no way for a test class to override
a bean override declared in a superclass.
To address that, this commit switches from direct use of
ReflectionUtils.doWithFields() to a custom search algorithm that
traverses the class hierarchy using tail recursion for processing
@BeanOverride fields (delegating now to
ReflectionUtils.doWithLocalFields() in order to continue to benefit
from the caching of declared fields in ReflectionUtils).
Closes gh-34194
Prior to this commit, the HTTP interface client would create URI
templates and name query params like so:
"?{queryParam0}={queryParam0[0]}".
While technically correct, the URI template is further used in
observations as a KeyValue. This means that several service methods
could result in having the exact same URI template even if they produce
a different set of query params.
This commit improves the naming of query params in the generated URI
templates for better observability integration.
Closes gh-34176
This change ensures that a request containing query parameters in the
array format `someArray[]=value` can be bound into a simple array in
constructors, even for cases where the array values don't have nested
properties.
The value resolver is directly called in the constructor case, before
any mutable properties are considered or even cleared (see
`WebDataBinder#adaptEmptyArrayIndices` method). As a result, we need to
accommodate the possibility that the request stores array elements under
the `name[]` key rather than `name`. This change attempts a secondary
lookup with the `[]` suffix if the type is a list or array, and the key
doesn't include an index.
Closes gh-34121
This change ensures that DataBinder can bind constructor with a Map
parameter that has no nested properties, but just simple values like
a String: `someMap[0]=exampleString`.
Integration tests have been added to cover similar cases that use the
ServletRequestDataBinder.
Closes gh-34043
This commit fixes a regression in property placeholder resolution where
the original key was no longer considered for an exact match before
processing the placeholder itself.
By default, property resolution uses ':' as the separator between the
key and the fallback value.
Consider a request to resolve ${prefix://service}. Previously,
placeholder resolution would first attempt to resolve the raw text, that
is 'prefix://service', before attempting to resolve the 'prefix' key and
then use '//service' if the key did not resolve.
This commit restores that behaviour purely for backward compatible
reason.
Closes gh-34124
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
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-34064
Prior to this commit, the order of parameters passed to
ELResolver#getValue was incorrect.
The `name` should correspond to the `property` parameter of the
`getValue` method instead the `base` parameter.
See gh-32383
See gh-33942
Closes gh-33945
Make it public and move it down to the annotations package alongside
InitBinderBindingContext. This is mirrors the hierarchy in Spring MVC
with the ExtendedServletRequestDataBinder. The change will allow
customization of the header names to include/exclude in data binding.
See gh-34039
Prior to this commit, `MockMvc` would support checking for the Servlet
error message as the "response status reason". While this error message
can be driven with the `@ResponseStatus` annotation, this message is not
technically the HTTP status reason listed on the response status line.
This message is provided by the Servlet container in the error page when
the `response.sendError(int, String)` method is used.
This commit adds the missing
`mvc.get().uri("/error/message")).hasErrorMessage("error message")`
assertion to check for this Servlet error message.
Closes gh-34016
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
This commit fixes a regression introduced by gh-24560, when adding
execution metadata support for scheduled tasks. The
`OutcomeTrackingRunnable` would delegate to the actual runnable but
could also hide whether it implements the `SchedulingAwareRunnable`
contract.
This commit ensures that `OutcomeTrackingRunnable` always implements
that contract and delegates to the runnable if possible, or return
default values otherwise.
Fixes gh-34058
Properly processes recursive types through always comparing generics via the top-level ResolvableType (rather than through nested TypeDescriptors with custom ResolvableType instances).
Closes gh-33932
It is currently possible for one Bean Override to override another
logically equivalent Bean Override.
For example, a @TestBean can override a @MockitoBean, and vice versa.
In fact, it's also possible for a @MockitoBean to override another
@MockitoBean, for a @TestBean to override a @TestBean, etc.
However, there may be viable use cases for one override overriding
another override. For example, one may have a need to spy on a bean
created by a @TestBean factory method.
In light of that, we do not prohibit one Bean Override from overriding
another Bean Override; however, with this commit we now log a warning
to help developers diagnose issues in case such an override is
unintentional.
For example, given the following test class, where TestConfig registers
a single bean of type MyService named "myService"...
@SpringJUnitConfig(TestConfig.class)
class MyTests {
@TestBean(methodName = "example.TestUtils#createMyService")
MyService testService;
@MockitoBean
MyService mockService;
@Test
void test() {
// ...
}
}
... running that test class results in a log message similar to the
following, which has been formatted for readability.
WARN - Bean with name 'myService' was overridden by multiple handlers:
[
[TestBeanOverrideHandler@44b21f9f
field = example.MyService example.MyTests.testService,
beanType = example.MyService,
beanName = [null],
strategy = REPLACE_OR_CREATE
],
[MockitoBeanOverrideHandler@7ee8130e
field = example.MyService example.MyTests.mockService,
beanType = example.MyService,
beanName = [null],
strategy = REPLACE_OR_CREATE,
reset = AFTER,
extraInterfaces = set[[empty]],
answers = RETURNS_DEFAULTS, serializable = false
]
]
NOTE: The last registered BeanOverrideHandler wins. In the above
example, that means that @MockitoBean overrides @TestBean, resulting
in a Mockito mock for the MyService bean in the test's
ApplicationContext.
Closes gh-34056
Prior to this commit, the Bean Override feature in the Spring
TestContext Framework (for annotations such as @MockitoBean and
@TestBean) silently allowed one bean override to override another
"identical" bean override; however, Spring Boot's @MockBean and
@SpyBean support preemptively rejects identical overrides and throws
an IllegalStateException to signal the configuration error to the user.
To align with the behavior of @MockBean and @SpyBean in Spring Boot,
and to help developers avoid scenarios that are potentially confusing
or difficult to debug, this commit rejects identical bean overrides in
the Spring TestContext Framework.
Note, however, that it is still possible for a bean override to
override a logically equivalent bean override. For example, a
@TestBean can override a @MockitoBean, and vice versa.
Closes gh-34054
This metadata information is required for supporting libraries using
`sun.misc.Unsafe#allocateInstance(Class<?>)`, even though Spring
Framework is not using this feature.
Closes gh-34055
To make an analogy to read phenomena for transactional databases, this
commit effectively fixes the "Phantom Read" problem for Bean Overrides.
A phantom read occurs when the BeanOverrideBeanFactoryPostProcessor
retrieves a set of bean names by-type twice and a new bean definition
for a compatible type has been created in the BeanFactory by a
BeanOverrideHandler between the first and second retrieval.
Continue reading for the details...
Prior to this commit, the injection of test Bean Overrides (for
example, when using @MockitoBean) could fail in certain scenarios if
overrides were created for nonexistent beans "by type" without an
explicit name or qualifier. Specifically, if an override for a SubType
was created first, and subsequently an attempt was made to create an
override for a SuperType (where SubType extends SuperType), the
override for the SuperType would "override the override" for the
SubType, effectively removing the override for the SubType.
Consequently, injection of the override instance into the SubType field
would fail with an error message similar to the following.
BeanNotOfRequiredTypeException: Bean named 'Subtype#0' is expected to
be of type 'Subtype' but was actually of type 'Supertype$Mock$XHb7Aspo'
This commit addresses this issue by tracking all generated bean names
(in a generatedBeanNames set) and ensuring that a new bean override
instance is created for the current BeanOverrideHandler if a previous
BeanOverrideHandler already created a bean override instance that now
matches the type required by the current BeanOverrideHandler.
In other words, if the generatedBeanNames set already contains the
beanName that we just found by-type, we cannot "override the override",
because we would lose one of the overrides. Instead, we must create a
new override for the current handler. In the example given above, we
must end up with overrides for both SuperType and SubType.
Closes gh-34025
This commit restores the user class in generated RootBeanDefinition
instances. Previously the CGLIB subclass was exposed. While this is
important in regular runtime as the configuration class parser operates
on the bean definition, this is not relevant for AOT as this information
is internal and captured in the instance supplier.
Closes gh-33960
This commit fixes a regression in PlaceHolderParser where it would no
longer resolve nested placeholders for a case where the fallback has a
placeholder itself.
This is due to the Part implementations and how they are structure, and
this commit makes sure that nested resolution happens consistently.
Closes gh-34020
This commit restores the signature of instance suppliers that are
exposing a CGLIB proxy. While calling the CGLIB proxy itself, and
making it available in BeanInstanceSupplier, is needed internally, such
type should not be exposed as it is an internal concern.
This was breaking InstanceSupplier.andThen as it expects the public
type of the bean to be exposed, not it's eventual CGLIB subclass.
Closes gh-33998
Prior to this commit, the equals() implementation in AdvisedSupport's
MethodCacheKey only considered methods to be equal based on an identity
comparison (`==`), which led to duplicate entries in the method cache
for the same logical method.
This is caused by the fact that AdvisedSupport's
getInterceptorsAndDynamicInterceptionAdvice() method is invoked at
various stages with different Method instances for the same method:
1) when creating the proxy
2) when invoking the method via the proxy
The reason the Method instances are different is due to the following.
- Methods such as Class#getDeclaredMethods() and
Class#getDeclaredMethod() always returns "child copies" of the
underlying Method instances -- which means that `equals()` should be
used instead of (or in addition to) `==` whenever the compared Method
instances can come from different sources.
With this commit, the equals() implementation in MethodCacheKey now
considers methods equal based on identity or logical equality, giving
preference to the quicker identity check.
See gh-32586
Closes gh-33915
Prior to this commit, the reactive Scheduled tasks would be wrapped as a
`SubscribingRunnable` which does not implement a custom `toString`. This
would result in task metadata using the default Java `toString`
representation for those.
This commit ensures that the bean class name and method name are used
for this `toString`.
Closes gh-34010
This commit introduces a test which verifies how many times the
matches() method of a StaticMethodMatcherPointcut is invoked during
ApplicationContext startup as well as during actual method invocations
via the advice chain, which also indirectly tests the behavior of the
equals() implementation in AdvisedSupport.MethodCacheKey.
In addition, this commit revises BeanFactoryTransactionTests to assert
that a transaction is started for the setAge() method.
See gh-33915
As a follow up to commit 0088b9c7f8, this commit introduces an
integration test which verifies that a spy created via @MockitoSpyBean
using the MockReset.AFTER strategy is not reset between the refresh of
the ApplicationContext and the first use of the spy within a @Test
method.
See gh-33941
See gh-33986
Before this commit, in Spring Framework 6.2, Kotlin value class
unboxing was done at CoroutinesUtils level, which is a good fit
for InvocableHandlerMethod use case, but not for other ones like
AopUtils.
This commit moves such unboxing to InvocableHandlerMethod in
order to keep the HTTP response body support while fixing other
regressions.
Closes gh-33943
The log message for a NoClassDefFoundError is now a DEBUG level message
handled like a TypeNotPresentException and similar to the following.
DEBUG: Skipping validation constraint hint inference for class
org.example.CustomConstraint due to a NoClassDefFoundError for
com.example.MissingType
See gh-33949
Prior to this commit, AOT processing for bean validation failed with a
NoClassDefFoundError for constraints with missing dependencies.
With this commit, the processing no longer fails, and a warning is
logged instead.
See gh-33940
Closes gh-33949
Co-authored-by: Sam Brannen <sam.brannen@broadcom.com>
Commit 6c2cba5d8a introduced a regression by inadvertently removing the
MockReset strategy comparison when resetting @MockitoBean and
@MockitoSpyBean mocks.
This commit reinstates the MockReset strategy check and introduces
tests for this feature.
Closes gh-33941
Prior to this commit, AOT processing for bean validation failed with a
StackOverflowError for constraints with fields having recursive generic
types.
With this commit, the algorithm tracks visited classes and aborts
preemptively when a cycle is detected.
Closes gh-33950
Co-authored-by: Sam Brannen <sam.brannen@broadcom.com>
Prior to this commit, `RestClient` would not use the full URI created by
the uri handler as a template request attribute.
This means that HTTP client observations would not contain the base URI
in recorded observations as the uri template keyvalue.
Closes gh-33928
This commit makes it clear that there are no visibility requirements
for @TestBean fields or factory methods as well as @MockitoBean or
@MockitoSpyBean fields.
Closes gh-33923
For Reactor Netty and Reactor Netty 2 (with Netty 5), the attributes are
stored as an `Attribute` on the netty channel. Reactor Netty replaces
the channel with a static placeholder one once the request has been
processed and as such, capturing the native request in the test will
lead to asserting an attribute-less channel.
This change switches to capturing the `Attribute` itself, which is a
value-holder that can be asserted later on.
Closes gh-33909
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.
Closes gh-33885
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
This commit introduces support for bean validation container
element constraints, including transitive ones.
Transitive constraints in the parameterized types of a container
are not discoverable via the BeanDescriptor, so a complementary
type discovery is done on Spring side to cover the related use
case.
Closes gh-33842
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
* pr/33850:
Polish "Prefer modified resources over the originals in TestCompiler"
Prefer modified resources over the originals in TestCompiler
Closes gh-33850
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
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
This commit introduces a TestBeanReflectiveProcessor that registers
GraalVM native image reflection hints for a fully-qualified method name
configured via @TestBean.
Closes gh-33836
Prior to this commit, the static factory methods in MockReset (such as
MockReset.before() and MockReset.after()) could only be applied to
beans within the ApplicationContext if the test class declared at least
one field annotated with either @MockitoBean or @MockitoSpyBean.
However, the Javadoc states that it should be possible to apply
MockReset directly to any mock in the ApplicationContext using the
static methods in MockReset.
To address that, this commit reworks the "enabled" logic in
MockitoResetTestExecutionListener as follows.
- We no longer check for the presence of annotations from the
org.springframework.test.context.bean.override.mockito package to
determine if MockReset is enabled.
- Instead, we now rely on a new isEnabled() method to determine if
MockReset is enabled.
The logic in the isEnabled() method still relies on the mockitoPresent
flag as an initial check; however, mockitoPresent only determines if
Mockito is present in the classpath. It does not determine if Mockito
can actually be used. For example, it does not detect if the necessary
reachability metadata has been registered to use Mockito within a
GraalVM native image.
To address that last point, the isEnabled() method performs an
additional check to determine if Mockito can be used in the current
environment. Specifically, it invokes Mockito.mockingDetails().isMock()
which in turn initializes core Mockito classes without actually
attempting to create a mock. If that fails, that means that Mockito
cannot actually be used in the current environment, which typically
indicates that GraalVM reachability metadata has not been registered
for the org.mockito.plugins.MockMaker in use (such as the
ProxyMockMaker).
In addition, isEnabled() lazily determines if Mockito can be
initialized, since attempting to detect that during static
initialization results in a GraalVM native image error stating that
Mockito internals were "unintentionally initialized at build time".
If Mockito cannot be initialized, MockitoResetTestExecutionListener
logs a DEBUG level message providing access to the corresponding stack
trace, and MockReset support is disabled.
Closes gh-33829
This commit verifies that MockReset.before() and MockReset.after() are
supported for beans within the ApplicationContext.
However, the test class must declare a field annotated with either
@MockitoBean or @MockitoSpyBean in order for the MockReset feature to
be triggered.
See gh-33742
Spring Boot has honored @Primary for selecting which candidate bean
@MockBean and @SpyBean should mock or spy since Spring Boot 1.4.3;
however, the support for @Primary was not ported from Spring Boot to
Spring Framework's new Bean Overrides feature in the TestContext
framework.
To address that, this commit introduces support for @Primary for
selecting bean overrides -- for example, for annotations such as
@TestBean, @MockitoBean, and @MockitoSpyBean.
See https://github.com/spring-projects/spring-boot/issues/7621
Closes gh-33819
This commit introduces a `@CheckReturnValue` annotation,
inspired from org.jetbrains.annotations.CheckReturnValue,
that specifies that the method return value must be used.
See gh-33818
This commit introduces integration tests which verify that Bean
Overrides (for example, @MockitoBean and @MockitoSpyBean) can select
a single candidate bean to override when there are multiple candidates
that match the required type.
To "select" the desired bean, these tests rely on one of the following.
- explicit bean name in the bean override annotation
- explicit @Qualifier on the bean override field
- explicit @Primary on one of the candidate beans
However, the @Primary tests are currently @Disabled until @Primary
is honored in the Spring TestContext Framework.
See gh-33742
Previously, we only looked at the OBJECT_TYPE_ATTRIBUTE on a
FactoryBean's bean definition; however this does not work for
situations where the information is provided by the definition's target
type rather than the attribute.
Rather than manually considering the target type in addition to the
existing consideration of the attribute, we now ask the BeanFactory for
the type that will be produced by the FactoryBean instead.
See https://github.com/spring-projects/spring-boot/issues/40234
Closes gh-33811
Co-authored-by: Andy Wilkinson <andy.wilkinson@broadcom.com>
This commit introduces a test which verifies that @MockitoSpyBean on a
field with generics can be used to replace an existing bean with
matching generics that's produced by a FactoryBean that's
programmatically registered via an ImportBeanDefinitionRegistrar.
However, the test is currently @Disabled until the fix for
https://github.com/spring-projects/spring-boot/issues/40234 has been
ported to Spring Framework.
See gh-33742
In gh-33602, we introduced strict singleton enforcement for bean
overrides -- for example, for @MockitoBean, @TestBean, etc. However,
the use of BeanFactory#isSingleton(beanName) can result in a
BeanCreationException for certain beans, such as a Spring Data JPA
FactoryBean for a JpaRepository.
In light of that, this commit relaxes the singleton enforcement in
BeanOverrideBeanFactoryPostProcessor by only checking the result of
BeanDefinition#isSingleton() for existing bean definitions.
This commit also updates the Javadoc and reference documentation to
reflect the status quo.
See gh-33602
Closes gh-33800
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
This commit removes the proxyTargetAware attribute from @MockitoSpyBean
while keeping the underlying feature in tact (i.e., transparent
verification for spies created via @MockitoSpyBean).
Closes gh-33775
Prior to this commit, SpringAopBypassingVerificationStartedListener
provided partial support for transparent verification for Mockito spies
created via @MockitoSpyBean when the spy is wrapped in a Spring AOP
proxy. However, attempting to actually verify invocations for a spy
resulted in an exception from Mockito since MockUtil.isMock() returned
false in such scenarios.
This commit addresses that by introducing a SpringMockResolver that
resolves mocks by walking the Spring AOP proxy chain until the target
or a non-static proxy is found.
SpringMockResolver is automatically registered whenever the spring-test
JAR is on the classpath, allowing Mockito to transparently resolve mocks
wrapped in Spring AOP proxies.
Closes gh-33774
This commit removes all references to the Resin Servlet container, as it
is not supported as of Spring Framework 6.0 because we require a
JakartaEE baseline.
Closes gh-33772
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
Update `PathMatchingResourcePatternResolver` so that in addition to
searching the `java.class.path` system property for classpath enties,
it also searches the `MANIFEST.MF` files from within those jars.
Prior to this commit, the `addClassPathManifestEntries()` method
expected that the JVM had added `Class-Path` manifest entries to the
`java.class.path` system property, however, this did not always happen.
The updated code now performs a deep search by loading `MANIFEST.MF`
files from jars discovered from the system property. To deal with
potential performance issue, loaded results are also now cached.
The updated code has been tested with Spring Boot 3.3 jars extracted
using `java -Djarmode=tools`.
See gh-33705
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
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
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
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
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
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
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
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
This new interface is not strictly necessary and introduces a binary
incompatibility. This commit merges back all the method definitions into
`SseBuilder` and `StreamBuilder` interfaces.
Closes gh-33736
This commit refines the contribution with the following changes:
- Move the support to findPrimaryConstructor
- Use a for loop instead of a Stream for more efficiency
- Support other visibilities than public
- Polishing
Closes gh-33707
Prior to this commit, OverrideMetadata was the only public type in the
org.springframework.test.context.bean.override package whose name did
not start with BeanOverride. In addition, an OverrideMetadata component
plays multiple roles in addition to serving as a holder for metadata.
This commit therefore renames OverrideMetadata to BeanOverrideHandler.
In addition, this commit updates the affected documentation and renames
the following related methods in the Bean Override support.
- BeanOverrideHandler: createOverride() -> createOverrideInstance()
- BeanOverrideHandler: track() -> trackOverrideInstance()
- BeanOverrideProcessor: createMetadata() -> createHandler()
- BeanOverrideContextCustomizer: getMetadata() -> getBeanOverrideHandlers()
- BeanOverrideRegistrar: registerNameForMetadata() -> registerBeanOverrideHandler()
- BeanOverrideRegistrar: markWrapEarly() -> registerWrappingBeanOverrideHandler()
Closes gh-33702
See gh-33715
```
Map has no value for 'thescheme'
java.lang.IllegalArgumentException: Map has no value for 'thescheme'
at org.springframework.web.util.UriComponents$MapTemplateVariables.getValue(UriComponents.java:348)
at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:263)
at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:436)
at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:53)
at org.springframework.web.util.UriComponents.expand(UriComponents.java:161)
at org.springframework.web.util.UriComponentsBuilder.buildAndExpand(UriComponentsBuilder.java:364)
```
This change remove the support for Mockito annotations, `MockitoSession`
and opening/closing of mocks that was inherited from Boot's `@MockBean`
support, as well as the switch to `MockitoSession` made in 1c893e6.
Attempting to take responsability for things Mockito's own JUnit
Jupiter extension does better is not ideal, and we found it leads to
several corner cases which make `SpringExtension` and `MockitoExtension`
incompatible in the current approach.
Instead, this change refocuses our Mockito bean overriding support
exclusively on aspects specific to the Framework. `MockitoExtension`
will thus be usable in conjunction with `SpringExtension` if one needs
to use `@Captor`/`@InitMocks`/`@Mock`/`@Spy` or other Mockito utilities.
See gh-33318
Closes gh-33692
Prior to this commit, our XML parser usage would be already haredened
against XXE (XML External Entities) attacks. Still, we recently received
several invalid security reports claiming that our setup should be
hardened.
This commit documents a few usages of XML parsers to add some more
context and hopefully prevent future invalid reports.
Closes gh-33713
Because Spring Framework already has a security policy, this shows up in
the issue template automatically. This commit removes the extra external
link and updates the original security policy.
See gh-33711
Prior to this commit, this repository had a single issue template
markdown file that listed all the information for creating a new issue
in this project. Because there was a lot, people missed warnings against
creating security reports publicly or asking questions in the issue
tracker.
This commit introduces an issue template configuration that provides
developers with a choice before creating the actual issue.
Closes gh-33711
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
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
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
Prior to this commit, the MockitoResetTestExecutionListener failed to
reset mocks created via @MockitoBean if the @MockitoBean field was
declared in an enclosing class for a @Nested test class. In addition,
the MockitoSession was not properly managed by the
MockitoTestExecutionListener.
This commit addresses those issue as follows.
1) The hasMockitoAnnotations() utility method has been overhauled so
that it finds Mockito annotations not only on the current test class
and on fields of the current test class but also on interfaces,
superclasses, and enclosing classes for @Nested test classes as well
as on fields of superclasses and enclosing classes.
That allows the MockitoResetTestExecutionListener to properly detect
that it needs to reset mocks for fields declared in enclosing classes
for @Nested classes.
2) MockitoTestExecutionListener has been revised so that it only
initializes a MockitoSession before each test method and closes the
MockitoSession after each test method. In addition, it now only manages
the MockitoSession when hasMockitoAnnotations() returns true for the
current test class (which may be a @Nested test class). Furthermore,
it no longer attempts to initialize a MockitoSession during the
prepareTestInstance() callback since that results in an
UnfinishedMockingSessionException for a @Nested test class due to the
fact that a MockitoSession was already created for the current thread
for the enclosing test class.
Closes gh-33676
This commit improves the user experience for common use cases by
introducing new `value` attributes in @MockitoBean and
@MockitoSpyBean that are aliases for the existing `name` attributes.
For example, this allows developers to declare
@MockitoBean("userService") instead of @MockitoBean(name =
"userService"), analogous to the existing name/value alias support in
@TestBean.
Closes gh-33680
Based on feedback from the Spring Boot team, we have decided to change
the default values for the enforceOverride flags in @TestBean and
@MockitoBean from true to false.
Closes gh-33613
This commit simplifies the field injection logic for Bean Overrides in
order to align with the semantics of the core container and the Spring
TestContext Framework.
Closes gh-33677
This change avoids the trap of creating a copy of `HttpHeaders` using a
case-sensitive `MultiValueMap` by mistake. Since mutability is always
desirable, we make a mutable copy by using `addAll` on an empty
`HttpHeaders`.
We can't simply rely on HttpHeaders' map-based constructor to detect
read-only header in this particular case, because the container's
original headers representation might in some cases be read-only.
Closes gh-33666
This set of commits introduces AOT and native image support for the new
Bean Override feature in the Spring TestContext Framework -- for
example, for using @TestBean and @MockitoBean in AOT mode on the JVM
as well as in a GraalVM native image.
Note, however, that @MockitoBean has currently only been tested in a
native image when mocking interfaces and using Mockito's
ProxyMockMaker, along with a custom runtime hints.
Closes gh-32933
Instead, MockitoResetTestExecutionListener is now only enabled if the
current test class uses Mockito annotations or Mockito-related
annotations in spring-test.
See gh-32933
This commit introduces a BeanOverrideReflectiveProcessor which
registers runtime hints for any BeanOverrideProcessor configured
via @BeanOverride.
See gh-32933
Prior to this commit, AOT processing failed for tests that made use of
the Bean Override feature to "override" a nonexistent bean. The reason
is that we register a "pseudo" bean definition as a placeholder for a
nonexistent bean, and our AOT support cannot automatically convert that
"pseudo" bean definition to a functional bean definition for use at AOT
runtime.
To address that, this commit skips registration of "pseudo" bean
definitions during AOT processing, and by doing so we enable the JVM
runtime and AOT runtime to operate with the same semantics.
See gh-32933
Prior to this commit, AOT processing failed for tests that made use of
the Bean Override feature, since the Set<OverrideMetadata> constructor
argument configured in the bean definition for the
BeanOverrideBeanFactoryPostProcessor cannot be properly processed by
our AOT support. The reason is that each OverrideMetadata instance is
effectively an arbitrary object graph that cannot be automatically
converted to a functional bean definition for use at AOT runtime.
To address that, this commit registers Bean Override infrastructure
beans as manual singletons instead of via bean definitions with the
infrastructure role.
See gh-32933
An example of this can be found in RFC 2732, but it is obsoleted by
RFC 3986 whose syntax for IPv6address does not allow dots.
Also, Appendix D of RFC 3986:
As [RFC2732] defers to [RFC3513] for definition of an IPv6 literal
address, which, unfortunately, lacks an ABNF description of
IPv6address, we created a new ABNF rule for IPv6address that matches
the text representations defined by Section 2.2 of [RFC3513].
See gh-33639
This commit simplifies the implementation of
BeanOverrideTestExecutionListener by introducing a static
injectFields() utility method and removing the use of BiConsumers,
records, and duplicated code.
This commit also introduces Javadoc for all methods in
BeanOverrideTestExecutionListener.
Closes gh-33660
Replaced the hardcoded '/' path separator with the `PATH_SEPARATOR` constant
to improve code readability and maintainability. This change ensures
consistency across the codebase when handling path separators.
Closes gh-33646
The commit skips using UndeclaredThrowableStrategy for
Kotlin classes in CglibAopProxy in order to fix a
related regression caused by gh-32469.
See gh-33585
Prior to this commit, ApplicationContext caching support was broken if
two Bean Override fields declared the same annotations but in a
different order.
This commit fixes that by switching to Set semantics for the
annotations declared on a Bean Override field.
Closes gh-33633
Prior to this commit, the SockJs server support would use
`java.util.Random` to send a random value to clients when they request
the `/info` endpoint. Per protocol, clients can use this value as a
source of entropy for generating a random session id.
In practice, this is not used by clients. For example, the SockJS
javascript client is using a cryptographically safe API to generate
session ids.
While this has no concrete effect on known clients, this commit improves
the random source in the server support by switching to
`java.security.SecureRandom`.
Closes gh-33632
Prior to this commit, BeanOverrideBeanFactoryPostProcessor replaced
existing bean definitions with "pseudo" bean definitions; however, that
is unnecessary. An existing BeanDefinition is suitable as-is and does
not need to be replaced with a pseudo/fake definition.
To address that, this commit reregisters an existing bean definition
and only registers a new bean definition when creating a bean
definition for a nonexistent bean.
As a side effect, we no longer need to copy primary and fallback flags.
Closes gh-33627
Prior to this commit, @MockitoBean could be used to either create or
replace a bean definition, but @TestBean could only be used to replace
a bean definition.
However, Bean Override implementations should require the presence of
an existing bean definition by default (i.e. literally "override" by
default), while giving the user the option to have a new bean
definition created if desired.
To address that, this commit introduces a new `enforceOverride`
attribute in @TestBean and @MockitoBean that defaults to true but
allows the user to decide if it's OK to create a bean for a nonexistent
bean definition.
Closes gh-33613
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
Prior to this commit, a non-singleton FactoryBean was silently replaced
by a singleton bean. In addition, bean definitions for prototype-scoped
and custom-scoped beans were replaced by singleton bean definitions
that were incapable of creating the desired bean instance. For example,
if the bean type of the original bean definition was a concrete class,
an attempt was made to invoke the default constructor which either
succeeded with undesirable results or failed with an exception if the
bean type did not have a default constructor. If the bean type of the
original bean definition was an interface or a FactoryBean that claimed
to create a bean of a certain interface type, an attempt was made to
instantiate the interface which always failed with a
BeanCreationException.
To address the aforementioned issues, this commit reworks the logic in
BeanOverrideBeanFactoryPostProcessor so that an exception is thrown
whenever an attempt is made to override a non-singleton bean.
Closes gh-33602
New NoTransactionInContextException instances are created frequently in
TransactionContextManager#currentContext() when there is no transaction,
we could reuse the same instance instead to reduce the GC pressure.
Closes gh-33601
The tests introduced in this commit reveal the following issues in our
Bean Override support.
- If a FactoryBean signals it does not manage a singleton, the Bean
Override support silently replaces it with a singleton.
- An attempt to override a prototype-scoped bean or a bean configured
with a custom scope results in one of the following.
- If the bean type of the original bean definition is a concrete
class, an attempt will be made to invoke the default constructor
which will either succeed with undesirable results or fail with an
exception if the bean type does not have a default constructor.
- If the bean type of the original bean definition is an interface or
a FactoryBean that claims to create a bean of a certain interface
type, an attempt will be made to instantiate the interface which
will always fail with a BeanCreationException.
In order to allow third parties (for example, Spring Boot) to ensure
that a DynamicPropertyRegistrarBeanInitializer has been registered in
an ApplicationContext which has not been customized by the
DynamicPropertiesContextCustomizer, this commit converts
DynamicPropertyRegistrarBeanInitializer to a public API for use in such
special use cases.
Closes gh-33593
Previously, a timeout was set both on HttpRequest, and used on
httpClient.sendAsync().get(). This leads to inconsistent behaviour
depending on which timeout gets triggered first.
See gh-33090
Align internal handling and contracts. The core copy could do without
those contracts, but it helps with alignment, and it's internal to
the implementation.
Closes gh-33592
This commit adds a new
AbstractGenericHttpMessageConverter(Charset, MediaType...)
constructor, similar to the one present in
AbstractHttpMessageConverter.
Closes gh-33563
Includes consistent withShortcut naming and consistent bean definition flag exposure.
Removes support for inner classes in alignment with standard core container behavior.
Closes gh-32834
This commit introduces example support for a custom @EasyMockBean
annotation that allows tests to use EasyMock as the mocking framework
for bean overrides in a test's ApplicationContext.
The point of this exercise is to ensure that it is possible for third
parties to introduce bean override support for mocking frameworks other
than Mockito, and that they can do so with the APIs currently in place.
Closes gh-33562
This commit adds support for HttpComponentsClientHttpRequestFactory to
set a read timeout, used on the underlying client as a RequestTimeout.
This brings the HttpComponentsClientHttpRequestFactory into alignment
with JDK, Jetty, OkHttp3, Reactor and SimpleClient
ClientHttpRequestFactory implementations.
See gh-33556
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
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
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
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
Spring Boot's testing support registers a DynamicPropertyRegistry as a
bean in the ApplicationContext, which conflicts with the
DynamicPropertyRegistry registered as a bean by the Spring TestContext
Framework (TCF) since Spring Framework 6.2 M2.
To avoid that conflict and to improve the user experience for Spring's
testing support, this commit introduces a DynamicPropertyRegistrar API
to replace the DynamicPropertyRegistry bean support.
Specifically, the TCF no longer registers a DynamicPropertyRegistry as
a bean in the ApplicationContext.
Instead, users can now register custom implementations of
DynamicPropertyRegistrar as beans in the ApplicationContext, and the
DynamicPropertiesContextCustomizer now registers a
DynamicPropertyRegistrarBeanInitializer which eagerly initializes
DynamicPropertyRegistrar beans and invokes their accept() methods with
an appropriate DynamicPropertyRegistry.
In addition, a singleton DynamicValuesPropertySource is created and
registered with the Environment for use in
DynamicPropertiesContextCustomizer and
DynamicPropertyRegistrarBeanInitializer, which allows
@DynamicPropertySource methods and DynamicPropertyRegistrar beans to
transparently populate the same DynamicValuesPropertySource.
Closes gh-33501
Prior to this commit, MVC function endpoints would allow Server Sent
Event responses through `ServerResponse.sse()`. While this covers a
common use case for streaming responses, other technologies would
benefit from a "low-level", unopinionated streaming support.
This commit introduces a new `BodyBuilder.stream()` methods that enables
such use cases. Developers are in charge of setting the relevant HTTP
response headers beforehand, and then can write to the response as raw
`String`, `byte[]` or using complex objects and the configured message
converters for serialization.
Because each streaming protocol has different message separator
semantics, it is also the developers' responsibility to flush buffered
content to the network once a message has been fully written.
Closes gh-32710
This aligns HttpHeaders with other places like ServletWebRequest and
DefaultWebExchange where an ETag is accepted as input.
It also allows us to remove quoting from places that delegate to
HttpHeaders#setETag since it now does that internally.
Closes gh-33412
Update checks whether quoting is needed to be more complete
than what we've used so far, making sure the there is both
opening and closing quotes independent of each other.
See gh-33412
This commit exposes the unexpanded URI template used to build a
MockHttpServletRequest. This allows MockMvc users to retrieve that
information, in consistency with ExchangeResult in WebTestClient.
Closes gh-33509
Since we now use asciidoctor-tabs instead of spring-asciidoctor-backends,
we no longer need the `role="primary"` and `role="secondary"` attributes
for tab groups.
Closes gh-33506
Prior to this commit, `ResponseBodyEmitter` woud accept a single
`Runnable` callback on each of its `onTimeout`, `onError` or
`onCompletion` methods. This would limit the developers' ability to
register multiple sets of callbacks: one for managing the publication of
streaming values, another one for managing other concerns like
keep-alive signals to maintain the connection.
This commit now allows multiple calls to `onTimeout`, `onError` and
`onCompletion` and will register all callbacks accordingly.
Closes gh-33356
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.
This commit revises the reference documentation for Spring JMX
annotations for various reasons including, but not limited to, the
following.
- Type names such as ManagedResource are often ambiguous, especially
when discussing an annotation like @ManagedResource instead of
org.springframework.jmx.export.metadata.ManagedResource which is a
class.
- AnnotationTestBean implements IJmxTestBean, even though an annotated
MBean is not required to implement any interfaces, and in fact the
example is meant to demonstrate that an annotated POJO suffices.
- @ManagedOperationParameter annotations are unnecessarily declared in
the @ManagedOperationParameters container.
- The documentation sometimes refers to JmxTestBean when it should
instead refer to AnnotationTestBean.
- Inconsistent and confusing wording for annotation attributes,
properties, managed attributes, etc.
- The tables refer to "source-level metadata types/parameters" when
they should refer to Spring JMX annotations and their attributes.
- The annotation and attribute tables have inconsistent ordering and
naming for column headers.
- @ManagedNotification and @ManagedMetric are not mentioned.
- The AutodetectCapableMBeanInfoAssembler example is broken since it
uses the non-annotated JmxTestBean instead of the AnnotationTestBean.
As a side note, the JmxTestBean in our test suite still contains
XDoclet "annotations" which can be safely removed. 😉
Closes gh-33466
Prior to this commit, the HTTP interceptor model used for `RestTemplate`
and `RestClient` would not update the "Content-Length" request header,
even when the request body had been updated by a
`ClientHttpRequestInterceptor`.
Even though this is the `ClientHttpRequestInterceptor`'s responsibility
(along with the content type and encoding changes if needed), this
would result in invalid requests. This invalid situation can be detected
by `InterceptingClientHttpRequest`.
This commit ensures that such situations are detected and fixed
automatically by setting the Content-Length header to the actual body
size, right before executing the actual request, after all interceptors
are done.
Closes gh-33459
This commit ensures that the `UrlHandlerFilter` does not handle "/"
paths in general, as they should not be altered and are meaningful for
web applications.
Closes gh-33444
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
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
This commit revises the AOP proxying section as follows.
- Documents all limitations of CGLIB-based proxies
- Documents self injection as alternative to AopContext.currentProxy()
- Avoids use of flippant language
See gh-33454
Closes gh-33455
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
Prior to this commit, when ReflectionTestUtils was used to invoke a
method on a CGLIB proxy, the invocation was always performed directly
on the proxy. Consequently, if the method was not proxied/intercepted
by the CGLIB proxy -- for example, if the method was final or
effectively private -- the invoked method could not operate on the
state of the target object or interact with other private methods in
the target object.
With this commit, if the supplied target object is a CGLIB proxy which
does not intercept the method, the proxy will be unwrapped allowing the
method to be invoked directly on the ultimate target of the proxy.
Closes gh-33429
Commit 47f88e123f introduced support for invoking init/destroy/SpEL
methods via public types whenever possible. To achieve that,
getInterfaceMethodIfPossible() was modified so that it only returned
interface methods from public interfaces; however, we have learned that
third parties relied on the previous behavior which found any interface
method (even in non-public interfaces).
In light of the above, this commit partially reverts commit 47f88e123f
in order to reinstate getInterfaceMethodIfPossible() in non-deprecated
form with its previous behavior.
See gh-33216
Prior to this commit, when invoking init methods and destroy methods
for beans as well as methods within Spring Expression Language (SpEL)
expressions via reflection, we invoked them based on the "interface
method" returned from ClassUtils.getInterfaceMethodIfPossible(). That
works well for finding methods defined in an interface, but it does not
find public methods defined in a public superclass.
For example, in a SpEL expression it was previously impossible to
invoke toString() on a non-public type from a different module. This
could be seen when attempting to invoke toString() on an unmodifiable
list created by Collections.unmodifiableList(...). Doing so resulted in
an InaccessibleObjectException.
Although users can address that by adding an appropriate --add-opens
declaration, such as --add-opens java.base/java.util=ALL-UNNAMED, it is
better if applications do not have to add an --add-opens declaration
for such use cases in SpEL. The same applies to init methods and
destroy methods for beans.
This commit therefore introduces a new
getPubliclyAccessibleMethodIfPossible() method in ClassUtils which
serves as a replacement for getInterfaceMethodIfPossible().
This new method finds the first publicly accessible method in the
supplied method's type hierarchy that has a method signature equivalent
to the supplied method. If the supplied method is public and declared
in a public type, the supplied method will be returned. Otherwise, this
method recursively searches the class hierarchy and implemented
interfaces for an equivalent method that is public and declared in a
public type. If a publicly accessible equivalent method cannot be
found, the supplied method will be returned, indicating that no such
equivalent method exists.
All usage of getInterfaceMethodIfPossible() has been replaced with
getPubliclyAccessibleMethodIfPossible() in spring-beans and
spring-expression. In addition, getInterfaceMethodIfPossible() has been
marked as deprecated in favor of the new method.
As a bonus, the introduction of getPubliclyAccessibleMethodIfPossible()
allows us to delete a fair amount of obsolete code within the SpEL
infrastructure.
See gh-29857
Closes gh-33216
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
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
This change adds 3 protected methods to `AbstractCacheInvoker` that wrap
additional `Cache#retrieve` and `Cache#get` calls with
`handleCacheGetError` in case the Cache call itself fails.
For example, if the cache is remote and a connection to it cannot be
established.
Closes gh-21590
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
On the client side, supports `name=value` pairs. Placeholders in values
are resolved by the `embeddedValueResolver`.
On the server side, additionally supports `name` and `!name` syntax.
Closes gh-33309
Based on feedback from htmx-spring-boot. It's more generally useful
to process those from within DefaultFragmentsRendering rather than
in ModelAndViewMethodReturnValueHandler. That way a custom
return value handler can create a FragmentsRendering as well and
get the same result.
See gh-33194
Thymeleaf has its own special handling for SSE that gets in the way
of fragment rendering. This is why we need to set the response
content-type before streaming, and then pass text/html to the
View for rendering each fragment.
See gh-33194
This commit revises QualifierAnnotationAutowireCandidateResolver to
reinstate "qualifier" support for the legacy JSR-330
@javax.inject.Named annotation.
See gh-31090
Closes gh-33345
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
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
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
This commit updates JbcTemplate#batchUpdate to provide additional
information when one batch fails. Previously, the raw
BatchUpdateException was thrown with no way to know what had completed
thus far.
This commit creates an AggregatedBatchUpdateException that wraps the
original BatchUpdateException, yet providing the counters of the batches
that ran prior to the exception. In essence, this represents the same
state as the return value of the method if no batch fails.
AggregateBatchUpdateException exposes the original BatchUpdateException
in advanced case, such as checking for a sub-class that may contain
additional information.
Closes gh-23867
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)
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.
This commit implements modifyContextPath in ServletRequestPath and
apply the same logic of concatenating the servlet path with the
context path.
Closes gh-33251
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
This commit changes the way the `MockitoTestExecutionListener` sets up
mockito, now using the `MockitoSession` feature. Additionally, stubbing
now defaults to a STRICT mode which can be overruled with a newly
introduced annotation: `@MockitoBeanSettings`.
Closes gh-33318
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
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
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
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
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
This commit makes sure that the programmatic exception that is thrown
by the cache abstraction uses the same message structure as a default
message produced by NoUniqueBeanDefinitionException.
Closes gh-33305
Follow-up to d2225c, which broke Boot tests because the ServletContext can
be the one of the embedded Servlet container if initializing a live server
and as well as MockMvc (e.g. via `@AutoConfigureMockMvc`).
See gh-33252
This change adds several overloads of `MimeMessageHelper#addInline`
which allow users to specify a file name for inline elements added from
an `InputStreamResource` or a `jakarta.activation.DataSource`.
Closes gh-33230
Prior to this commit, the `DatabaseClient` interface would allow batch
operations for binding parameters by their names and values. Positional
parameters did not have such equivalent.
This commit adds a new `bindValues(List<?>)` method variant for adding
multiple positional arguments in a single call and avoiding allocation
overhead when the parameters count is large.
Closes gh-33274
This commit makes sure to check first if
DynamicPropertySourceBeanInitializer has been registered before trying
to register it.
When running with AOT optimizations, the bean definition has been
contributed so there is no need to register it again when the context
customizer runs.
Closes gh-33272
This commit review the support for AOT by only ignoring beans that are
using an instance supplier. The Kotlin DSL has a way to register a
bean by type where all inferences should happen as usual and that was
previously ignored.
This commit no longer ignores those beans so AOT can optimize them, and
makes sure that they are not registered again when running with AOT
optimizations. This change makes it so that the order in which beans are
registered is now different when running with AOT optimizations, and
we'll have to find a solution for that.
See gh-29555
This commit documents `ControllerAdviceBean` as internal usage, as it is
not meant for application to manually create controller advice bean
instances.
This also refactors the existing partial implementation of the support
for creating controller advice beans "programmatically".
Closes gh-32776
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
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
This commit adds AOT/Native support for beans that are contributed by
the Kotlin DSL.
Since they use an instance supplier, such beans are now configured to
be ignored by AOT generation. They are part of the bean factory still
so any hint generation works.
This commit removes a previous attempt at fixing this issue when we
were not checking for instance suppliers. Rather than skipping the
initializr at runtime, it runs again as intended since their state
can't be stored in AOT-generated code.
Closes gh-29555
This commits allows a particular bean definition to be excluded from
AOT processing using an attribute.
If BeanRegistrationAotProcessor#IGNORE_REGISTRATION_ATTRIBUTE is set
to `true`, then the bean definition is excluded. This complement the
existing BeanRegistrationExcludeFilter capability.
Closes gh-33243
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
This commit introduces a notion of different styles for the formatting
of Duration.
The `@DurationFormat` annotation is added to ease selection of a style,
which are represented as DurationFormat.Style enum, as well as a
supported time unit represented as DurationFormat.Unit enum.
DurationFormatter has been retroffited to take such a Style,
optionally, at construction. The default is still the JDK style a.k.a.
ISO-8601.
This introduces the new SIMPLE style which uses a single number + a
short human-readable suffix. For instance "-3ms" or "2h".
This has the same semantics as the DurationStyle in Spring Boot and
is intended as a replacement for that feature, providing access to the
feature to projects that only depend on Spring Framework.
Finally, the `@Scheduled` annotation is improved by adding detection
of the style and parsing for the String versions of initial delay, fixed
delay and fixed rate.
See gh-22013
See gh-22474
Closes gh-30396
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
* 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
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
* pr/33233:
Polish "Support JAXBElement in Jaxb2RootElementHttpMessageConverter"
Support JAXBElement in Jaxb2RootElementHttpMessageConverter
Closes gh-33233
Previous to this commit, MockHttpServletRequestBuilder was not binary
compatible as its methods had moved to a parent class with a generic
argument on the return type. MockMultipartHttpServletRequestBuilder
was also not source compatible as it no longed extended from
MockHttpServletRequestBuilder.
Both these changes were introduced to allow the AssertJ support to
expose builders that implement an extra AssertJ interface, without
copying the features the builders provide.
This commit restore compatibility. For MockHttpServletRequestBuilder
we simply override all methods that returns the generic type into
the resolved type.
MockMultipartHttpServletRequestBuilder is more involved. Because we
need to extend from MockHttpServletRequestBuilder, we have no other
choice than duplicating the code. For now, the abstract builder for
multipart is only used by the AssertJ support, but we can revisit this
again in a major release.
Closes gh-33229
This commit adapts code generation to "slice" the registration of bean
definitions in separate bean methods rather than a unique method for
all of them.
If the bean factory has more than a thousand bean, a method is created
for each slice of 1000 bean definitions.
Closes gh-33126
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
The internal ArgumentsMatchInfo type seems to have once had additional
methods beyond the functionality provided by the ArgumentsMatchKind
enum; however, that is no longer the case. Consequently, there is no
need to maintain both types.
This commit therefore merges the convenience methods from
ArgumentsMatchInfo into the ArgumentsMatchKind enum and removes the
unnecessary ArgumentsMatchInfo type.
This application/javascript MIME type is deprecated.
This commit therefore changes the MIME type mapping for *.js files from
application/javascript to text/javascript in order to align with
industry standards.
Closes gh-33197
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
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
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
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
This commit updates the "create-github-release" action to allow an
additional input that specifies whether this is a pre-release. If that
is the case, then the `--prerelease` flag is set.
Closes gh-33200
The result returned by Kotlin reflective invocation of a function
returning an inline value class is wrapped, which makes sense
from Kotlin POV but from a JVM perspective the associated value
and type should be unwrapped to be consistent with what
would happen with a reflective invocation done by Java.
This commit unwraps such result.
Closes gh-33026
This commit ensures that the varargs component type for a MethodHandle
cannot be null in ReflectionHelper's
convertAllMethodHandleArguments(...) method in SpEL.
Closes gh-33193
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
This commit improves SimpleInstantiationStrategy by providing a common
template method before the regular runtime and AOT. As a result, the
method to set the currently invoked factory method is deprecated as it
should no longer be used.
Closes gh-33192
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
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
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
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
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
FunctionReference in the Spring Expression Language (SpEL) currently
does not unwrap an InvocationTargetException; however,
ConstructorReference and MethodReference do.
For example, currently one may encounter an exception like the
following, where the 'null' comes from the fact that an
InvocationTargetException doesn't always have a message.
SpelEvaluationException: EL1023E: A problem occurred whilst attempting
to invoke the function 'formatObjectVarargs': 'null'
To address that, and to align with the behavior of ConstructorReference
and MethodReference, this commit modifies FunctionReference so that it
unwraps the InvocationTargetException to use its cause for the
exception message, resulting in an exception message like the following.
SpelEvaluationException: EL1023E: A problem occurred whilst attempting
to invoke the function 'formatObjectVarargs': 'Format specifier '%s''
Closes gh-33174
This provides an implementation of an HTTP Handler Adapter that is coded
directly to the Eclipse Jetty core API, bypassing any servlet
implementation.
This includes a Jetty implementation of the spring `WebSocketClient`
interface, `JettyWebSocketClient`, using an explicit dependency to the
jetty-websocket-api.
Closes gh-32097
Co-authored-by: Lachlan Roberts <lachlan@webtide.com>
Co-authored-by: Arjen Poutsma <arjen.poutsma@broadcom.com>
This commit mirrors toMap/toMessageHeaders with from factory methods
that allow to create an instance without having to create an
intermediate message if all they have is the headers.
Closes gh-33153
This commit allows `@Reflective` to be used on arbitrary types, not
only Spring beans. This makes the feature much more powerful as
components can be tagged directly.
Scanning happens during AOT processing (typically at build-time) when
`@ReflectiveScan` is used. Types do not need to have a particular
annotation, and types that can't be loaded are ignored.
This commit also exposes the infrastructure that does the scanning so
that custom code can do the scanning in an AOT contribution if they
don't want to rely on the annotation.
Closes gh-33132
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
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
This commit introduces a declarative way of registering reflection
information for arbitrary types. Types can be specified as a class,
a class name, or by annotating the type itself.
This existing RegisterReflectionForBinding becomes a specialized
version of the new annotation, registering the necessary hints for
data binding.
Closes gh-29194
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
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
This commit introduces an abstraction that allows to convert HTTP
inputs to a data type based on a set of HttpMessageConverter.
Previously, the AssertJ integration was finding the first converter
that is able to convert JSON to a Map (and vice-versa) and used that
in its API. With the introduction of SmartHttpMessageConverter, exposing
a specific converter is fragile.
The added abstraction allows for converting other kind of input than
JSON if we need to do that in the future.
Closes gh-33148
Prior to this commit, paths configured via the scripts attribute in
@Sql were required to be final paths without dynamic placeholders;
however, being able to make script paths dependent on the current
environment can be useful in certain testing scenarios.
This commit introduces support for property placeholders (${...}) in
@Sql script paths which will be replaced by properties available in
the Environment of the test's ApplicationContext.
Closes gh-33114
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
SmartHttpMessageConverter is similar to GenericHttpMessageConverter,
but more consistent with WebFlux Encoder and Decoder contracts, with
the following differences:
- A ResolvableType parameter is used instead of the Type one
- The MethodParameter can be retrieved via the ResolvableType source
- No contextClass parameter
- `@Nullable Map<String, Object> hints` additional parameter for write
and read methods
This commit also refines RestTemplate#canReadResponse in order to use
the most specific converter contract when possible.
Closes gh-33118
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
Prior to this commit, @TestBean factory methods had to be defined in
the test class, one of its superclasses, or in an implemented
interface. However, users may wish to define common factory methods in
external classes that can be shared easily across multiple test classes
simply by referencing an external method via a fully-qualified method
name.
To address that, this commit introduces support for referencing a
@TestBean factory method via its fully-qualified method name following
the syntax <fully-qualified class name>#<method name>.
Closes gh-33125
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
Prior to this commit, if ModelMap was used as an argument type in a
WebFlux controller method, the user encountered an exception similar to
the following.
java.lang.IllegalStateException: argument type mismatch
Controller [example.SampleController]
Method [java.lang.String example.SampleController.index(org.springframework.ui.ModelMap)] with argument values:
[0] [type=org.springframework.validation.support.BindingAwareConcurrentModel] [value={}]
However, the above error message is a bit cryptic since the error
occurs while attempting to invoke the controller method with an
instance of BindingAwareConcurrentModel which is not compatible with
ModelMap. More importantly, this error message does not explicitly
convey to the user that a ModelMap is not supported.
This commit improve the diagnostics for the user in such scenarios by
rejecting the use of ModelMap upfront in WebFlux.
Consequently, for the same use case as above, the user now encounters
an exception similar to the following.
java.lang.IllegalStateException:
Could not resolve parameter [0] in
java.lang.String example.SampleController.index(org.springframework.ui.ModelMap):
No suitable resolver
Closes gh-33109
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
According to the official FreeMarker documentation, Spring's
FreeMarkerView implementations should be configuring the
output_encoding for template rendering.
To address that, this commit modifies the FreeMarkerView
implementations in Web MVC and WebFlux to explicitly set the
output_encoding for template rendering.
See https://freemarker.apache.org/docs/pgui_misc_charset.html#autoid_53
See gh-33071
Closes gh-33106
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
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
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.
This commit replaces `@Nonnull(when = When.MAYBE)` meta-annotation in
org.springframework.lang.Nullable by `@CheckForNull` in order to
prevent "unknown enum constant When.MAYBE" compilation warnings.
IntelliJ IDEA 2024.1.2+ is required to interpret correctly the related
annotations.
Closes gh-27183
As pointed out in gh-33085, the `AntPatternComparator` hardcodes the "/"
separator when checking for "catch all" patterns like "/**".
This commit ensures that the custom path separator is used for those
checks, in order to guarantee consistent comparator results.
See gh-33085
This commit provides an advanced handling of generated files that
provides more control over files registration. The callback provides
a FileHandler that can determine if the file already exists and its
content. The caller can then chose to override the content or leave it
as it is.
Closes gh-31331
This commit restructures the section on MockMvc so that the anchors
are easier to read. The standard integration has moved to a
Hamcrest Integration section at the same level as HtmlUnit Integration,
and a new AssertJ Integration section has been created.
Closes gh-32454
This commit aligns code generation to recent improvement in the core
container regarding type detection. Now that nested types are properly
resolved, our code generation that uses hasResolvableGenerics() is
taking the wrong decision if only a nested type has an unresolved
generics. Previously, this was hidden by the fact that the core
container would not resolve them recursively.
A new hasResolvableGenerics() method allows to verify that at least
one direct generic type is resolved. This restore our intent of checking
at the first level only and let recursive invocations figure out if they
have to write the raw type or the type with generics.
Closes gh-33069
Before this commit, characters were always encoded with the default
encoding (i.e. ISO-8859-1). Now, the character encoding of the response
is used.
Closes gh-files
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
This commit makes MockHttpServletResponse consistent with the other
parts of the framework where the body of a response is read as an UTF-8
String when the content type is application/json or similar, overriding
the ISO-8859-1 default Servlet encoding.
Closes gh-33019
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
Prior to this commit, WebFlux had Protobuf codecs for managing the
`Message`/`"application/x-protobuf"` encoding and decoding.
The `com.google.protobuf:protobuf-java-util` library has additional
support for JSON (de)serialization, but this is not supported by
existing codecs.
This commit adds the new `ProtobufJsonEncode` and `ProtobufJsonDecoder`
classes that support this use case. Note, the `ProtobufJsonDecoder` has
a significant limitation: it cannot decode JSON arrays as
`Flux<Message>` because there is no available non-blocking parser able
to tokenize JSON arrays into streams of `Databuffer`. Instead,
applications should decode to `Mono<List<Message>>` which causes
additional buffering but is properly supported.
Closes gh-25457
This commit improves the handling of asynchronous requests by offering
a way to opt-in for the raw async result. This provides first class
support for asserting a request that might still be in process as well
as the asyncResult, if necessary.
See gh-33040
This commit makes asynchronous requests first class by providing a
MvcTestResult that represents the final, completed, state of a request
by default. Previously, the result was an intermediate step that may
require an ASYNC dispatch to be fully usable. Now it is de facto
immutable.
To make things a bit more explicit, an `.exchange(Duration)` method has
been added to provide a dedicated time to wait. The default applies a
default timeout that is consistent with what MVcResult#getAsyncResult
does.
Given that we apply the ASYNC dispatch automatically, the intermediate
response is no longer available by default. As a result, the asyncResult
is not available for assertions.
As always, it is possible to use plain MockMvc by using the `perform`
method that takes the regular RequestBuilder as an input. When this
method is invoked, no asynchronous handling is done.
Closes gh-33040
This commit simplifies the package private constructors on those two
builders now that the URI can be specified by dedicated builder methods.
Closes gh-33062
File uploads with MockMvc require a separate
MockHttpServletRequestBuilder implementation. This commit applies the
same change to support AssertJ on this builder, but for the multipart
version.
Any request builder can now use `multipart()` to "down cast" to a
dedicated multipart request builder that contains the settings
configured thus far.
Closes gh-33027
This commit simplifies assertions on MockMvc requests that have failed
to process. A now general hasFailed/doesNotHaveFailed/failure provides
the necessary to assert the exception.
Any attempt to access anything from the result with an unresolved
exception still fails as before.
Closes gh-33060
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
This commit replaces the use of EngineTestKit to test scenarios where
bean override could not process the test class. There is no need to
run an actual test for this as:
1. Regular integration tests are already validating that adding the
annotation triggers the processing as part of executing the test.
2. The entry point is a ContextCustomizer that can easily be invoked
in a regular test.
As part of harmonizing this, AbstractTestBeanIntegrationTestCase can
be nested, and BeanOverrideTestSuite serve no purpose. The tests can
be executed in an IDE without any special setup.
This commit harmonizes the class names of the bean override support by
using a consistent prefix for integration test, inspire from the one
that was used in Spring Boot
This commit revers the removal of the `private` keyword in the examples
of the reference documentation and the tests for consistency. While the
default visibility makes the example more concise, it could imply to the
reader that the field (or the factory method) cannot be private.
Also, there is no need to multiply anything returned from `Objects.hash`
as its very distinct on its own already.
This commit adds new information about the execution and scheduling of
tasks.
The `Task` type now exposes the `TaskExecutionOutcome` of the latest
execution; this includes the instant the execution started, the
execution outcome and any thrown exception.
The `ScheduledTask` contract can now provide the time when the next
execution is scheduled.
Closes gh-24560
This commit compiles our Protobuf against 4.27, effectively raising our
baseline to 3.9+.
This commit also re-generates all the Java messages from the .proto spec
using the latest protoc binary.
Closes gh-33011
This commit harmonizes the equals/hashCode behavior of OverrideMetadata
to always take the implementation class as a factor for its identity.
This is important as two OverrideMetadata implementations could use
the same strategy and other settings while creating the override value
in a totally different way. This commit makes sure they are identified
as different.
Closes gh-33005
This commit harmonizes how a candidate bean definition is determined
for overriding using `@TestBean`, `@MockitoBean`, and `@MockitoSpyBean`.
Previously, a qualifier was necessary even if the name of the annotated
field matches the name of a candidate. After this commit, such candidate
will be picked up transparently, the same it is done for regular
autowiring.
This commit also reviews the documentation of the feature as considering
the field means that its name is taken into account to compute a cache
key if by-type lookup is requested.
Closes gh-32939
This commit fixes a package tangle between the root bean override
package and its sub-packages. This was vastly improved with the
introduction of `@DummyBean` but we still had a few tests that were
at the wrong place.
This commit changes how factory method for `@TestBean` usage is
discovered. Previously the field name or bean name suffixed with
'TestOverride' was used. It sounds more natural to just use the
field name or bean name, leaving cases where a suffix is required
to explicitly providing the method name.
As part of this change, the exception messages have been revisited as
it's less since the method name candidates have the exact same name
as the field or bean name. A `()` is added to make it more clear the
name is for a method.
Closes gh-32940
TestOverrideMetadata was doing byName lookup by default, even without
a bean name. This makes writing tests that need to do by type lookup
way more complicated that it should.
This commit introduces DummyBean, that merely replaces two types with
hardcoded values. It also exposes the raw attribute of OverrideMetadata
and doesn't override anything from it to make sure the behavior is not
altered.
Closes gh-32982
This commit aligns the by-type lookup for bean overrides with what was
done when a bean name is present. It now correctly generate a bean
name rather than failing because no bean of that type exists.
Closes gh-32990
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
By swallowing the exception on failing to release a savepoint, we are hiding
client code from database errors that they may need to be aware of or handle.
e.g. if the connection is now dead when trying to release the savepoint, by
swallowing the exception here, client code has no way of knowing this now until
the next operation on the database, which will yield a confusing message about
the problem and obscures where the failure occurred as it will be in a different
part of their code that throws any exception.
Swallowing the exception here is also inconsistent with all the other database
calls in the Transaction Object, where we always raise an exception up and let
client code decide how to handle the error.
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
This commit reviews how bean override support can influence the key of
an application context cached by the TCF. OverrideMetadata and its
subclasses now implement a proper equals/hashCode pair that is tested
in various scenarios.
Due to how the TCF operates, OverrideMetadata has to be computed in
two locations:
1. In a ContextCustomizerFactory, using the metadata in the enclosing
class if any. This determines whether a customizer is needed in the
first place. The computed set of unique metadata identifies the
customizer and participates in the application context cache's key.
2. In the TestExecutionListener so that it knows the override points
it has to process.
Parsing of the metadata based on a test class has been greatly
simplified and moved to OverrideMetadata proper as we don't need several
flavors. 1 and 2 are using the same algorithm with the former wrapping
that in a Set to compute a proper key.
BeanOverrideContextCustomizerEqualityTests provides a framework for
testing edge cases as we only care about whether the created
ContextCustomizer behaves correctly against the identity of another.
Closes gh-32884
This commit reviews the structure of several classes to comply with
our guidelines. Also, rather than exposing a static method to configure
the context in a test, we call the high-level API directly.
Rather than having to override the getBeanName method when there is one,
this commit moves it as a @Nullable argument. This makes sure that
equals and hashCode consistently use the bean name. getBeanName cannot
be final just yet as the test infrastructure overrides it.
Also, arguments are now ordered consistently, which improves code
readability and type signature.
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
This commit adds support for the "Partitioned" cookie attribute in
WebFlux servers and the related testing infrastructure.
Note, Undertow does not support this feature at the moment.
Closes gh-31454
This commit adds support for Kotlin BeanPostProcessor beans which should
be defined in a companion object and annotated with `@JvmStatic`.
Closes gh-32946
This commit makes sure to account for FactoryBean names when registering
a bean override. In the case of ReplaceDefinition mode, if there is a
factory bean name, it is used to check singleton status and as the name
in the registrar.
Closes gh-32971
Prior to this commit, exceptions thrown by MVC functional handlers would
not be considered by `ExceptionHandlerExceptionResolver`. This means
that common exceptions would not be handled consistently between
annotated and functional handlers. This is true, for example, for all
`ProblemDetails`-related exception handling.
While MVC functional and annotation models are separate concepts,
WebFlux has a different error handling model that processes all
exceptions in a central place.
This commit ensures that `ExceptionHandlerExceptionResolver` considers
exceptions thrown by handlers of type `HandlerFunction<?>` and processes
them accordingly.
Closes gh-32689
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
This commit aligns Spring WebFlux with WebMvc in adding URI variables
conditionally if not already in the map. The idea is that data
binding is primarily through form data and query params, with URI
variables, and request headers (to be implemented next) also made
available but without shadowing existing values.
See gh-32676
I accidentally introduced a regression in commit d185bb1d97 by no
longer checking the number of unique method names found when searching
for @TestBean factory methods.
This commit reintroduces that check and introduces a proper unit test
in TestBeanOverrideProcessorTests.
It turns out that we already had an integration test that was intended
to check for this scenario; however, that test actually did not test
this scenario due to a copy-and-paste error. Thus, this commit also
updates TestBeanInheritanceIntegrationTests so that
fieldInSupertypeWithPrioritizedFactoryMethodInSubtype() tests what it's
supposed to.
This commit benefits from a feature introduced in AssertJ 3.26.0, see
https://github.com/assertj/assertj/pull/3377.
This allows to use any AssertFactory and convert the actual value to
the type the factory manages. Previously, we were using
ParameterizedTypeReference to express the type with its generic
signature but the returned assert object would not be narrowed to the
converted type.
Thanks to this change, we can request to convert the actual value to
`InstanceOfAssertFactories.list(Member.class)` and get a `ListAssert`
of `Member` as a result, rather than an `ObjectAssert` of `List<User>`.
Thanks very much to @scordio for his efforts.
Closes gh-32953
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
Prior to this commit, a @TestBean factory method was found in the
directly enclosing class for a @Nested test class; however, such a
factory method was not found in the enclosing class of the enclosing
class, etc.
This commit updates the search algorithm for @TestBean factory methods
so that it recursively searches the enclosing class hierarchy for
@Nested test classes.
Closes gh-32951
This commit adds a number of catch point that provides additional
context when an AOT processor fails to execute. Amongst other things,
this makes sure that the bean name and its descriptor is consistently
provided in the error message when available.
Closes gh-32777
- Do not silently abort bean override processing if the ApplicationContext
is not a BeanDefinitionRegistry.
- Include conflicting bean names in error messages instead of just the
number of conflicting beans.
- Consistently throw IllegalStateException.
- etc.
Prior to this commit, @TestBean factory methods were required to be
defined in the test class or one of its superclasses. However, users
may wish to define common factory methods in interfaces that can be
shared easily across multiple test classes simply by implementing the
necessary interface(s).
This commit therefore switches from ReflectionUtils to
MethodIntrospector to find @TestBean factory methods in implemented
interfaces within the type hierarchy of the test class.
Closes gh-32943
Includes checking the Servlet 3.0+ ServletRequest.getServletContext() method in the request-only constructors, being able to fall back to the root WebApplicationContext.
See gh-32926
As a follow up to the previous commit (31f8e12adb), this commit
polishes bean override tests and revises them with a focus on AOT
testing support and simplified maintenance.
- Introduce EngineTestKitUtils to simplify working with JUnit's
EngineTestKit.
- Use idiomatic EngineTestKit APIs to simplify assertions on
EngineTestKit results.
- Introduce BeanOverrideTestSuite to simplify running all bean override
tests within the IDE.
- Separate failure and success scenario tests, so that failure tests do
not launch the JUnit Platform to run tests using the Spring
TestContext Framework (TCF) within a test class that itself uses the
TCF.
- Make AbstractTestBeanIntegrationTestCase actually abstract.
- Rename test case classes to give them meaningful names and simplify
understanding of what's being tested.
- Ensure tests for @MockitoSpyBean functionality use @MockitoSpyBean
instead of @MockitoBean.
- Declare @Configuration classes local to @SpringJUnitConfig test
classes whenever possible.
See gh-29122
See gh-32925
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.
This commit moves the features of MockHttpServletRequestBuilder in
an abstract class so that another class can offer the same feature
whilst providing AssertJ support. This wasn't possible previously as
the builder's return type would lose the concrete builder types.
This change benefits MockMultipartHttpServletRequestBuilder that can
use the same mechanism to offer additional settings.
This change also makes it so that a builder instance can be created
using only the HttpMethod. Previously, the URI had to be provided as
well and that makes it impossible to specify it using the builder.
See gh-32913
This commit ensures that the FormHttpMessageConverter no longer supports
reading Maps (just MultiValueMaps). Plain maps are often used to
represent JSON.
See gh-32826
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
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
Prior to this commit, the `WebSocketMessageBrokerStats` would be in
charge of periodically logging WebSocket stats. This class would also
publicly expose each stats type with dedicated methods, as `String`.
This would not allow observation libraries to easily extract information
and turn them into metrics.
This commit introduces new methods exposing the `Stats` types directly
and deprecates the former `String` variants. This will allow
observability libraries like Micrometer to expose this as metrics:
```
MeterRegistry meterRegistry = ...;
Gauge.builder("spring.stomp.frames", stats.getStompSubProtocolStats(),
StompSubProtocolHandler.Stats::getTotalConnect)
.tag("type", "CONNECT")
.description("number of CONNECT frames processed")
.register(meterRegistry);
```
Closes gh-31604
Previously, AbstractJsonContentAssert worked on a raw String, which
made standard AssertJ nested calls, such as satisfies, to return an
assert on the raw string, rather than one with JSON support.
This commit rework AbstractJsonContentAssert so that it no longer
extend from AbstractStringAssert. This makes the list of methods more
focused on JSON assertions, and allow standard operations to provide
the right assert object.
Closes gh-32894
Prior to this commit, the Gradle build issued the following warning.
- The deprecated "gradleEnterprise.buildScan.value" API has been
replaced by "develocity.buildScan.value"
This commit makes several improvements to MultiValueMap:
- asSingleValueMap offers a single-value view (as opposed to the
existing toSingleValueMap, which offers a copy)
- fromSingleValue is a static method that adapts a Map<?,?> to the
MultiValueMap interface
- fromMultiValue is a static method that adapts a Map<?,List<?>> to the
MultiValueMap interface
Closes gh-32832
Prior to this commit, gh-31936 enabled content negotiation for
`@ExceptionHandler` annotated methods in Spring MVC and WebFlux.
In the case of WebFlux, HTTP clients sending invalid media types in the
"Accept" request header would fail with a `NotAcceptableStatusException`
This exception would be handled with an HTTP 406 response status,
instead of processing the original exception.
This commit ensures that invalid media types are ignored during the
exception handling phase and that we fall back to "*/*".
Fixes gh-32878
This commit introduces a JsonComparator abstraction, with an
implementation using JSONAssert. Previously, JSONAssert was the only
choice.
Test APIs have been adapted to allow the new abstraction while relying
on JSONAssert still for high-level methods.
Closes gh-32791
Co-authored-by: Stéphane Nicoll <stephane.nicoll@broadcom.com>
This commit changes the FormHttpMessageConverter from a
HttpMessageConverter<MultiValueMap<String, ?>> to a
HttpMessageConverter<Map<String, ?>>, so that normal, single-value maps
can also be used as form representation, both for reading and writing.
Closes gh-32826
* pr/32876:
Polish "Extend nested placeholders resolution to any CharSequence"
Extend nested placeholders resolution to any CharSequence
Closes gh-32876
Prior to this commit, as a result of commit 6cdb34410b, the
DynamicValuesPropertySource was eagerly registered in the Environment
even if the DynamicPropertyRegistry was never used to register dynamic
properties.
This commit ensures that the DynamicValuesPropertySource is only
registered if we know that the DynamicPropertyRegistry is actually used
-- either by a @DynamicPropertySource method in a test class or via a
bean in the ApplicationContext that invokes add() on the
DynamicPropertyRegistry bean.
See gh-32271
Closes gh-32871
- 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
This commit allows to extend the `ServerHttpObservationFilter` when the
observation scope is opened. This typically allows to add the current
traceId as a response header.
Closes gh-30632
This commit uses the bean factory `isAutowiredCandidate` method directly
in `BeanOverrideBeanFactoryPostProcessor` to select a single match among
multiple candidates when matching by type.
The expected consequence, in most cases, is that this will delegate to
a `@Qualifier`-aware `QualifierAnnotationAutowireCandidateResolver`.
In that sense, bean overriding by-type matching is now potentially
taking Qualifier annotations or meta-annotations into account.
It also changes the way existing bean definitions are checked in case
a bean name has been specified: factory beans are now taken into account
when checking the type of an existing definition matches the expected
bean override type.
Closes gh-32822
Includes JAXBContext locking revision (avoiding synchronization) and consistent treatment of DocumentBuilderFactory (in terms of caching as well as locking).
Closes gh-32851
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
Prior to this commit, `@ExceptionHandler` annotated controller methods
could be mapped using the exception type declaration as an annotation
attribute, or as a method parameter.
While such methods support a wide variety of method arguments and return
types, it was not possible to declare the same exception type on
different methods (in the same controller/controller advice).
This commit adds a new `produces` attribute on `@ExceptionHandler`; with
that, applications can vary the HTTP response depending on the exception
type and the requested content-type by the client:
```
@ExceptionHandler(produces = "application/json")
public ResponseEntity<ErrorMessage> handleJson(IllegalArgumentException exc) {
return ResponseEntity.badRequest().body(new ErrorMessage(exc.getMessage(), 42));
}
@ExceptionHandler(produces = "text/html")
public String handle(IllegalArgumentException exc, Model model) {
model.addAttribute("error", new ErrorMessage(exc.getMessage(), 42));
return "errorView";
}
```
This commit implements support in both Spring MVC and Spring WebFlux.
Closes gh-31936
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
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
The code was necessary while ForwardedHeaderFilter was deprecated
but still possible to use. When the filter was removed, this code
could have been removed as well.
Prior to this commit, DynamicPropertyRegistry could only be used with a
static @DynamicPropertySource method in an integration test class;
however, it can also be useful to be able to register a "dynamic
property" from within a test's ApplicationContext -- for example, in a
@Bean method in a @Configuration class that is specific to testing
scenarios.
To support such use cases, this commit updates the dynamic property
source infrastructure so that a DynamicPropertyRegistry is always
registered as a singleton bean in a test's ApplicationContext. This
allows DynamicPropertyRegistry to be autowired into a @Configuration
class or supplied to a @Bean method as an argument as shown in the
following example.
@Bean
@DynamicPropertySource
ApiServer apiServer(DynamicPropertyRegistry registry) {
ApiServer apiServer = new ApiServer();
registry.add("api.url", apiServer::getUrl);
return apiServer;
}
Note that the use of @DynamicPropertySource on the @Bean method is
optional and results in the corresponding bean being eagerly
initialized so that other singleton beans in the context can be given
access to the dynamic properties sourced from that bean when those
other beans are initialized.
Side note: DynamicPropertySourceBeanInitializer temporarily implements
LoadTimeWeaverAware since doing so is currently the only way to have a
component eagerly initialized before the
ConfigurableListableBeanFactory.preInstantiateSingletons() phase.
However, we plan to introduce a first-class callback to support such
use cases in the future.
Closes gh-32271
This commit introduces a `isNotEqualTo(String)` assertion in order to
avoid false negatives when using the default Object-based assertion.
This is a risk since MediaTypeAssert has a `isEqualTo(String)` method
that overrides the base object method and parses the provided String
into a MediaType. Users may thus be tempted to use the reverse assertion
and expect the same parsing behaviour.
This commit also adds tests around the String parsing and the isNotEqual
cases.
Closes gh-32756
This commit promotes a previously private method in
`BeanRegistrationsAotContribution` to a top-level method in
`ReflectionHints`.
This helps to register hints on all interfaces implemented in the class
hierarchy of the given type.
Closes gh-32824
This change switches default behavior of `@TestBean`, `@MockitoBean` and
`@MockitoSpyBean` to match the bean definition / bean to override by
type in the case there is no explicit bean name provided via the
annotation. The previous behavior of using the annotated field's name
is still an option for implementors, but no longer the default.
Closes gh-32761
This commit merges support for compiling SpEL expressions that contain
varargs invocations where the supplied array is a subtype of the
declared varargs array type.
Closes gh-32804
This commit first reverts changes to SpelNodeImpl from the previous
commit in order to reduce the scope of the overall change set.
This commit then implements a different approach to support type-safe
checks for array subtype compatibility.
In order to support backward compatibility, this commit also
reintroduces generateCodeForArguments(MethodVisitor, CodeFlow, Member,
SpelNodeImpl[]) in deprecated form.
See gh-32804
This commit introduces support for compiling SpEL expressions that
contain varargs invocations where the supplied array is a subtype of
the declared varargs array type.
See gh-32804
Prior to this commit, trailing slash matching was disabled by default in
Spring MVC with gh-28552. `StandaloneMockMvcBuilder` was not changed as
a result and still had the trailing slash match option enabled.
This commit aligns the defaults in `StandaloneMockMvcBuilder` to better
reflect the expected behavior in tests.
Closes gh-32796
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
Prior to this commit, `DataBufferLimitException` would be thrown by
codecs when the request body was too large for the configured buffer
limit. This exception would not be handled by the web infrastructure and
would result in an HTTP 500 server error.
This commit introduces a new `PayloadTooLargeException` type that will
result in an HTTP 413 "Payload too large" response status.
Closes gh-32558
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
Adds support common in other ResultSet implemenatations for qualifying column names with table name to distinguish potentially duplicate column names in a join of two or more tables from one another. The expected format is {table_name}.{column_namne}, where column_name is the actuall designated column name and not the column label.
This commit renames AssertableMockMvc to MockMvcTester as the former
was too mouthful, and we are looking for a naming pattern that can be
applied consistently to test utilities that rely on AssertJ.
Rather than AssertableMvcResult, we now use MvcTestResult and it no
longer extends from MvcResult itself. That avoids having existing code
that is migrated to the new API whilst assigning the result to MvcResult
and get a bad DevXP as that doesn't bring any of the AssertJ support.
See gh-32712
This commit removes ResponseBodyAssert and rather offers first-class
access support for the response body at the root level using bodyText(),
bodyJson(), and body().
This avoids a double navigation to assert the response body.
See gh-32712
This commit merges the JSONCompare and JsonPath support in a single
assert object. The rationale for the previous situation was that
JsonPath is optional but merging the assertions methods do not make
it mandatory as the usage if JsonPath is triggered only if it is
actually used.
See gh-32712
Improvements include:
- Replace throwing exceptions with failure results in hot areas,
- Verify digits of a string before passing it to Integer::parseInt
- Lazily initialization of fields
- Using LinkedList instead of ArrayList where size is not known
beforehand
See gh-32513
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
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
Before this commit, creating a CompositeMap from two maps with the same
key has strange results, such as entrySet returning duplicate entries
with the same key.
After this commit, we give precedence to the first map by filtering out
all entries in the second map that are also mapped by the first map.
See gh-32245
This commit ensures that a copy is made of old attributes before
replacing it with new attributes. Because new attributes can be
composed of old, clearing the old would also remove entries from the
new.
See gh-32245
Prior to this commit, an IndexAccessor could not provide support for a
Collection target type, since the built-in support for indexing into a
Collection in SpEL's Indexer took precedence.
This commit allows an IndexAccessor to support custom Collection target
types by separating the built-in List and Collection support and
applying the built-in Collection support after custom index accessors
have been applied.
Closes gh-32736
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
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
This commit introduces ReflectiveIndexAccessor for the Spring
Expression Language (SpEL) which is somewhat analogous to the
ReflectivePropertyAccessor implementation of PropertyAccessor.
ReflectiveIndexAccessor is a flexible IndexAccessor implementation that
uses reflection to read from and optionally write to an indexed
structure of a target object. ReflectiveIndexAccessor also implements
CompilableIndexAccessor in order to support compilation to bytecode for
read access.
For example, the following creates a read-write IndexAccessor for a
FruitMap type that is indexed by Color, including built-in support for
compilation to bytecode for read access.
IndexAccessor indexAccessor = new ReflectiveIndexAccessor(
FruitMap.class, Color.class, "getFruit", "setFruit");
Closes gh-32714
* pr/28958:
Polish "Include URL and HTTP method in DefaultResponseErrorHandler"
Include URL and HTTP method in DefaultResponseErrorHandler
Closes gh-28958
This commit raises the baseline to Hibernate 6.5 for native support,
which allows to remove remaining Hibernate substitutions as well as
deprecated properties usage.
Closes gh-32314
This commit gathers the ShadowMatch instances that AspectJ requires in
a dedicated class that can be used to clear the instances when they are
no longer required.
As those are mainly triggered via AspectJAwareAdvisorAutoProxyCreator,
it now implements the necessary callbacks to clear the cache.
Closes gh-12334
This commit introduces
BodyInserters.fromValue(T, ParameterizedTypeReference<T>) variant as
well as related WebClient.RequestBodySpec API,
ServerResponse.BodyBuilder API and Kotlin extensions.
Closes gh-32713
This commit replaces the IllegalStateException thrown in
CacheAspectSupport when a CacheManager cannot be determined. These were
added to provide a dedicated error message, but it is possible to do
so without hiding the more adequate exception type.
Closes gh-22442
This commit introduces a new CompilableIndexAccessor SPI for the Spring
Expression Language (SpEL) which allows an IndexAccessor to support
compilation to bytecode for operations that read an index.
This analogous to the CompilablePropertyAccessor SPI.
This commit also includes a prototype for a general purpose
ReflectiveIndexAccessor in the tests.
Closes gh-32613
In order to make SpelNode compilation aware, this method moves the
declaration of isCompilable() and generateCode(...) from SpelNodeImpl
to SpelNode.
Closes gh-32707
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
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>
This is equivalent of the same contract for WebFlux. It is implemented
by HandlerMappingIntrospector, and may be called directly by Spring
Security to handle a pre-flight request without delegate to the rest
of the filter chain.
HandlerMappingIntrospector also has the boolean method
allHandlerMappingsUsePathPatternParser that checks whether all handler
mappings are configured to use parsed PathPattern's.
See gh-31823
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
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.
Closes gh-32694
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
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
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
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
Prior to this commit, `HttpHeaders#setContentLength` would accept
negative values. Those are not allowed by the RFC and the headers
implementation only uses "-1" as a way to convey that no value was set.
This commit ensures that negative values are rejected.
Fixes gh-32660
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
This commit introduces a new URL parser based on algorithm provided in
the Living URL standard. This new UrlParser is used by
UriComponentsBuilder::fromUriString, replacing the regular expressions.
Closes gh-32513
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
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
This change splits the documentation in the reference manual: the
`@TestBean`, `@MockitoBean` and `@MockitoSpyBean` annotations are kept
in the appendix and the general documentation about the feature is moved
into a dedicated sub-section of the TCF section.
Close gh-32490
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
Prior to this commit, the text `#{ }` was displayed as { } with a bright
green background.
This commit addresses this by making use of Asciidoc's literal monospace
feature: `+#{ }+`.
This commit refines the expressions for the scheme, user info, host and
port parts of the URL in UriComponentsBuilder to better conform to
RFC 3986.
Fixes gh-32616
This commit improves on the bean overriding feature in several ways:
the API is simplified and polished (metadata and processor contracts,
etc...).
The commit also reworks infrastructure classes (context customizer,
test execution listener, BeanOverrideBeanFactoryPostProcessor, etc...).
Parsing of annotations is now fully stateless.
In order to avoid OverrideMetadata in bean definition and to make a
first step towards AOT support, the BeanOverrideBeanFactoryPostProcessor
now delegates to a BeanOverrideRegistrar to track classes to parse,
the metadata-related state as well as for the field injection methods
for tests.
Lastly, this commit increases the test coverage for the provided
annotations and adds integration tests and fixes a few `@TestBean`
issues.
Prior to this commit, `BufferingClientHttpRequestWrapper` would always
write to the actual client request body, even if the buffered content
was empty (empty byte array).
This would cause issues with specific client request factories,
especially the OkHttp variant, that would consider empty byte arrays as
non-empty body and would reject such cases for GET requests with an
"IllegalArgumentException: method GET must not have a request body".
This commit only writes to the request if the buffered content is not
empty.
Fixes gh-32612
This set of commits introduces a new IndexAccessor SPI for the Spring
Expression Language (SpEL) which allows third parties to customize the
SpEL Indexer.
A custom IndexAccessor implementation can be registered in a
StandardEvaluationContext.
For an example, see the JacksonArrayNodeIndexAccessor in IndexingTests
in the spring-expression module.
See gh-26409
Closes gh-26478
Prior to this commit, the read() method in the IndexAccessor SPI
declared a return type of ValueRef which introduced a package cycle.
This commit addresses this by aligning with the PropertyAccess SPI and
returning TypedValue from IndexAccessor's read() method. This commit
also reworks the internals of Indexer based on a new, local
IndexAccessorValueRef implementation.
See gh-26409
See gh-26478
Prior to this commit, MethodIntrospector failed to properly detect
bridge methods for subsequent invocations of selectMethods() with the
same targetType and MetadataLookup, if such subsequent invocations
occurred after the ApplicationContext had been refreshed.
The reason this occurs is due to the following.
- Class#getDeclaredMethods() always returns "child copies" of the
underlying Method instances -- which means that `equals()` should be
used instead of `==` whenever the compared Method instances can come
from different sources (such as the static caches mentioned below).
- BridgeMethodResolver caches resolved bridge methods in a static cache
-- which is never cleared.
- ReflectionUtils caches declared methods in a static cache
-- which gets cleared when an ApplicationContext is refreshed.
Consequently, if you attempt to load an ApplicationContext twice in the
same ClassLoader, the second attempt uses the existing, populated cache
for bridged methods but a cleared, empty cache for declared methods.
This results in new invocations of Class#getDeclaredMethods(), and
identity checks with `==` then fail to detect equivalent bridge methods.
This commit addresses this by additionally comparing bridge methods
using `equals()` in MethodIntrospector.selectMethods().
Note that the `==` checks remain in place as an optimization for when
`equals()` is unnecessary.
Closes gh-32586
Prior to this commit, the `JmsTemplate#sendAndReceive` method would not
instrument the JMS session. This means that no metric would be recorded
when sending the message and no trace would be propagated downstream.
This commit ensures that the JMS session is instrumented in this case as
well. Note, the reception of the response message does not create a
`"jms.message.process"` observation as the session is only receiving the
message, no listener has been configured on the message consumer.
Fixes gh-32606
This commit replaces `@Nonnull(when = When.MAYBE)` meta-annotation in
`org.springframework.lang.Nullable` by `@CheckForNull` in order to
prevent `unknown enum constant When.MAYBE` compilation warnings.
Closes gh-27183
This commit ensures that the response body is drained and closed when
the response itself is closed, instead of disposing the connection, as
this will disable the connection pool.
Closes gh-32528
This commit reverts some null-safety changes which make sense
on main but are too impactful for 6.1.x for Kotlin developers
using -Xjsr305=strict.
See gh-32475
This commit ensures that `InvocableHandlerMethod` executes the method
on the desired thread if a non-blocking thread is specified, even in the
case where arguments resolution happens on a different thread. This is
notably the case if the method body is resolved as an input argument to
the controller method (`@RequestBody`).
Closes gh-32502
This commit makes the use of bean definition overriding more visible and
prepare for a deprecation of the feature in the next major release.
As of this commit, use of bean definition overriding logs at INFO level.
The previous log level can be restored by setting the
allowBeanDefinitionOverriding flag explicitly on the BeanFactory (or
via the related ApplicationContext).
A number of tests that are using bean overriding on purpose have been
updated to set this flag, which will make them easier to find once we
actually deprecate the feature.
Closes gh-31288
This commit introduces support for org.webjars:webjars-locator-lite
via a new LiteWebJarsResourceResolver in Spring MVC and WebFlux, and
deprecates WebJarsResourceResolver which is performing a classpath
scanning that slows down application startup.
Closes gh-27619
Javadoc doesn't seem to like having `e.g.` as it thinks the sentence
ends there, which is usually incorrect and results in broken descriptions.
This commit rewords the doc strings slightly to avoid problematic parts.
Closes gh-32532
This commit updates SpringConfiguratorTests to not rely on classpath
scanning as it could have side effect. In this particular case, the
configuration class that sources the scan is detected again, leading
to bean overriding.
Irrespective of that, adding more code in that package may have side
effect as they could be scanned as well.
Closes gh-32535
This set of commits introduces support for a null-safe operator in the
Spring Expression Language (SpEL), including support for compiling
expressions that use the null-safe index operator.
Note, however, that compilation is not supported for null-safe indexing
into a String or any kind of Collection (other than a List).
See gh-21468
Closes gh-29847
Prior to this commit, SpEL's CompoundExpression omitted the null-safe
syntax in AST string representations of indexing operations.
To address this, this commit implements isNullSafe() in Indexer.
See gh-29847
Prior to this commit, SpEL's CompoundExpression omitted the null-safe
syntax in AST string representations of the selection and projection
operators.
To address this, this commit implements isNullSafe() in Projection and
Selection.
Closes gh-32515
Prior to this commit, MethodReference and PropertyOrFieldReference
already defined local isNullSafe() methods, but we need identical
methods in Selection, Projection, and Indexer, and we may potentially
need null-safe support for additional operators in the future.
To address the common need for an is-null-safe check, this commit
introduces an isNullSafe() method in SpelNodeImpl with a default
implementation that returns false.
Closes gh-32516
Prior to this commit when a required parameter defined as a property or
expression placeholder was missing, the exception thrown would refer to
the placeholder instead of the resolved name.
This change covers messaging handlers and web controllers, both blocking
and reactive. It also fixes the error message when handling null values
for non-required parameters, as well as in cases that need conversion.
See gh-32323
Closes gh-32462
Prior to this commit, the SpEL compiler generated classes in a package
named "spel" with names following the pattern "Ex#", where # was an
index starting with 2.
This resulted in class names such as:
- spel.Ex2
- spel.Ex3
This commit improves the names of classes created by the SpEL compiler
by generating classes in a package named
"org.springframework.expression.spel.generated" with names following
the pattern "CompiledExpression#####", where ##### is a 0-padded
counter starting with 00001.
This results in class names such as:
- org.springframework.expression.spel.generated.CompiledExpression00001
- org.springframework.expression.spel.generated.CompiledExpression00002
This commit also moves the saveGeneratedClassFile() method from
SpelCompilationCoverageTests to SpelCompiler and enhances it to:
- Save classes in a "build/generated-classes" directory.
- Convert package names to directories.
- Create missing parent directories.
- Use logging instead of System.out.println().
Running a test with saveGeneratedClassFile() enabled now logs something
similar to the following.
DEBUG o.s.e.s.s.SpelCompiler - Saving compiled SpEL expression [(#root.empty ? 0 : #root.size)] to [/Users/<username>/spring-framework/spring-expression/build/generated-classes/org/springframework/expression/spel/generated/CompiledExpression00001.class]
Closes gh-32497
The ApplicationContext has a resource cache that it uses while the
context is being refreshed. Once the refresh phase completes, the
cache is cleared as its content is no longer in use. If beans are
lazily initialized, there is a case where the cache might be filled
again as processing is deferred past the refresh phase.
For those cases, the cache is not cleared. This can be a problem when
running in this mode with a large set of test configurations as the TCF
caches the related contexts.
This commit includes an additional TestExecutionListener to the TCF that
clears the resource cache if necessary once a test class completes. It
is ordered so that it runs after `@DirtiesContext` support as marking
the context as dirty will remove it from the cache and make that extra
step unnecessary.
Closes gh-30954
This commit introduces null-safety checks for spring-core at build-time
in order to validate the consistency of Spring null-safety annotations
and generate errors when inconsistencies are detected during a build
(similar to what is done with Checkstyle).
In order to make that possible, this commit also introduces a new
org.springframework.lang.Contract annotation inspired from
org.jetbrains.annotations.Contract, which allows to specify semantics
of methods like Assert#notNull in order to prevent artificial
additional null checks in Spring Framework code base.
This commit only checks org.springframework.core package, follow-up
commits will also extend the analysis to other modules, after related
null-safety refinements.
See gh-32475
The fix for #31254 resulted in an InvalidMimeTypeException being thrown
by MimeTypeUtils.sortBySpecificity() instead of an
IllegalArgumentException. However, InvalidMimeTypeException extends
IllegalArgumentException. Consequently, the change from
IllegalArgumentException to InvalidMimeTypeException did not result in
the desired effect in HeaderContentNegotiationStrategy.
HeaderContentNegotiationStrategy.resolveMediaTypes() still allows the
InvalidMimeTypeException to propagate as-is without wrapping it in an
HttpMediaTypeNotAcceptableException.
To address this issue, this commit catches InvalidMediaTypeException
and InvalidMimeTypeException in HeaderContentNegotiationStrategy and
wraps the exception in an HttpMediaTypeNotAcceptableException.
See gh-31254
See gh-31769
Closes gh-32483
There is no way to consistently test this use case because listener
container implementations have different behavior for unhandled errors
and might retry or close the container altogether.
See gh-32458
Prior to this commit, when using the `DefaultMessageListenerContainer`
as a backing listener container for JMS messages, the instrumentation
would not record JMS exceptions as observation errors when they were not
handled by configured `ErrorHandler`.
This commit ensures that this is the case.
Fixes gh-32458
This commit adds a new way to use MockMvc by returning a MvcResult that
is AssertJ compatible. Compared to the existing MockMvc infrastructure,
this new model has the following advantages:
* Can be created from a MockMvc instance
* Dedicated builder methods for easier setup
* Assertions use familiar AssertJ syntax with discoverable assertions
through a DSL
* Improved exception message
See gh-21178
Co-authored-by: Brian Clozel <brian.clozel@broadcom.com>
This commit adds AssertJ compatible assertions for HTTP request and
responses, including headers, media type, and response body. The latter
delegate to the recently included JSON assert support.
See gh-21178
Historically, we have rarely intentionally thrown a
NullPointerException in the Spring Framework. Instead, we prefer to
throw either an IllegalArgumentException or IllegalStateException
instead of a NullPointerException.
However, changes to the code in recent times have introduced the use of
Objects.requireNonNull(Object) which throws a NullPointerException
without an explicit error message.
The latter ends up providing less context than a NullPointerException
thrown by the JVM (since Java 14) due to actually de-referencing a
null-pointer. See https://openjdk.org/jeps/358.
In light of that, this commit revises our current use of
Objects.requireNonNull(Object) by removing it or replacing it with
Assert.notNull().
However, we still use Objects.requireNonNull(T, String) in a few places
where we are required to throw a NullPointerException in order to
comply with a third-party contract such as Reactive Streams.
Closes gh-32430
Prior to this commit, gh-21783 introduced `ReadOnlyHttpHeaders` to avoid
parsing media types multiple times during the lifetime of an HTTP
exchange: such values are cached and the headers map is made read-only.
This also added a new `HttpHeaders.writableHttpHeaders` method to unwrap
the read-only variant when needed.
It turns out this method sends the wrong signal to the community
because:
* the underlying map might be unmodifiable even if this is not an
instance of ReadOnlyHttpHeaders
* developers were assuming that modifying the collection that backs the
read-only instance would work around the cached values for
Content-Type and Accept headers
This commit adds more documentation to highlight the desired behavior
for cached values by the read-only variant, and deprecates the
`writableHttpHeaders` method as `ReadOnlyHttpHeaders` is package private
and we should not surface that concept anyway.
Instead, this commit unwraps the read-only variant if needed when a new
HttpHeaders instance is created.
Closes gh-32116
This commit ensures pathExtension predicate is skipped when the value
is null, in order to provide a more predictable behavior, and allow
a better compatibility with collections not supporting null elements
like the ones created by List#of.
Closes gh-32404
Prior to this commit, gh-31609 added the current observation context as
a request attribute for `WebClient` calls. While it was not confirmed as
the main cause, this feature was linked to several reports of memory
leaks. This would indeed attach more memory to the request object graph
at runtime - although it shouldn't prevent its collection by the GC.
This commit removes this feature and instead developers should get the
current observation from the reactor context if they wish to interact
with it.
Closes gh-32198
This commit introduce a change of behaviour when component scan is used
with conditions. Previously, any condition in the REGISTER_BEAN phase
were ignored and the scan was applied regardless of the outcome of
those conditions. This is because REGISTER_BEAN condition evaluation
happens later in the bean factory preparation.
Rather than ignoring those conditions, this commit fails fast when it
detects such use case. Code will have to be adapted accordingly.
Closes gh-23206
This commit upgrades to a major new release of HtmlUnit. This is a
breaking change as HtmlUnit 3 moves to a `org.htmlunit` package and
calling code needs to be restructured.
Our use of Selenium has been adapted accordingly, moving to Selenium
3, using the new org.seleniumhq.selenium:htmlunit3-driver integration.
Closes gh-30392
This commit moves findPublicDeclaringClass() from ReflectionHelper to
CodeFlow, since findPublicDeclaringClass() is only used for bytecode
generation and therefore not for reflection-based invocations.
This commit adds support for application/yaml in MediaType and leverages
jackson-dataformat-yaml in order to support Yaml in RestTemplate,
RestClient and Spring MVC.
See gh-32345
It was never necessary for SpEL's OptimalPropertyAccessor to be public.
Instead, clients should interact with OptimalPropertyAccessor
exclusively via the CompilablePropertyAccessor API.
In light of that, this commit makes SpEL's OptimalPropertyAccessor
private.
Closes gh-32410
Rework AnnotatedElementAdapter to avoid cloning the underlying
Annotation array if it is empty when getAnnotations() is called.
Additionally, make the class static and add a factory method that
returns a singleton instance for null or empty Annotation arrays.
Closes gh-32405
Commit c79436f832 ensured that methods are invoked via a public
interface or public superclass when compiling Spring Expression
Language (SpEL) expressions involving method references or property
access (see MethodReference, PropertyOrFieldReference, and
collaborating support classes). However, compilation of expressions
that access properties by indexing into an object by property name is
still not properly supported in all scenarios.
To address those remaining use cases, this commit ensures that methods
are invoked via a public interface or public superclass when accessing
a property by indexing into an object by the property name – for
example, `person['name']` instead of `person.name`.
In addition, SpEL's Indexer now properly relies on the
CompilablePropertyAccessor abstraction instead of hard-coding support
for only OptimalPropertyAccessor. This greatly reduces the complexity
of the Indexer and simultaneously allows the Indexer to potentially
support other CompilablePropertyAccessor implementations.
Closes gh-29857
This commit introduces two sets of annotations (`@TestBean` on one side
and `MockitoBean`/`MockitoSpyBean` on the other side), as well as an
extension mecanism based on the `@BeanOverride` meta-annotation.
Extension implementors are expected to only provide an annotation,
a BeanOverrideProcessor implementation and an OverrideMetadata subclass.
Closes gh-29917.
Prior to this commit, error signals flowing from the client response
publisher in `WebClient` would be set on the `Observation.Context`. This
is enough for the observation convention to collect data about the error
but observation handlers are not notified of this error.
This commit sets the error instead on the observation directly to fix
this issue.
Fixes gh-32389
Although the Spring Expression Language (SpEL) generally does a good
job of locating the public declaring class or interface on which to
invoke a method in a compiled expression, prior to this commit there
were still a few unsupported use cases.
To address those remaining use cases, this commit ensures that methods
are invoked via a public interface or public superclass whenever
possible when compiling SpEL expressions.
See gh-29857
webmvc.fn now also uses the StandardServletAsyncWebRequest wrapped response
to enforce lifecycle rules from Servlet spec (section 2.3.3.4).
See gh-32340
KClass instantiation in CoroutinesUtils is suboptimal, and should be
replaced by KTypes#isSubtypeOf checks using pre-instantiated types for
Flow, Mono and Publisher.
This commit impact on performances is significant since a throughput
increase between 2x and 3x has been measured on basic endpoints.
Closes gh-32390
This commit fixes an issue where a Cacheable method which returns a
Flux (or multi-value publisher) will be invoked once, but the returned
publisher is actually subscribed twice.
The previous fix 988f3630c would cause the cached elements to depend on
the first usage pattern / request pattern, which is likely to be too
confusing to users. This fix reintroduces the notion of exhausting the
original Flux by having a second subscriber dedicated to that, but uses
`refCount(2)` to ensure that the original `Flux` returned by the cached
method is still only subscribed once.
Closes gh-32370
Also fix a couple of related issues:
- add AsyncRequestNotUsableException to the list of exceptions
that imply response issues.
- handle exceptions from @ExceptionHandler regardless of whether
thrown immediately or via Publisher.
Closes gh-32359
The JSP VariableResolver API has been deprecated since JSP 2.1 in favor
of the newer ELContext API.
This commit therefore refactors JspPropertyAccessor to use the
ELContext API.
Closes gh-32383
This commit documents that an empty list is not guaranteed to be
supported by the database. For example, MySQL and PostgreSQL do not
support `foo in ()`.
See gh-32380
This commit fixes an issue where a Cacheable method which returns a
Flux (or multi-value publisher) will be invoked once, but the returned
publisher is actually subscribed twice.
By using the Reactor `tap` operator, we ensure that we can emit values
downstream AND accumulate emitted values into the List with a single
subscription.
The SignalListener additionally handles scenarios involving cancel,
for instance in case of a `take(1)` in the chain. In that case values
emitted up until that point will have been stored into the List buffer,
so we can still put it in the cache. In case of error, no caching occurs
and the internal buffer is cleared. This implementation also protects
against competing onComplete/onError signals and cancel signals.
Closes gh-32370
Includes rollbackOn annotation attribute on @EnableTransactionManagement and addDefaultRollbackRule method on AnnotationTransactionAttributeSource, as well as publicMethodsOnly as instance-level flag (also on AnnotationCacheOperationSource).
Closes gh-23473
The following adjustments are also made as a result:
- Use int to check if lock is held and unlock is needed, given that
for non-async requests we don't need to obtain a lock.
- Protect access methods getOutputStream and getWriter with the
same locking and state checks.
Closes gh-32340
This commit updates ServletServerHttpResponse.ServletResponseHttpHeaders
in order to use ServletResponse#getContentType instead of
ServletResponse#getHeader.
It allows to have a consistent behavior between Tomcat (which sets only
the former) and Undertow/Jetty (which set both).
Closes gh-32339
ServletResponseHttpHeaders#get should be annotated with `@Nullable` and
return null instead of a singleton list containing null when there is no
content type header.
Closes gh-32362
In addition to using the ServletOutputStream, it's also possible to call
ServletResponse#flushBuffer, so the ServletOutputStream wrapper logic needs
to apply there as well.
See gh-32340
The wrapped response prevents use after AsyncListener onError or completion
to ensure compliance with Servlet Spec 2.3.3.4.
The wrapped response is applied in RequestMappingHandlerAdapter.
The wrapped response raises AsyncRequestNotUsableException that is now
handled in DefaultHandlerExceptionResolver.
See gh-32340
Prior to this commit, if a Spring Expression Language (SpEL) expression
referenced the root context object via the #root or #this variable, we
inserted a checkcast in the generated byte code that cast the object to
its concrete type. However if the root context object's type was
non-public, that resulted in an IllegalAccessError when the compiled
byte code was executed.
VariableReference.getValueInternal() already contains a solution for
global variables which inserts a checkcast to Object in the generated
byte code instead of to the object's concrete non-public type.
This commit therefore applies the same logic to #root (or #this when
used to reference the root context object) that is already applied to
global variables.
Closes gh-32356
To smooth upgrade from 6.1.x, this commit makes sure that code that used
to catch an IAE to ignore a faulty placeholder resolution still works.
See gh-9628
Prior to this commit, the reference manual only documented indexing
support for arrays, lists, and maps.
This commit improves the overall documentation for SpEL's property
navigation and indexing support and introduces additional documentation
for indexing into Strings and Objects.
Closes gh-32355
This commit refines WebMVC and WebFlux argument resolution in order to
convert properly Kotlin value class arguments by using the type of the
value instead of the type of the value class.
Closes gh-32353
The HttpHeaders.getAcceptLanguageAsLocales was incurring overhead from
using a Stream, as well as calling the fairly expensive
Locale.getDisplayName method.
Switch to using an ArrayList, and skipping over wildcard ranges to avoid
needing to check the display name.
Closes gh-32318
This commit fixes a performance regression caused by gh-31698,
and more specifically by KClass#isValue invocations which are slow since
they load the whole module to find the class to get the descriptor.
After discussing with the Kotlin team, it has been decided that only
checking for the presence of `@JvmInline` annotation is enough for
Spring use case.
As a consequence, this commit introduces a new
KotlinDetector#isInlineClass method that performs such check, and
BeanUtils, CoroutinesUtils and WebMVC/WebFlux InvocableHandlerMethod
have been refined to leverage it.
Closes gh-32334
For consistency with other examples, this commit omits `method` parameter
names in the "Migrating from RestTemplate to RestClient" section of the
reference docs.
Closes gh-32335
Based on feedback from several members of the community, we have
decided to revert the caching of the Content-Type header that was
introduced in ContentCachingResponseWrapper in 375e0e6827.
This commit therefore completely removes Content-Type caching in
ContentCachingResponseWrapper and updates the existing tests
accordingly.
To provide guards against future regressions in this area, this commit
also introduces explicit tests for the 6 ways to set the content length
in ContentCachingResponseWrapper and modifies a test in
ShallowEtagHeaderFilterTests to ensure that a Content-Type header set
directly on ContentCachingResponseWrapper is propagated to the
underlying response even if content caching is disabled for the
ShallowEtagHeaderFilter.
See gh-32039
Closes gh-32317
Prior to this commit, getHeaderNames() returned duplicates for the
Content-Type and Content-Length headers if they were set in the wrapped
response as well as in ContentCachingResponseWrapper.
This commit fixes that by returning a unique set from getHeaderNames().
In addition, this commit introduces a new test in
ContentCachingResponseWrapperTests to verify the expected behavior for
Content-Type and Content-Length headers that are set in the wrapped
response as well as in ContentCachingResponseWrapper.
See gh-32039
See gh-32317
Commit 375e0e6827 introduced a regression in
ContentCachingResponseWrapper (CCRW). Specifically, CCRW no longer
honors Content-Type and Content-Length headers that have been set on
the wrapped response and returns null for those header values if they
have not been set directly on the CCRW.
This commit fixes this regression as follows.
- The Content-Type and Content-Length headers set in the wrapped
response are honored in getContentType(), containsHeader(),
getHeader(), and getHeaders() unless those headers have been set
directly on the CCRW.
- In copyBodyToResponse(), the Content-Type in the wrapped response is
only overridden if the Content-Type has been set directly on the CCRW.
See gh-32039
Closes gh-32317
This commit adapts Hibernate native support to handle
the changes performed as part of HHH-17643 which impacts
Hibernate versions 6.4.3+ and 6.2.21+.
It ignores the BytecodeProvider services loaded by the
service loader feature in order to default to the
"no-op" provider with native, and makes the substitutions
more lenient when a substituted field or method does not
exist.
gh-32314 is expected to remove the need for such
substitutions which are not great for maintainability
by design.
Closes gh-32311
This commit introduces composite collections (i.e. Collection, Set, Map)
and uses these composites in request predicates, where before new
collections were instantiated.
Closes gh-32245
This commit checks whether the CompletableFuture<ServerResponse> passed
to AsyncServerResponse.async has been completed, and if so returns a
CompletedAsyncServerResponse that simply delegates to the completed
response, instead of the DefaultAsyncServerResponse that uses async
dispatch.
Closes gh-32223
Add helpers to CollectionUtils for building HashSets and LinkedHashSets
that can hold an expected number of elements without needing to
resize/rehash.
Closes gh-32291
This commit revisits the improved detection algorithm for stored
procedure as, unfortunately, certain JDBC drivers do not support
the documented pattern for schema and procedure name.
To work around this limitation, this commit applies the escaping of
wildcard characters to the case where multiple procedures have been
found for a given search.
Closes gh-32295
In places where a ConcurrentHashMap was used as a set by wrapping it
with Collections.newSetFromMap, switch to just using the set returned
by ConcurrentHashMap.newKeySet directly.
Closes gh-32294
This commit updates the content-type for form data to not include the
charset, unless it is different from the default charset.
Some servers don't handle charset parameter and the spec is unclear.
See gh-31781
NamedParameterUtils in spring-r2dbc now supports MySQL-style backticks
for quoted identifiers for consistency with spring-jdbc.
See gh-31944
Closes gh-32285
Since the Spring Expression Language does not actually support local
variables in expressions, this commit deprecates all public APIs
related to local variables in ExpressionState (namely, the two
enterScope(...) variants that accept local variable data,
setLocalVariable(), and lookupLocalVariable()).
In addition, we no longer invoke `state.enterScope("index", ...)` in
the Projection and Selection AST nodes since the $index local variable
was never accessible within expressions anyway.
See gh-23202
Closes gh-32004
Delegate to the spliterator method of the underlying collection in
MutablePropertyValues and MutablePropertySources. In both cases, those
collection types have specialized Spliterator implementations.
Delegating to these Spliterators also means the characteristics of the
Spliterator are properly set.
See gh-32281
* pr/32243:
Polish "Add ThreadLocalAccessor for LocaleContext and RequestAttributes"
Add ThreadLocalAccessor for LocaleContext and RequestAttributes
Closes gh-32243
This commit removes the previous implementation in favor of the new
PlaceholderParser. The only noticeable side effect is that the exception
is no longer an IllegalArgumentException, but rather the dedicated
PlaceholderResolutionException.
See gh-9628
This commit provides a rewrite of the parser for properties containing
potentially placeholders.
Assuming a source where `firstName` = `John` and `lastName` = `Smith`,
the "${firstName}-${lastName}" property is evaluated as "John-Smith".
Compared with the existing implementation in PropertyPlaceholderHelper,
the new implementation offers the following extra features:
1. Placeholder can be escaped using a configurable escape character.
When a placeholder is escaped it is rendered as is. This does apply to
any nested placeholder that wouldn't be escaped. For instance,
"\${firstName}" is evaluated as "${firstName}".
2. The default separator can also be escaped the same way. When the
separator is escaped, the left and right parts are not considered as
the key and the default value respectively. Rather the two parts
combined, including the separator (but not the escape separator) are
used for resolution. For instance, ${java\:comp/env/test} is looking
for a "java:comp/env/test" property.
3. Placeholders are resolved lazily. Previously, all nested placeholders
were resolved before considering if a separator was present. This
implementation only attempts the resolution of the default value if the
key does not provide a value.
4. Failure to resolve a placeholder are more rich, with a dedicated
PlaceholderResolutionException that contains the resolution chain.
See gh-9628
See gh-26268
Prior to this commit, the `SimpleCommandLineArgsParser` would reject
"--" arguments as invalid. As reported by the community, the POSIX
utility conventions (Guideline 10) state that
> The first -- argument that is not an option-argument should be
> accepted as a delimiter indicating the end of options.
> Any following arguments should be treated as operands, even if they
> begin with the '-' character.
This commit updates `SimpleCommandLineArgsParser` to not reject "--"
arguments and instead to consider remaining arguments as non-optional.
See gh-31513
This commit updates the WebSocket message broker configuration to stop
setting a thread name prefix for externally defined Executors.
This used to apply to:
* clientInboundChannel with a thread name prefix of
"clientInboundChannel-".
* clientOutboundChannel with a thread name prefix of
"clientOutboundChannel-".
* brokerChannel with a thread name prefix of "brokerChannel-".
Closes gh-32132
This commit harmonizes the configuration of the WebSocket message
broker to use Executor rather than TaskExecutor as only the former
is enforced. This lets custom configuration to use a wider range
of implementations.
Closes gh-32129
This commit makes sure that content within backticks are skipped
when parsing a SQL statement using NamedParameterUtils. This harmonizes
the current behavior of ignoring special characters that are wrapped
in backticks.
Closes gh-31944
This commit improves jsonpath support in WebTestClient by detecting
a suitable json encoder/decoder that can be applied to assert more
complex data structure.
Closes gh-31653
This commit improves JsonPathExpectationsHelper to allow a custom json
path configuration to be defined. The primary objective of a custom
configuration is to specify a custom mapper that can deserialize complex
object structure.
As part of this commit, it is now possible to invoke a Matcher against
a type that holds generic information, using a regular
ParameterizedTypeReference.
Given that the existing constructor takes a vararg of Object, this
commit also deprecates this constructor in favor of formatting the
expression String upfront.
Closes gh-31651
This commit allows EmbeddedDatabaseConfigurer instances to be further
customized if necessary. EmbeddedDatabaseBuilder has a way now to set
a DatabaseConfigurer rather than just a type to provide full control,
or customize an existing supported database type using the new
EmbeddedDatabaseConfigurers#customizeConfigurer callback.
Closes gh-21160
Prior to this commit, the SseBuilder API in WebMvc.fn would only allow
to send Server-Sent Events with `data:` items in them. The spec doesnn't
disallow this and other specifications rely on such patterns to signal
the completion of a stream, like:
```
event:next
data:some data
event:complete
```
This commit adds a new `send()` method without any argument that sends
the buffered content (id, event comment and retry) without data.
Fixes: gh-32270
Although EvaluationContext defines the API for setting and looking up
variables, the internals of the Spring Expression Language (SpEL)
actually provide explicit support for registering functions as
variables.
This is self-evident in the two registerFunction() variants in
StandardEvaluationContext; however, functions can also be registered as
variables when using the SimpleEvaluationContext.
Since custom functions are also viable in use cases involving the
SimpleEvaluationContext, this commit documents that functions may be
registered in a SimpleEvaluationContext via setVariable().
This commit also explicitly documents the "function as a variable"
behavior in the class-level Javadoc for both StandardEvaluationContext
and SimpleEvaluationContext, as well as in the reference manual.
Closes gh-32258
This notably enables Jackson to reflectively call a user-provided
builder class and invoke its declared methods (setters and build) in
a native app.
Closes gh-32238
The cancellation of read and write inactivity tasks was done via
WebSocketHandler#afterConnectionClosed, relying on the WebSocket
library to always invoke the callback.
This change moves the cancellation to the `close` method instead
that in turn is called from DefaultStompSession#resetConnection,
in effect making the cancellation more proactive and aligned with
connection cleanup in DefaultStompSession vs relying on a
subsequent call from the WebSocket library after the connection
is closed.
Closes gh-32195
ConnectionLostException was applies only after the WebSocket library
notified us of a session close. However, read inactivity and heartbeat
send failures are also cases of the connection being lost rather than
closed intentionally.
This commit also ensures resetConnection is called after a heartbeat
write failure, consistent with other places where a transport error
is handled that implies the connection is lost.
See gh-32195
This commit focuses on improving the AOT section on programmatic
registration of additional beans. This makes it more clear that a
`BeanDefinitionRegistry` must be used and that singletons are not
processed.
Closes gh-32240
Closes gh-32241
This commit introduces new HTTP method, Content-Type, and Accept header
request predicates that handle single values. Previously, these
predicates were always dealt with as single-value collections, which
introduced computational overhead.
Closes gh-32244
Previously, RestClientAdapter claimed that it supports request
attributes when, in fact, it does not. This commit updates the
implementation accordingly.
See gh-32232
Schedulers remain strict, just plain executors are lenient on shutdown now.
An early shutdown for executors can be enforced via setStrictEarlyShutdown.
Closes gh-32226
Fix another instance where a LinkedHashMap was initialized with an initial
capacity that would always cause a resize / rehash to occur. Switch to
CollectionUtils.newLinkedHashMap to size the map appropiately for the expected
number of items.
Closes gh-32215
Prior to this commit, the `RequestPredicates` would add new attributes
to the existing request attributes by creating a new `LinkedHashMap`
with the total number of elements as its new initial capacity.
This would not achieve optimal performance as initial resize or rehash
operations could be expected. Consistently using
`CollectionUtils#newLinkedHashMap` avoids this problem.
Closes gh-32201
ServletAttributesMap inherited default implementations of the size
and isEmpty methods from AbstractMap which delegates to the Set returned
by entrySet. ServletAttributesMap's entrySet method made this fairly
expensive, since it would copy the attributes to a List, then use a
Stream to build the Set. To avoid the cost, add implementations of
isEmpty / size that don't need to call entrySet at all.
Additionally, change entrySet to return a Set view that simply lazily
delegates to the underlying servlet request for iteration.
Closes gh-32189
This commit ensures that, when creating a RestClient.Builder from a
RestTemplate, the UriBuilderFactory is only copied if it has been
changed from the default values.
Before this commit, the UriBuilderFactory was effectively alway copied,
resulting in not being able to use a baseUrl.
This commit also introduces a small memory optimization in
DefaultUriBuilderFactory, so that default environment variables are
created lazily.
Closes gh-32180
This commit replaces occurrences of modelAttribitePredicate with modelAttributePredicate
in HandlerMethodValidationException and the associated validator.
Closes gh-32183
As a bit of trivia, Jakarta EL was originally Unified EL, which was
originally JSP EL, which was originally SPEL.
SPEL: Simplest Possible Expression Language
SpEL: Spring Expression Language
So one could say that SPEL inspired SpEL.
This commit introduces a globally applied Checkstyle rule which
enforces the use of class literals for primitive types and void by
forbidding the use of the TYPE constants in Boolean, Character, Byte,
Short, Integer, Long, Float, Double, and Void.
For example, if MyClass uses one of the TYPE constants, the build will
now fail with a message similar to the following.
[ERROR] <...>/MyClass.java:39: Please use class literals for primitives and void -- for example, int.class instead of Integer.TYPE.
This commit improves PersistenceManagedTypesBeanRegistrationAotProcessor
so that it does not attempt to load JPA classes when checking for the
presence of a PersistenceManagedTypes bean. To make it more clear a
check on the presence for JPA has been added to prevent the nested
classes to be loaded regardless of the presence of the bean.
Closes gh-32155
To improve consistency and avoid confusion regarding primitive types
and their wrapper types, this commit ensures that we always use class
literals for primitive types.
For example, instead of using the `Void.TYPE` constant, we now
consistently use `void.class`.
Prior to this commit, SpEL's Indexer incorrectly requested conversion
to wrappers instead of primitives when setting an element in a
primitive array.
This commit addresses this by requesting primitive conversion -- for
example, conversion to `int.class` instead of `Integer.class` when
setting a value in an `int[]` array.
For greater clarity, this commit also switches from using `TYPE`
constants in wrapper classes to primitive class literals -- for
example, from `Integer.TYPE` to `int.class`.
Closes gh-32147
Since SpEL is no longer "in progress", this commit removes the obsolete
InProgressTests class and moves all non-duplicated test cases to other
test classes.
This commit harmonizes SimpleJdbcCall and SimpleJdbcInsert to
consistently use a catalog name if one is set. Previously,
SimpleJdbcInsert only used the catalog name to retrieve database
metadata.
Closes gh-32124
Prior to this commit, only the MethodFilter and ConstructorResolver
functional SPIs in the org.springframework.expression package were
annotated with @FunctionalInterface.
For consistency, this commit designates each of the following
functional SPIs in that package as a @FunctionalInterface as well.
- BeanResolver
- ConstructorExecutor
- MethodExecutor
- MethodResolver
Closes gh-32135
This commit introduces a new method to configure an existing
TaskExecutor in ChannelRegistration. Contrary to
TaskExecutorRegistration, a ThreadPoolTaskExecutor is not necessary,
and it can't be further configured. This includes the thread name
prefix.
Closes gh-32081
Before this commit, the JDK and Jetty connectors do not have any
safeguards against multiple body subscriptions. Such as check has now
been added.
Closes gh-32100
Since the bug in JDK 22-ea builds has been fixed [1], this commit
re-enables the disabled tests.
Verified using: OpenJDK Runtime Environment (build 22-ea+31-2314)
[1] https://bugs.openjdk.org/browse/JDK-8322214
The behavior for the toString() implementation for annotations changed
in JDK 19, per my request to the JDK team (see link below).
Specifically, since JDK 19, the toString() implementation for annotation
proxies created by the JDK started using canonical names instead of
binary names for types.
See https://bugs.openjdk.org/browse/JDK-8281462
Prior to this commit, the `RestTemplate` observation instrumentation
would only record `RestClientException` and `IOException` as errors in
the observation. Other types of errors can be thrown by custom
components, such as `ResponseErrorHandler` and in this case they aren't
recorded with the observation.
Also, the current instrumentation does not create any observation scope
around the execution. While this would have a limited benefit as no
application code is executed there, developers could set up custom
components (such as, again, `ResponseErrorHandler`) that could use
contextual logging with trace ids.
This commit ensures that all `Throwable` are recorded as errors with the
observations and that an observation `Scope` is created around the
execution of the client exchange.
Fixes gh-32060
This commit revises the RequestMappingHandlerMapping implementations in
Spring MVC and Spring WebFlux to ensure that a @Controller class which
implements an interface annotated with @HttpExchange annotations can
inherit the @HttpExchange declarations from the interface or
optionally override them locally with @HttpExchange or
@RequestMapping annotations.
Closes gh-32065
This commit updates the RequestMappingHandlerMapping implementations in
Spring MVC and Spring WebFlux so that mixed @RequestMapping and
@HttpExchange declarations on the same element are rejected.
Note, however, that a @Controller class which implements an interface
annotated with @HttpExchange annotations can still inherit the
@HttpExchange declarations from the interface or optionally override
them locally with @HttpExchange or @RequestMapping annotations.
See gh-31962
See gh-32049
Closes gh-32065
This commit makes sure that, when building a RestClient based on the
configuration of a RestTemplate, the request factory is unwrapped if it
is a InterceptingClientHttpRequestFactory.
Closes gh-32038
This commit ensures that setting the Content-Length through
setHeader("Content-Length", x") has the same effect as calling
setContentLength in the ShallowEtagHeaderFilter. It also filters out
Content-Type headers similarly to Content-Length.
Closes gh-32039
This commit updates the RequestMappingHandlerMapping implementations in
Spring MVC and Spring WebFlux so that multiple @HttpExchange
declarations on the same element are rejected.
Closes gh-32049
If multiple request mapping annotations are discovered, Spring MVC and
Spring WebFlux now log a warning similar to the following (without
newlines).
Multiple @RequestMapping annotations found on
void org.example.MyController.put(), but only the first will be used:
[
@org.springframework.web.bind.annotation.PutMapping(consumes={}, headers={}, name="", params={}, path={"/put"}, produces={}, value={"/put"}),
@org.springframework.web.bind.annotation.PostMapping(consumes={}, headers={}, name="", params={}, path={"/put"}, produces={}, value={"/put"})
]
Closes gh-31962
Prior to this commit, the alias resolution error message in
SimpleAliasRegistry was misleading.
When a resolution conflict is detected, the IllegalStateException
thrown by resolveAliases(...) now states that the resolved alias is
already registered for an `existingName` instead of the `registeredName`.
See gh-31353
Closes gh-32025
This commit improves SimpleAliasRegistryTests in the following ways.
- Some existing methods have been split up into smaller test methods
which focus on a single use case.
- The use of Mockito mocks has been replaced by a hand-crafted
StubStringValueResolver which ensures that existing aliases and names
are not accidentally replaced by null thereby removing their removing
there mappings inadvertently.
- Several test methods now include inline comments that document the
current state of the aliasMap in order to clarify what is happening
behind the scenes in the ConcurrentHashMap.
- Several test methods warn that the current expectations are based on
ConcurrentHashMap iteration order!
- New @ParameterizedTest which is currently @Disabled but
demonstrates that complex use cases involving placeholder replacement
can be supported consistently -- regardless of the values of the
aliases involved -- but only if alias registration order is honored.
Closes gh-31353
This commit documents the following Spring properties in the reference
manual.
- spring.aot.enabled
- spring.cache.reactivestreams.ignore
- spring.classformat.ignore
- spring.context.checkpoint
- spring.context.exit
Closes gh-31987
This commit updates ContentRequestMatchers#multipartData
Javadoc to mention Tomcat fork of Commons FileUpload library
instead of the original variant.
It also adds a similar note to
ContentRequestMatchers#multipartDataContains.
Closes gh-31988
ResponseEntityExceptionHandler should not set the exception attribute
when there is a response body, and the response is fully handled.
Closes gh-31541
This commit introduces support for a Spring property named
`spring.context.expression.maxLength`. When set, the value of that
property is used internally in StandardBeanExpressionResolver to
configure the SpelParserConfiguration used when evaluating String
values in bean definitions, @Value, etc.
Closes gh-31952
This change moves container element properties from ParameterErrors
to base class ParameterValidationResult, and makes that support
independent of whether violations are nested within a container
element bean or through constraints on container elements, e.g.
`List<@NotBlank String>`.
Closes gh-31887
This is able to resolve the original method even if no bridge method has been generated at the same class hierarchy level (a known difference between the Eclipse compiler and regular javac).
Closes gh-21843
Includes TypeVariable bypass for reflection-free annotation retrieval.
Includes info log message for annotation attribute retrieval failure.
Closes gh-27182
This commit adds CORS support for Private Network Access
by adding an Access-Control-Allow-Private-Network response
header when the preflight request is sent with an
Access-Control-Request-Private-Network header and that
Private Network Access has been enabled in the CORS
configuration.
See https://developer.chrome.com/blog/private-network-access-preflight/
for more details.
Closes gh-28546
This commit makes sure to resolve placeholders in request mappings
using the EmbeddedValueResolver of the current WebApplicationContext.
To avoid retrieving the context too often, we check for the presence of
the standard placeholder prefix.
Closes gh-26795
To align with the existing processInjection() method in
AutowiredAnnotationBeanPostProcessor, this commit introduces an analogous
method in CommonAnnotationBeanPostProcessor.
Closes gh-31956
This commit implements Cookie support in WebFlux without any workaround
as now all supported servers have the SameSite feature enabled.
Closes gh-31954
Includes differentiation between lenient and fixed execution.
Includes default time zone resolution from scheduler-wide Clock.
Closes gh-19475
Closes gh-31948
Prior to this commit, the `HandlerMappingIntrospector` would comparea
request with a cached request by using `String#matches` on their String
URI. This could lead to `PatternSyntaxException` exceptions at runtime
if the request URI contained pattern characters.
This commit fixes this typo to use `String#equals` instead.
Fixes gh-31937
This commit updates the description of RequestHandledEvent to avoid
providing a misleading status as the absence of a failure logs OK which
can be inaccurate.
Closes gh-27595
This commit adds Javadoc to the `getContentLength` method of
`MockHttpServletResponse` to reflect that it gets its value from the
HTTP response header.
Closes gh-31833
This commit adds a functional style registration of an application
listener for a particular event. Rather than introducing another method
at the ConfigurableApplicationContext interface level, this commit
provides a factory method in GenericApplicationListener.
Closes gh-21411
Prior to this commit, the `DefaultScheduledTaskObservationConvention`
would fail as it tried to add a `KeyValue` to the observation context
that is `null`. This is rejected by the observation registry and should
be prevented. This happened when registered scheduled methods were
lambdas or part of anonymous classes. Those types do not have a
canonical name and return `null` as a value there.
This commit ensures that for these cases, the default convetion uses a
`"ANONYMOUS"` value as the `"code.namespace"` keyvalue.
Fixes gh-31918
Upgrading leads to to WebClientIntegrationTests to fail with Jetty and
the build does not complete properly. This commit reverts the upgrade.
See gh-31931
* pr/31916:
Upgrade copyright year of changed files
Polish "Replace if with switch where feasible"
Replace if with switch where feasible
Use Map.computeIfAbsent() where feasible
Polish "Use Object.equals() where feasible"
Use Object.equals() where feasible
Polish "Use diamond operator where feasible"
Use diamond operator where feasible
Use auto boxing and unboxing where feasible
Use enhanced for loop where feasible
Polish "Use text block where feasible"
Use text block where feasible
Polish "Use String.repeat() where feasible"
Use String.repeat() where feasible
Polish "Remove unnecessary final modifier"
Remove unnecessary final modifier
Closes gh-31916
This commit fixes the Hibernate dialect lookup for SQLServer as it was
previously using a dialect that has been deprecated. In recent
versions, the standard SQLServerDialect is the one we should be using.
Closes gh-31896
Prior to this commit, the `ForwardedHeaderFilter` and the forwarded
header utils would throw `IllegalArgumentException` and
`IllegalStateException` when request headers are invalid and cannot be
parsed for Forwarded handling.
This commit aligns the behavior with the WebFlux counterpart by
rejecting such requests with HTTP 400 responses directly.
Fixes gh-31842
This commit fixes the Hibernate dialect lookup for Oracle as it was
previously using a dialect that has been moved and deprecated to a
separate project. In recent versions, the standard OracleDialect is the
one we should be using.
Closes gh-31892
This commit fixes the Hibernate dialect lookup for MySQL as it was
previously using a deprecated dialect that has been removed in the most
recent Hibernate version.
Closes gh-31889
After the updates to MethodValidationAdapter in commit d7ce13 related
to method validation on element containers, we also need to adjust
the checks in HandlerMethod when method validation applies.
See gh-31746
This commit restores support for Kotlin extensions in
web handlers, and adds support for invoking reflectively
suspending extension functions, as well as the other
features supported as of Spring Framework 6.1 like
value classes and default value for parameters.
Closes gh-31876
The goal for #31530 was to support bean validation on Set and other
method parameters that are containers of value(s) for which there is
a registered Jakarta Validation ValueExtractor.
Unfortunately, bean validation does not expose the unwrapped value
for a Path.Node, which we need for a method parameter in order to
create a BindingResult for the specific bean within the container,
and the leafBean that we tried to use is really the node at the
very bottom of the property path (i.e. not what we need).
This change removes the use of beanLeaf, restores the logic as it
was before, adds support for arrays, and a new test class for
scenarios with cascaded violations.
See gh-31746
Prior to this commit, the `WebHttpHandlerBuilder` would only configure
a custom observation convention if there is a single convention in the
application context. It would other wise use the default.
This commit aligns with the previous Spring Boot behavior where multiple
conventions setups are rejected as invalid with
`NoUniqueBeanDefinitionException`.
Fixes gh-31864
This commit refines InvocableHandlerMethod (both Servlet and
Reactive variants) in order to support annotated property
accessors as they translate into regular Java methods, instead
of throwing a NullPointerException.
Closes gh-31856
DataBinder should skip any jakarta.validation.Validator yielding
to method validation when that is expected. This change improves
the check to skip by unwrapping the validator from in a
SmartValidator before checking if it is for bean validation.
Closes gh-31711
Method validation needs to be used for a container such as a List or
Map, but until now we were only checking for a List container.
Moreover, in gh-31530 we improved method validation to also cover
any Collection.
This change aligns with HandlerMethod check for when method validation
applies with the underlying ability of method validation.
This commit improves JettyWebSocketHandlerAdapter::copyByteBuffer so
that it allocates a buffer large enough for the remaining bytes
contained in the source, instead of allocating one with the capacity of
the source.
Closes gh-31857
This commit updates the JSON writers to use a deterministic order for
arrays. Previously, the order could change with the same content,
breaking caching.
Closes gh-31852
This commit ensures that the capacity of the remainder buffer after a
split operation is set directly on the field. Calling capacity(int)
caused a new buffer to be allocated.
Closes gh-31848
This commit builds on top of changes made in gh-29775 and gh-31737.
Before this change, we would allocate several byte arrays even in cases
of known request size. This could decrease performance when getting the
cached content as it requires merging several arrays and data is not
colocated in memory.
This change ensures that we create a `FastByteArrayOutputStream`
instance with the known request size so that the first allocated segment
can contain the entire content.
If the request size is not know, we will default back on the default
allocation size for the `FastByteArrayOutputStream`.
Closes gh-31834
Refining the change from 43700302c6 so that
we consistently pick a PathPatternParser (a) if it is provided, and (b)
if both PathPatternParser and PathMatcher are not provided. Also applying
the same in the mutate builder.
See gh-31662
This commits allows ValueCodeGenerator$Delegate implementations to be
loaded from `META-INF/spring/aot.factories` and considered for code
generation of bean definition property values. This default behavior
in DefaultBeanRegistrationCodeFragments can be customized as usual.
Closes gh-31427
This commit introduces ValueCodeGenerator and its Delegate interface
as a way to generate the code for a particular value. Implementations
in spring-core provides support for common value types such a String,
primitives, Collections, etc.
Additional implementations are provided for code generation of bean
definition property values.
Closes gh-28999
Prior to this commit, the AnnotationsScanner used in the
MergedAnnotations infrastructure found duplicate annotations on methods
within multi-level interface hierarchies.
This commit addresses this issue by scanning methods at a given level
in the interface hierarchy using ReflectionUtils#getDeclaredMethods
instead of Class#getMethods, since the latter includes public methods
declared in super-interfaces which will anyway be scanned when
processing super-interfaces recursively.
Closes gh-31803
This commit matches the behavior of the core container when it
invokes a custom init or destroy method. If the custom method is an
interface implementation, the core container attempts to invoke the
method that's defined on the interface. This commit makes sure to also
register a hint for the interface method.
Closes gh-31819
Prior to this commit, the WebClient observations would have a specific
lifecycle where the observation context is build with a
`ClientRequest.Builder` as tracing needs to add an outgoing request
header before the request is made immutable.
With this setup, the metrics observation handler processes the start
event by increasing the "http.client.requests.active" counter and
collecting tags at this point. Because then the immutable request is not
yet fully built or set on the context, the keyvalues collected by the
observation convention at that point can be incomplete.
This commit ensures that a request is always made available in the
context, even if it is updated right after the observation start. The
only difference between the two should be additional tracing headers and
a request attribute holding the current observation context.
Closes gh-31702
This commit documents the fact that any (Unchecked)IOExceptions or
HttpMessageNotReadableExceptions thrown from the error handler will be
wrapped in a RestClientException.
Closes gh-31783
Prior to this commit, the `ConcurrentReferenceHashMap#restructure`
operation would null out the entire references array before starting the
restructuring operation (in case resizing is not necessary).
This could cause at runtime race conditions where a lookup operation
would return null, when the value is actually cached but not accesible
during the restructuring phase.
This commit ensures that, when resizing is not required, a new reference
list is built (purged of null entries) and then assigned to the
reference array. This way, concurrent reads will not return null for
existing entries and there are less chances of re-calculating cache
entries during the restructuring phase.
Closes gh-31008
Required by Spring Security to complete work on
https://github.com/spring-projects/spring-security/issues/14128
The setCache and resetCache methods used from createCacheFilter are now
public. Generally they don't need to be used outside of the Filter if
only making checks against the current request. Spring Security, however,
makes additional checks against requests with alternative paths.
Commit 33454a4007 introduced a regression in Comparators.nullsLow() and
Comporators.nullsHigh().
This commit updates the code so that nullsLow() sorts null values lower
than non-null values and nullsHigh sorts null values higher than
non-null values.
See gh-25478
Closes gh-31808
This commit adds ahead of time support for @Resource on fields and
methods. Lookup elements are discovered and code is generated to replace
that introspection at runtime.
Closes gh-29614
Introduce ShardingKeyDataSourceAdapter to get shard connections.
This commit introduces a DataSource proxy, that changes the behavior of the getConnection method to use the `createConnectionBuilder()` api to acquire direct shard connections. The shard connection is acquired by specifying a `ShardingKey` that is correspondent to the wanted shard.
While it is not easily possible to create a ConcurrentTaskScheduler
with no scheduled executor, DefaultManagedTaskScheduler has a default
constructor that does that as the JNDI lookup happens in the regular
afterPropertiesSet callback. If such an instance is created manually,
it can throw an unhelpful NullPointerException if one attempts to
schedule a task.
This commit updates ConcurrentTaskScheduler to flag that the scheduled
executor could be `null` and check if that's the case before using it.
This now throws a dedicated exception that should hopefully provide
better context for those upgrading.
See gh-27914
Closes gh-31751
This file is incomplete and has outdated content. Given that several
core committers are not even listed, it does not seem to serve a
valid purpose anymore.
Closes gh-31740
Previously, if an annotation processors was present in the classpath
it was executed as part of tests using `TestCompiler`.
This commit updates `TestCompiler` to always set the annotation
processors to use. By default, this sets an empty list which does not
use annotation processing.
Closes gh-31791
Includes special support for a read-only DataSource in addition to the regular target DataSource, avoiding the overhead of switching the Connection's read-only flag at the beginning and end of every transaction.
Closes gh-29931
Closes gh-31785
Closes gh-19688
Closes gh-21415
In gh-30549 we applied changes to the `DefaultPersistenceUnitManager` to
use the `ValidationMode.CALLBACK` to better detect invalid validation
setup and enforce bootstrap failures in those cases.
Unfortunately, doing so disables the detection of validation annotation
on entities during the schema creation phase. This is a known Hibernate
issue. This commit reverts this change until HHH-12287 is fixed.
Fixes gh-31726
This commit fixes a bug in DefaultPartHttpMessageReader's
MultipartParser, due to which the last token in a part window was not
properly indicated.
Closes gh-30953
Work performed in conjunction with gh-30941 resulted in a regression.
Specifically, prior to Spring Framework 6.1 a locally declared
@ComponentScan annotation took precedence over @ComponentScan
meta-annotations, which allowed "local" configuration to override
"meta-present" configuration.
This commit modifies the @ComponentScan search algorithm so that
locally declared @ComponentScan annotations are once again favored
over @ComponentScan meta-annotations (and, indirectly, composed
annotations).
See gh-30941 Closes gh-31704
Search for : assertThat\((.+).isEmpty\(\)\).isTrue\(\)
Replace with : assertThat($1).isEmpty()
Search for : assertThat\((.+).isEmpty\(\)\).isFalse\(\)
Replace with : assertThat($1).isNotEmpty()
Closes gh-31758
Search for : assertThat\((.+)\.equals\((\w+)\)\)\.isTrue\(\)
Replace with : assertThat($1).isEqualTo($2)
Search for : assertThat\((.+)\.equals\((\w+)\)\)\.isFalse\(\)
Replace with : assertThat($1).isNotEqualTo($2)
Closes gh-31763
Search for : assertThat\((.+)\.contains\((.+)\)\)\.isTrue\(\)
Replace with : assertThat($1).contains($2)
Search for : assertThat\((.+)\.contains\((.+)\)\)\.isFalse\(\)
Replace with : assertThat($1).doesNotContain($2)
Closes gh-31762
This commit partially reverts 39786e4790
and c5c843696b, as the approach taken did
not take into account request predicates that query request attributes,
including path variables.
Closes gh-31732
This commit introduces a toString() overload in
FastByteArrayOutputStream that accepts a Charset in order to mirror the
method that was introduced in ByteArrayOutputStream in JDK 10,
including a special case for when a single buffer is in use internally
to avoid the need to resize.
This commit also updates getContentAsString() in
ContentCachingRequestWrapper to use this new toString(Charset) method.
Closes gh-31737
This commit ensures that the RestClient uses the
IntrospectingClientHttpResponse to verify whether the response has a
body, and return null if it does not.
See gh-12671
Closes gh-31719
The getContentAsString method was originally added in d9b8826 to avoid
the extra copying inherent to calling ByteArrayOutputStream.toByteArray;
however, in f83c609 the class was updated to instead use
FastByteArrayOutputStream, and in the process the extra copy was brought
back when getContentAsString was changed to call toByteArray.
Switch to calling toByteArrayUnsafe, a method provided by
FastByteArrayOutputStream, which avoids the extra copy; since we
immediately pass the byte array to the String constructor, and it isn't
accessed anywhere else, the usage is safe.
See gh-31731
This commit allows to define a bean order programmatically
at bean definition level (functional equivalent of
`@Order`).
If specified, the order attribute defined at bean
definition level overrides potential values set with
`@Order`.
See gh-30849
Prior to this commit, regressions were introduced with gh-31417:
1. the observation keyvalues would be inconsistent with the HTTP response
2. the observation scope would not cover all controller handlers, causing
traceIds to be missing
The first issue is caused by the fact that in case of error signals, the
observation was stopped before the response was fully committed, which
means further processing could happen and update the response status.
This commit delays the stop event until the response is committed in
case of errors.
The second problem is caused by the change from a `contextWrite`
operator to using the `tap` operator with a `SignalListener`. The
observation was started in the `doOnSubscription` callback, which is too
late in some cases. If the WebFlux controller handler is synchronous
non-blocking, the execution of the handler is performed before the
subscription happens. This means that for those handlers, the
observation was not started, even if the current observation was
present in the reactor context. This commit changes the
`doOnSubscription` to `doFirst` to ensure that the observation is
started at the right time.
Fixes gh-31703
Fixes gh-31706
This commit updates MetadataNamingStrategy to quote an ObjectName
attribute value if necessary. For now, only the name attribute is
handled as it is usually a bean name, and we have no control over
its structure.
Closes gh-23608
This commit moves the condition used by `@DisabledInAotMode` to a
concrete implementation rather than using `@DisabledIf` as it causes
build initialization in a native image.
Closes gh-31705
This commit removes a list of hardcoded servers and version as this is
bound to get outdated and the reference guide/wiki is a more suitable
place for this.
This changes ensures RequestMappingInfo uses PathPatternParser by default
as all AbstractHandlerMapping implementations do as of 6.0.
RequestMappingInfo instances are typically created internally and aligned with
the RequestMappingHandlerMapping in terms of path mapping options.
If a RequestMappingInfo is registered programmatically, the caller needs to also
ensure they are aligned. However, if the two should be aligned by default.
Closes gh-31662
Prior to this commit, the TestContextManager logged an exception from a
TestExecutionListener at WARN level except in prepareTestInstance()
where such an exception was logged at ERROR level (except for a skipped
exception which is logged at INFO level).
For consistency, this commit modifies TestContextManager so that it
always logs non-skipped exceptions from TestExecutionListeners at WARN
level.
Closes gh-31688
This commit supports the scroll() and scroll(ScrollMode) methods from
Hibernate's Query API in SharedEntityManagerCreator's query-terminating
methods set.
Closes gh-31682
This commit makes sure to initialize any HandlerMapping defined in the
context when searching for resource handlers. Previously, the detection
algorithm was looking up for `SimpleUrlHandlerMapping` while the
declared target type in WebMvcConfigurationSupport is HandlerMapping.
If the application uses lazy initialization, the lookup algorithm would
not force that bean to be initialized.
Closes gh-25488
Prior to this commit, any time an aborted/skipped exception was thrown
by a TestExecutionListener, the TestContextManager unconditionally
logged the exception at WARN level -- or ERROR level for
prepareTestInstance() callbacks.
Regarding the latter, an aborted/skipped exception is certainly not an
ERROR, and in general the associated log output is very verbose
(including a stack trace) and not something the user should be warned
about it.
To improve the user experience, this commit revises TestContextManager
so that it logs such exceptions at INFO level.
Specifically, the following types of exceptions are considered
aborted/skipped exceptions.
- JUnit Jupiter: org.opentest4j.TestAbortedException
- JUnit 4 org.junit.AssumptionViolatedException
- TestNG: org.testng.SkipException
Closes gh-31479
The documentation currently states that Inversion of Control (IoC) and
Dependency Injection (DI) are the same thing. Although the two terms
are related, they are not synonymous: DI is a type of IoC.
I believe this change is important because using the terms
interchangeably really muddies the water about the meaning of these two
fundamental concepts of software frameworks.
Closes gh-31679
Prior to this commit, `ExchangeFilterFunction` could only get the
current observation from the reactor context. This is particularly
useful when such filters want to add KeyValues to the observation
context.
This commit makes this use case easier by adding the context of the
current observation as a request attribute. This also aligns the
behavior with other instrumentations.
Fixes gh-31609
The JDBC API that retrieves a proedure or a function allows to specify
patterns for the schema and the procedure name. So far, we've called
this API with the value as is, which does not work if either contains
a wildcard characters that need to be escaped.
This commit updates GenericCallMetadataProvider to escape, if necessary,
the schema or procedure name using the search string escape from the
database metadata.
Closes gh-22725
Prior to this commit, AspectJExpressionPointcut doesn't fall back to original method if `!@annotation()` is used, it can cause false positive result.
Fix GH-27119
Prior to this commit, the Jackson 2.x encoders, in case of encoding a
stream of data, would first release the `ByteArrayBuilder` and then the
`JsonGenerator`. This order is inconsistent with the single value
variant (see `o.s.h.codec.json.AbstractJackson2Encoder#encodeValue`) and
invalid since the `JsonGenerator` uses internally the
`ByteArrayBuilder`.
In case of a CSV Encoder, the codec can buffer data to write the column
names of the CSV file. Writing an empty Flux with this Encoder would not
fail but still log a NullPointerException ignored by the reactive
pipeline.
This commit fixes the order and avoid such issues at runtime.
Fixes gh-30493
This commit fixes a regression introduced by gh-21139
via the usage of Kotlin reflection to invoke HTTP
handler methods. It ensures that kotlin.Unit is treated
as void by returning null.
It also polishes CoroutinesUtils to have a consistent
handling compared to the regular case, and adds related
tests to prevent future regressions.
Closes gh-31648
Includes removal of evict step on pipeline exception, retaining a previous cache value and avoiding an incomplete key (for consistency with non-reactive caching).
Closes gh-31626
This commit extract spring-related links and recurring external links
into asciidoctor attributes to be used by the Antora toolchain.
It notably homogenizes links to:
- IETF RFCs
- Java Community Process JSRs
- the Java API Documentation (on the Java 17 version)
- Kotlin documentations (on the Kotlinlang.org version)
- the Spring Boot reference guide (on the `html` version)
This commit also reworks most link attributes to follow a
Project-Category-Misc syntax. For example, `spring-boot-docs` rather
than `docs-spring-boot`.
Finally, it makes an effort to clean up remainders from the previous
documentation toolchain, namely the `docs/asciidoc` folder and
`modules/ROOT/pages/attributes.adoc` file.
Closes gh-26864
Closes gh-31619
In order to prevent leaks of large amounts of non-heap
memory (and potential other efficiency and performance side
effects), this commit updates ResourceUtils#useCachesIfNecessary
to leave the caching flag to its JVM default value for instances
of JarURLConnection.
The previous behavior was originally introduced via gh-9316 and
gh-13755 to avoid I/O failure during webapp hot reloading in
Servlet containers. This is not a popular deployment mode anymore
and we have not been able to reproduce the original issue with
a Java 17 JVM and Tomcat 10.
Closes gh-30955
Legacy EJB attributes are ignored since 6.0 due to being bound to a plain JndiObjectFactoryBean - but can still be declared now, e.g. when validating against the common versions of spring-jee.xsd out there.
Closes gh-31627
The description is for WebFlux, but the link points to WebFlux unit
testing support.
This commit changes the link to point the the WebFlux chapter.
Closes gh-31632
Adding generated code in the default package is not supported as we
intend to import it, most probably from another package, and that is
not supported. While this situation is hard to replicate with Java,
Kotlin is unfortunately more lenient and users can end up in that
situation if they forget to add a package statement.
This commit checks for the presence of a valid package, and throws
a dedicated exception if necessary.
Closes gh-31628
Prior to this commit, the getResource() methods in PathResourceResolver
implementations allowed an exception thrown from Resource#getURL() to
propagate instead of logging a warning about the missing resource as
intended.
This commit modifies the getResource() methods in PathResourceResolver
implementations so that the log messages include the output of the
toString() implementations of the underlying resources instead of their
getURL() implementations, which may throw an exception.
Furthermore, logging the toString() output of resources aligns with the
existing output for "allowed locations" in the same log message.
Note that the toString() implementations could potentially also throw
exceptions, but that is considered less likely.
Closes gh-31623
This commit makes sure that the per-operation execution context for
caching and event listening does not recreate the default internal
delegates, but rather get initialized with a shared state.
This reduces the number of instances created per operation execution,
reducing the GC pressure as a result. This also makes sure that any
cache, such as the one in StandardTypeLocator, is reused.
Closes gh-31617
This commit introduces a ConvertibleClientHttpResponse type that
extends ClientHttpResponse, and that can convert the body to a desired
type. Before this commit, it was not easy to use the configured HTTP
message converters in combination with RestClient::exchange.
Closes gh-31597
This commit allows to terminate the JVM when the
-Dspring.context.exit=onRefresh property is set,
which can be useful for AppCDS training run in order
to get most of the AppCDS cache without starting the
beans.
Closes gh-31595
This commit adds a link in the package-overview pages of KDoc and
Javadoc, pointing to the other documentation's own page.
In order for local tests to work, the build has been slightly modified
to align with the directory structure in the distributed documentation
zip (and consequently with that of the deployed documentation website).
Lastly, the javadoc build was fixed to include the `overview.html` again
in the resulting HTML index, since this is where the KDoc link is added.
See gh-28055
Closes gh-31587
This commit clarifies that the annotation is used to capture events that
are fired from the test `Thread` or descendant threads, since the test
framework uses `InheritableThreadLocal` to store captured events now.
See gh-31079
See gh-30020
This commit ensures that not every OutputStream.write gets written as a
separate chunk, by buffering the written data in a BufferedOutputStream.
In some cases, a large quantity of small writes would result in many
sent chunks.
Closes gh-31361
Prior to this commit, the JMS listener observations would only cover the
actual listener invocation, but not the error handling phase. This means
that all errors (including the handled ones) are marked as errors in the
observation and that the observation is not current anymore when error
handling happens.
This commit aligns the behavior with the other Spring Framework
instrumentations and ensures that the error handling phase is fully part
of the observation recording.
Closes gh-31559
This commit updates PersistenceManagedTypesBeanRegistrationAotProcessor
to register reflection hints for `@EmbeddableInstantiator` annotations
available as of Hibernate 6.0 when needed.
Related tests will be added in
https://github.com/spring-projects/spring-aot-smoke-tests.
Closes gh-31534
Allows Kotlin caller to get a non-nullable property,
using a default value when the property is not set.
A method already exists on PropertyResolver which does this,
but takes a Class parameter.
The extension method can eliminate the parameter via reified type,
similar to the other extension methods which exist already.
Closes gh-31523
This commit documents that the "error" key in Micrometer Observations
should be preferred over the legacy "exception" one. Right now the
information is duplicated but we might remove the deprecated one in the
future.
Closes gh-31514
This commit ensures that the StreamingHttpOutputMessage.Body.repeatable
flag is set in message converters for bodies that can be written
repeatedly.
Closes gh-31516
See gh-31449
This reverts commit 93206c3f6e and updates
the related test to only rely on the fact the compiler fails. Relying
on a message will not work and the status code can be implementation
independent according to its javadoc.
Closes gh-31536
The me.champeau.mrjar Gradle plugin causes non-existent libraries to be
added to the Eclipse classpath, such as:
<classpathentry kind="lib" path="/workspaces/spring-framework/spring-core/build/classes/kotlin/java21">
<attributes>
<attribute name="gradle_used_by_scope" value="java21"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
This results in build errors in Eclipse IDE like the following.
Project 'spring-core' is missing required library:
'/workspaces/spring-framework/spring-core/build/classes/kotlin/java21'
This commit filters those and removes them.
Commit d3fba6d49b introduced built-in pattern matching support for
method names in ControlFlowPointcut; however, it was still cumbersome
to extend ControlFlowPointcut with support for regular expressions
instead of simple pattern matching.
To address that, this commit introduces a variant of isMatch() that
accepts the pattern index instead of the pre-resolved method name
pattern. The default implementation retrieves the method name pattern
from the methodNamePatterns field and delegates to isMatch(String, String).
Subclasses can override the new isMatch(String, int) method to support
regular expressions, as can be seen in the example
RegExControlFlowPointcut class in ControlFlowPointcutTests.
See gh-31435
This commit fixes code generation when an indexed constructor argument
value is null as the method is overloaded and need the value to be
cast to `Object`.
Closes gh-31508
Prior to this commit, ControlFlowPointcut supported a single method
name which was matched exactly. Although it was possible to extend
ControlFlowPointcut to add support for pattern matching, it was a bit
cumbersome.
To address that, this commit introduces built-in pattern matching
support for method names in ControlFlowPointcut, analogous to the
pattern matching support in NameMatchMethodPointcut.
Specifically, a user can provide one or more method name patterns, and
the patterns will be matched against candidate method names using OR
semantics.
By default, the matching algorithm delegates to
PatternMatchUtils.simpleMatch(), but this can be overridden in
subclasses by overriding the new protected isMatch() method.
Closes gh-31435
Previously, ConstructorResolver would reject any candidate if the
parameter is `null`. The reason for that is that null does not carry
any type and the matching algorithm would systematically fail for that
argument.
This commit adds an extra check, and several tests, to validate that
a null value is taken into account.
Closes gh-31495
Prior to this commit, @SpringJUnitConfig and @SpringJUnitWebConfig
did not declare `loader` attributes that alias @ContextConfiguration's
`loader` attribute. Consequently, it was not possible to configure a
custom ContextLoader via those annotations.
The lack of those `loader` attributes was an oversight, and this commit
introduces them to support custom ContextLoader configuration directly
via the @SpringJUnitConfig and @SpringJUnitWebConfig annotations.
Closes gh-31498
This commit surfaces the ETag generation feature for both
`ResourceHttpRequestHandler` and `ResourceWebHandler` on their
respective `ResourceHandlerRegistration` for easier configuration.
See gh-29031
This commit makes ControlFlowPointcut more open to subclasses by:
1. Making the ControlFlowPointcut#clazz field protected.
2. Making the ControlFlowPointcut#methodName field protected.
3. Introducing a protected incrementEvaluationCount() method.
Closes gh-27187
This commit introduces the maxParts and maxPartSize properties to
PartEventHttpMessageReader, which can be used to limit the amount of
parts, and maximum part size respectively.
Closes gh-31343
Previously the documentation assumed that the readers knew how to use
the X-Forwarded-* headers. This commit documents details & examples
of how to use the X-Forwarded-* headers.
See gh-31491
Since we do not yet have support for registering resource hints for
classpath location patterns, we have decided to explicitly skip such
resources and log a warning to inform users that they need to manually
supply resource hints for the exact resources needed by their
application.
This commit applies this change for @PropertySource and
@TestPropertySource.
See gh-31162
Closes gh-31429
This commit harmonizes AnnotationDrivenBeanDefinitionParser so that it
does not instantiate a property value while parsing the element. Rather,
it creates an inner bean definition so that the property is created
during the refresh phase.
Closes gh-31472
This commit refines MaxUploadSizeExceededException
handling in order to translate to a "413 Payload Too Large"
status code instead of "500 Internal Server Error", with
related ProblemDetail body.
Closes gh-27170
Prior to this commit, the `ResourceHttpRequestHandler` would support
HTTP caching when serving resources, but only driving it through the
`Resource#lastModified()` information.
This commit introduces an ETag generator function that can be configured
on the `ResourceHttpRequestHandler` to dynamically generate an ETag
value for the Resource that is going to be served.
Closes gh-29031
This commit improves the exception that is thrown when a particular
source class cannot be parsed. Previously, the message would include
the root configuration class, which may not be the class that
actually failed as parsing can trigger component scan. There's now
a dedicated catch that generates an exception message that includes the
class that is currently parsed.
Closes gh-31146
We can't upgrade to Eclipselink 4 as it would change the baseline that
this generation uses. However, there is a recent release in the current
line that adds compatibility with recent JDKs.
See gh-31078
This commit removes the "plain old class" bit of the documentation as
it may be confusing. The gist of it is that it must be a bean but not
annotated with `@Configuration` so the updated sentence states exactly
that.
Closes gh-29957
This commit introduces additional tests for "quoted identifier" support
in SimpleJdbcInsert when the schema itself is defined using quoted
identifiers -- for example, to use keywords as column names.
See gh-31208
This commit improves the handling of IllegalArgumentException in
SimpleInstantiationStrategy. Previously, only arguments mismatch were
handled but the exception can also be thrown if the factory instance
does not match the target method.
Closes gh-28897
This commit adds a test and polishing for a change in
AbstractNamedValueMethodArgumentResolver erroneously committed
with (unrelated) commit e57b942b.
If an argument becomes null after conversion and a default value is
applied, that default value should also pass through conversion.
Closes gh-31336
This commit adds a repeatable property to
StreamingHttpOutputMessage.Body, indicating that the body can be written
multiple times. In HttpComponentsClientHttpRequest, this property is
exposed via org.apache.hc.core5.http.HttpEntity.isRepeatable, to allow
for redirects.
Closes gh-31449
Prior to this commit, configuring a Servlet filter in MockMvc with a
defined mapping would only consider "/*" as a catch-all pattern.
This commit relaxes this rule by also accepting "*" mappings.
Closes gh-28041
This commit re-generates the protobuf Java classes with a recent version
of the protoc binary and adds JMH benchmarks that exercise the message
converter for both the reading and writing cases.
See gh-29496
Use the helper to reduce logging when an @ExceptionHandler fails
to write to the response due to a network failure where the client
has gone away.
Closes gh-26181
Prior to this commit, the NestedTestCase resulted in errors during our
AOT end-to-end integration tests since it did not comply to our "*Tests"
naming convention.
See gh-29122
This commit applies @DisabledInAotMode to test classes in the
spring-test module that will never be able to be processed for AOT
optimizations.
Test classes that fail for reasons that can potentially be addressed in
a future version of the framework have not been annotated with
@DisabledInAotMode.
See gh-29122
Although it should not happen in theory, sometimes a test class is
discovered more than once via the TestClassScanner in our integration
tests. When it does happen in our tests, the two Class objects have the
same fully-qualified class name but represent different classes which
leads to failures due to incorrect associations between test class
names and their MergedContextConfiguration.
To address this, this commit modifies TestContextAotGenerator so that
it skips duplicate test class names.
This commit adds Coroutines support for `@Cacheable`.
It also refines SimpleKeyGenerator to ignore Continuation
parameters (Kotlin does not allow to have the same method
signature with both suspending and non-suspending variants)
and refines
org.springframework.aop.framework.CoroutinesUtils.awaitSingleOrNull
in order to wrap plain value to Mono.
Closes gh-31412
This commit introduces @DisabledInAotMode in the TestContext
framework to support the following use cases.
- Disabling AOT build-time processing of a test ApplicationContext --
applicable to any testing framework (JUnit 4, JUnit Jupiter, etc.).
- Disabling an entire test class or a single test method at run time
when the test suite is run with AOT optimizations enabled -- only
applicable to JUnit Jupiter based tests.
Closes gh-30834
This commits makes sure that a bean that produces an array can be
processed ahead of time. If the request target type is an array, its
component type is used.
Closes gh-31426
This commit improves compatibility with the core container when running
in AOT mode by adding support for generic constructor argument values.
Previously, these were ignored altogether. We now have code generation
support for them as well as resolution that is similar to what
AbstractAutowiredCapableBeanFactory does in a regular runtime.
This commit also improves AOT support for XML bean configurations by
adding more support for TypedStringValue and inner bean definitions.
Closes gh-31420
Since the Spring WebFlux HTTP server instrumentation has been moved from
the `WebFilter` to the `HttpWebHandlerAdapter`, we need to apply similar
changes there.
See gh-31417
This commit adds support for TypeStringValue when generating AOT code.
If the value does not specify an explicit type, it's specified as is.
Otherwise, the TypeStringValue instance is restored via the appropriate
code generation.
Closes gh-29074
This commit reintroduces a deprecated ReactorResourceFactory in
org.springframework.http.client.reactive package that extends
the one in org.springframework.http.client package to avoid an
API breaking change and to provide a smoother upgrade experience.
Closes gh-31399
This commit is a best effort attempt at identifying the members that
code generation invokes and might be deprecated. It introduces
a CodeWarnings helper class that records warnings, with special
handling for `@Deprecated`.
See gh-29597
This commit is a prerequisite to help suppressing deprecating warnings
by allowing tests to validate that the compiler does not encounter them.
See gh-29597
In AbstractApplicationEventMulticaster.retrieveApplicationListeners,
despite best efforts to avoid it, unwrapped proxies (singleton targets)
can end up in the list of programmatically registered listeners. In
order to avoid duplicates, we need to find and replace them by their
proxy counterparts, because if both a proxy and its target end up in
'allListeners', listeners will fire twice.
Fixes#28283.
This commit adds a constructor with externally managed
Reactor Netty resources to ReactorNettyClientRequestFactory
and makes it lifecycle-aware in order to support Project CRaC.
Closes gh-31280
Closes gh-31281
Prior to this commit, the bean definition properties code generator
would register hints for invoking the setter methods of registered
property values defined for the bean definition.
The internal algorithm is also reflecting on the Field to discover
annotations. Doing so actually calls `getDeclaredFields` to iterate on
the available fields. This is done recursively up the type hierarchy
until the field is found.
This commit registers the required reflection metadata.
Closes gh-31390
This commit revises the previous commit as follows.
- Remove hasTestMethod() from TestContext and instead introduce a new
variant of createDelegatingTransactionAttribute() in
TestContextTransactionUtils which accepts a boolean
`includeMethodName` flag.
- Add missing @TestMethodOrder declaration to
AfterTestClassSqlScriptsTests to ensure that the test methods are
always executed in the required order.
- Polish Javadoc and add missing @since tags.
Closes gh-27285
This commit replaces uses of onErrorResume() with
- onErrorMap() in places where onErrorResume() is just used to map to a
different exception.
- onErrorComplete() where onErrorResume() just maps to Mono.empty().
- onErrorReturn() where onErrorResum() just maps to Mono.just().
Closes gh-31352
This commit removes the previously introduced reflection hints that were
working around known issues in GraalVM.
Spring Framework 6.1 will require recent maintenance versions of GraalVM
and should not contribute such hints anymore.
Closes gh-30394
Prior to this commit, the bean registration AOT contributions would
register introspection and invocation hints on both declared and public
methods for bean types. The bean introspection algorithm also looks at
default methods implemented by interfaces when collecting bean property
information.
This commit ensures that introspection hints are registered for all
implemented interfaces when registering beans.
Closes gh-31350
This commit partially reverts 3b8dd0a5, which introduced a strict
validation in JmsAccessor#setSessionAcknowledgeMode that prevents use
of vendor-specific acknowledge modes.
See gh-31328
This commit introduces initialize() methods in
AbstractRoutingDataSource and AbstractRoutingConnectionFactory as an
alternative to invoking afterPropertiesSet().
Closes gh-31248
Prior to this commit, DefaultJdbcClient updated the supplied KeyHolder
when using named parameters but not for positional parameters.
This commit refactors the creation of the
PreparedStatementCreatorFactory so that the PreparedStatementCreator
properly creates a PreparedStatement which returns generated keys.
Closes gh-31297
Prior to this commit, the `BeanRegistrationsAotContribution` would only
contribute introspection hints for declared methods. This does not cover
inherited public methods.
This commit adds the missing hint on public methods.
Fixes gh-31293
This commit configures the Foojay resolver plugin in the Gradle build in
order to auto-provision a required JDK distribution if it's not present
already on the host.
Currently the Spring Framework build requires both a JDK 17 and a JDK 21
distribution to build artifacts.
Closes gh-30474
Prior to this commit, `DisposableBeanAdapter` supported reactive bean
destroy methods by detected if `Publisher` is available on the
classpath. The AOT engine did not contribute a reflection hint for this
call.
This commit ensures that this reflection hint is registered in all
cases, even if there are no destroy methods detected on beans.
Fixes gh-31278
`PathMatchingResourcePatternResolver` is reflecting on
`org.eclipse.core.runtime.FileLocator` and invoking methods on it for
OSGi support. While this use case is highly unlikely in native images,
registering the reflection entry by itself should be enough.
Fixes gh-31271
This commit adds the relevant reflection hints required by
`KotlinDetector`; this class is trying to detect both `kotlin.Metadata`
and `kotlin.reflect.full.KClasses`.
Fixes gh- 31269
This commit adds reflection hints for `jakarta.inject.Provider` and
ensures that hints are always contributed even if jakarta classes are
not on the classpath.
Fixes gh-31259
Prior to this commit, `ClassUtils#forName` would always attempt to
resolve the given class name as a nested type. For example, searching
for `org.example.Spring` would try to resolve:
* `org.example.Spring`
* if not available, try `org.example$Spring` as well
Java classes usually start with uppercase letters, so this additional
lookup can be costly and not very useful.
This commit only attempts nested class lookups when the previous segment
starts with an uppercase. So `org.example.Spring.Issue` will look for
`org.example.Spring$Issue`, but `org.example.Spring` will not.
Closes gh-31258
Except for meaningful double spaces (for example, to align the
indentation of comments), this commit replaces all unnecessary double
spaces with single spaces in the spring-webmvc module.
Closes gh-31245
Prior to this commit in the message converters it was possible
to set a pre-configured ObjectMapper. However the constructor
would still create and configure an ObjectMapper.
With the added constructor it is now possible to directly
construct the message converter with the proper ObjectMapper.
This prevents the this additional ObjectMapper to be constructed.
send(..) -methods of JavaMailSenderImpl which is only delegating to
other methods are pulled up as default methods in the interfaces
JavaMailSender and MailSender, to make these interfaces require fewer
methods to implement.
See gh-23651
Prior to this commit, it was only possible to register a
ContextCustomizerFactory in the TestContext framework (TCF) via the
SpringFactoriesLoader mechanism.
This commit introduces support for declarative registration of a
ContextCustomizerFactory local to a test class via a new
@ContextCustomizerFactories annotation.
Closes gh-26148
In light of the refinements to ObjectUtils, this commit updates
SynthesizedMergedAnnotationInvocationHandler to use
ObjectUtils.nullSafeHashCode() and removes the now obsolete code in
SynthesizedMergedAnnotationInvocationHandler.
See gh-29051
This commit reverts the deprecation of CommandLinePropertySource and
SimpleCommandLinePropertySource, since we have discovered that Spring
Boot actively uses SimpleCommandLinePropertySource in
org.springframework.boot.SpringApplication.
Closes gh-31207
This commit deprecates the various nullSafeHashCode methods taking array
types as they are superseded by Arrays.hashCode now. This means that
the now only remaining nullSafeHashCode method does not trigger a
warning only if the target type is not an array. At the same time, there
are multiple use of this method on several elements, handling the
accumulation of hash codes.
For that reason, this commit also introduces a nullSafeHash that takes
an array of elements. The only difference between Objects.hash is that
this method handles arrays.
The codebase has been reviewed to use any of those two methods when it
is possible.
Closes gh-29051
This commit revises the contribution for gh-25921 in the following ways.
- Use instanceof pattern matching
- Use List.of() and Map.of()
- Add missing @since tags
- Polish Javadoc
- Rename isNegativeNumber() to isNegativeNumberLiteral()
- Restructure InlineCollectionTests using @Nested, etc.
- Fix testListWithVariableNotCached() test: it previously set a SpEL
"variable" but tested a "property" in the root context object, which
effectively did not test anything.
- Introduce additional tests: listWithPropertyAccessIsNotCached(),
mapWithVariableIsNotCached(), and mapWithPropertyAccessIsNotCached().
This commit changes the way request attributes are handled in
RequestPredicates. Previously, the AND/OR/NOT predicates copied all
attributes in a map, and restored that when the delegate predicate(s)
failed.
Now, we only set the attributes when all delegates have succeeded.
Closes gh-30028
This commit ensures that both `ObservationRegsitry` and
`ServerRequestObservationConvention` beans are automatically detected in
the application context if they are unique. This aligns with the
existing behavior for all other builder methods.
Closes gh-31205
AnnotationBeanNameGenerator was written before the introduction of the
MergedAnnotations API and therefore heavily relies on the
AnnotationMetadata abstraction and various helper methods for ASM
compatibility.
However, recent work on determineBeanNameFromAnnotation() has made it
apparent that we should use the MergedAnnotations API directly in
AnnotationBeanNameGenerator where feasible in order to avoid
unnecessary, repeated iterations/streams over the same annotation
metadata.
Closes gh-31203
This commit allows a custom code fragment to provide the code to
create a bean without relying on ConstructorResolver. This is especially
important for use cases that derive from the default behaviour and
provide an instance supplier with the regular runtime scenario.
This is a breaking change for code fragments providing a custom
implementation of the related methods. As it turns out, almost all of
them did not need the Executable argument. Configuration class parsing
is the exception, where it needs to provide a different constructor in
the case of the proxy. To make this use case possible,
InstanceSupplierCodeGenerator has been made public.
Closes gh-31117
This commit replaces the initial allocation size for the content caching
buffer by a `FastByteArrayOutputStream`. With this variant, allocations
are cheap and we don't need to apply heuristics anymore to guess the
best initial buffer size.
See gh-29775
Prior to this commit, the initial buffer size for content caching
allocated in `ContentCachingRequestWrapper` would be:
* the request content length, if available in request headers
* the cache limit size as configured on the wrapper
The latter is really an upper bound and should not be considered as a
good default in most cases. This commit ensures that the request content
length is still used if available, but uses a default 1024 size if it's
not.
While this change will probably cause more reallocations as the buffer
grows, this will avoid large allocations in many cases and should
overall help with GC.
Closes gh-29775
Prior to this commit, @BeforeTransaction and @AfterTransaction
methods could not accept any arguments. This is acceptable with testing
frameworks such as JUnit 4 and TestNG that do not provide support for
parameter injection. However, users of JUnit Jupiter have become
accustomed to being able to accept arguments in lifecycle methods
annotated with JUnit's @BeforeEach, @AfterEach, etc.
As a follow up to the previous commit (see gh-31199), this commit
introduces first-class support for parameter injection in
@BeforeTransaction and @AfterTransaction methods, as demonstrated in
the following example.
@BeforeTransaction
void verifyInitialDatabaseState(@Autowired DataSource dataSource) {
// Use the DataSource to verify the initial DB state
}
Closes gh-30736
In order to be able to support parameter injection in
@BeforeTransaction and @AfterTransaction methods (see gh-30736), this
commit introduces a MethodInvoker API for TestExecutionListeners as a
generic mechanism for delegating to the underlying testing framework to
invoke methods.
The default implementation simply invokes the method without arguments,
which allows TestExecutionListeners using this mechanism to operate
correctly when the underlying testing framework is JUnit 4, TestNG, etc.
A JUnit Jupiter specific implementation is registered in the
SpringExtension which delegates to the
ExtensionContext.getExecutableInvoker() mechanism introduced in JUnit
Jupiter 5.9. This allows a TestExecutionListener to transparently
benefit from registered ParameterResolvers in JUnit Jupiter (including
the SpringExtension) when invoking user methods, effectively providing
support for parameter injection for arbitrary methods.
Closes gh-31199
Prior to this commit, when using RowCallbackHandler or ResultSetExtractor in JdbcClient
and passing a parameter to paramSource(), an exception was thrown stating "No value
supplied for the SQL parameter 'xxxxxx'" because the SqlParameterSource used internally
was the wrong one.
Closes gh-31195
Prior to this commit, `DispatcherServlet` would completely reset the
response (status, headers and body) before handling errors within Spring
MVC. This can cause unintended consequences when Servlet Filters added
response headers before the error happened. Such response headers might
be still required in case of error handling.
This commit changes the complete reset of the response to only resetting
the response buffer, if possible.
Closes gh-31154
See gh-31104
When a handler method is annotated with `@ResponseStatus(reason="...")`,
Spring MVC will use `HttpServletResponse#sendError` to complete the
response. As a result, the Servlet container will send an HTML error
page and any existing data in the response buffer will be cleared.
This commit clarifies the `@ResponseStatus` Javadoc and ensures that a
message is logged at the WARN level if a handler method is annotated
like this and still returns a non-Void value. In this case, the return
value will be ignored and developers should be aware of this fact.
See gh-31113
Closes gh-31121
With this commit, ReactorClientHttpConnector now implements
SmartLifecycle which optionally allows recreating the HttpClient
after ReactorResourceFactory has been updated.
Closes gh-31180
With this commit, ReactorResourceFactory now implements
Lifecycle which allows supporting JVM Checkpoint Restore
in Spring Boot with Reactor Netty server, and helps
to support Reactor Netty client as well.
Closes gh-31178
Prior to this commit, the withoutTableColumnMetaDataAccess() and
includeSynonymsForTableColumnMetaData() methods in SimpleJdbcInsert
incorrectly declared a SimpleJdbcInsertOperations return type, which
prevented method chaining when the instance was declared to be of type
SimpleJdbcInsert.
This commit changes the return types of those methods to
SimpleJdbcInsert to benefit from covariant return types like the rest
of the configuration methods in SimpleJdbcInsert.
Closes gh-31177
Prior to this commit and the previous commit, SimpleJdbcInsert did not
provide built-in support for "quoted identifiers". Consequently, if any
column names conflicted with keywords or functions from the underlying
database, you had to manually quote the column names when specifying
them via `usingColumns(...)`, and there was unfortunately no way to
quote schema and table names.
The previous commit provided rudimentary support for quoted SQL
identifiers (schema, table, and column names) by querying
java.sql.DatabaseMetaData.getIdentifierQuoteString() to determine the
quote string. It also introduced `usingEscaping(boolean)` in
`SimpleJdbcInsertOperations` to enable the feature. However, it
incorrectly quoted the schema and table names together, and it did not
take into account the fact that a quoted identifier should respect the
casing (uppercase vs. lowercase) of the underlying database's metadata.
This commit revises quoted identifier support in `SimpleJdbcInsert` by:
- renaming `usingEscaping(boolean)` to `usingQuotedIdentifiers()`
- quoting schema and table names separately
- respecting the casing (uppercase vs. lowercase) of the underlying
database's metadata when quoting identifiers
- introducing integration tests against an in-memory H2 database
See gh-13874
Closes gh-24013
Prior to this commit, the `RestTemplateAdapter` would manually expand
templated URIs. This means that the `RestTemplate` instance itself would
never see the templated URIs and could not record it in the client
observations at runtime.
This commit ensures that when URI templates are available, the adapter
uses the correct `exchange` method variant.
Fixes gh-31144
As a workaround before a proper solution the Spring team is trying to
find with the Hibernate team in a future version of Hibernate, this
commit introduces 2 GraalVM substitutions that should allow to remove
ByteBuddy reachability with Hibernate 6.3.
Closes gh-29549
BlockingExecutionConfigurer#setExecutor takes an AsyncTaskExecutor
not an Executor as the documentation states. With this commit,
this has been corrected.
Closes gh-31150
This is a follow-up change related to gh-31104.
This change reverts the changes previously made in
`ExceptionHandlerExceptionResolver` and instead attempts to reset the
response directly in `DispatcherServlet` in order to cover all types or
exception handling.
Unlike the previous change, we decided to continue even if the response
was already committed: exception handlers will have a chance to be
called, even if it means they'll have to operate on a garbled response.
This change will cause less disruption, in case existing exception
handlers were relying on this behavior.
See gh-31104
Prior to this commit, the Spring Framework build would publish several
zip artifacts:
* a "*-schema.zip" containing all the XSD schemas produced
* a "*-docs.zip" containing the API docs
* a "*-dist.zip" containing all of the above, plus module jars
Since the reference docs are now produced by Antora in a separate
process, the "*-docs.zip" does not contain the reference docs anymore.
But it still contains the API docs which are automatically fetched from
the artifact repository and published on the docs.spring.io website.
This commit intends to update the current arrangement and optimize the
build.
First, the "*-dist.zip" is not published anymore, since it cannot be
consumed anyway by the community: repo.spring.io does not distribute
release artifacts publicly, developers are expected to get them from
Maven Central. This arrangement is quite dated anyway and is not really
useful in current application build setups.
The generation of API docs is moved to a new "framework-api" module,
separating it from the reference docs module ("framework-docs") which
contains Java, Kotlin and Asciidoctor sources. This removes the custom
javadoc aggregation task and instead uses a dedicated Gradle plugin.
This change also adds a new `-PskipDocs` Gradle project property that
skips entirely the documentation tasks (javadoc, kdocs) as well as the
"distrbution" tasks managed in the framework-api module.
This allows developers to publish locally a SNAPSHOT of Spring Framework
without creating the entire documentation distribution. This is
particularly useful for local testing.
For example, `$ ./gradlew pTML -PskipDocs`.
Closes gh-31049
Prior to this commit, the `ExceptionHandlerExceptionResolver` would
resolve exceptions and handle them by writing to the HTTP response body,
even if the request was already partially handled and content was
written to the response body.
This could result in HTTP responses with some content for the intended
application response, then other content for the handled exception.
This would happen especially when the error would be raised while
writing to the response (for example when serializing content).
This commit attempts to reset the HTTP response before handling the
exception. This effectively resets the response buffer for the body as
well as response headers. If the response is already committed, the
Servlet container raises an exception and the exception handling is
skipped altogether in order to avoid garbled responses.
Closes gh-31104
Prior to this commit, `@Async` and `@EventListener` annotated methods
would lose the the logging and observation contexts whenever their
execution was scheduled on a different Thread.
The Context Propagation library supports this use case and can propagate
context values in ThreadLocals, Reactor Context and more.
This commit introduces a new `TaskDecorator` implementation that
leverages the Context Propagation library. When configured on a
`TaskExecutor`, this allows to properly propagate context value through
the execution of the task.
This implementation is completely optional and requires the
"io.micrometer:context-propagation" library on the classpath. Enabling
this feature must be done consciously and sometimes selectively, as
context propagation introduces some overhead.
Closes gh-31130
When use of the deprecated feature is detected, a WARNING log message
will be generated analogous to the following.
WARN o.s.c.a.AnnotationBeanNameGenerator - Support for convention-based
stereotype names is deprecated and will be removed in a future version
of the framework. Please annotate the 'value' attribute in
@org.springframework.context.annotation.AnnotationBeanNameGeneratorTests$ConventionBasedComponent1
with @AliasFor(annotation=Component.class) to declare an explicit alias
for @Component's 'value' attribute.
See gh-31089
Closes gh-31093
This commit schedules blocking I/O operations on the bounded elastic
scheduler, which includes retrieving the content length and writing
the resource (region).
Closes gh-30928
This commit builds on the recently added support for using @AliasFor to
override the `value` attribute in `@Component, and allows a custom
component name to be specified in both @ControllerAdvice and
@RestControllerAdvice via new `name` attributes.
See gh-31089
Closes gh-21108
Although gh-20615 introduced the use of @AliasFor for @Component(value) in the built-in
stereotype annotations (@Service, @Controller, @Repository, @Configuration, and
@RestController), prior to this commit the framework did not actually rely on @AliasFor
support when looking up a component name via stereotype annotations. Rather, the
framework had custom annotation parsing logic in
AnnotationBeanNameGenerator#determineBeanNameFromAnnotation() which effectively ignored
explicit annotation attribute overrides configured via @AliasFor.
This commit revises AnnotationBeanNameGenerator#determineBeanNameFromAnnotation() so that
it first looks up @Component stereotype names using @AliasFor semantics before falling
back to the "convention-based" component name lookup strategy.
Consequently, the name of the annotation attribute that is used to specify the bean name
is no longer required to be `value`, and custom stereotype annotations can now declare an
attribute with a different name (such as `name`) and annotate that attribute with
`@AliasFor(annotation = Component.class, attribute = "value")`.
Closes gh-31089
Create LinkedHashSet with a initialCapacity, prevent under the hood
table resize cost in continuous add operations. Reduce bootstrap time
in the case of large properties.
See gh-27236
This commit reinstates support for the legacy JSR-250
@javax.annotation.ManagedBean and JSR-330 @javax.inject.Named
annotations with regard to component name lookups and component
scanning.
Closes gh-31090
If you wish to stop after a certain number of attempts with an
`ExponentialBackOff` you have to calculate the `maxElapsedTime`
corresponding to the number of attempts.
Add a new property to make it more convenient to stop after a
certain number of attempts.
See gh-27071
Optimize TransactionSynchronizationManager.getSynchronizations() to
avoid sorting and ArrayList creation in case of a single
TransactionSynchronization.
See gh-27335
This commit instruments the new `RestClient` HTTP client for
observability. Since this client is sharing its HTTP infrastructure with
`RestTemplate` and operates on the same request/response types, this
instrumentation reuses the Observation convention and context.
This choice makes sense since one can build a new `RestClient` instance
using a `RestTemplate` instance, effectively reusing the underlying
configuration.
Closes gh-31114
This commit adds support for Kotlin Coroutines to Spring AOP
by leveraging CoroutinesUtils#invokeSuspendingFunction in
AopUtils#invokeJoinpointUsingReflection to convert it to the
equivalent Publisher return value, like in other parts of Spring
Framework.
That allows method interceptors with Reactive support to process
related return values.
CglibAopProxy#processReturnType and JdkDynamicAopProxy#invoke
take care of the conversion from the Publisher return value
to Kotlin Coroutines.
Reactive transactional and HTTP service interface support
have been refined to leverage those new generic capabilities.
Closes gh-22462
This commit implements StringToRegexConverter in Java
in order to avoid circular dependencies between Java
and Kotlin codes that can break IDE support, and for
consistency with the rest of the codebase.
See gh-24311
This commits adds a getContentAsString method to
ContentCachingRequestWrapper that uses the configured charset without
copying the underlying byte array.
See gh-30709
Since an annotation cannot be extended in Java, there is no need to use
the INHERITED_ANNOTATIONS SearchStrategy to search for meta-annotations
on an annotation.
Prior to this commit, there was an issue with the semantics of property
source overrides. Specifically, a @PropertySource annotation present as
a meta-annotation on a @Configuration class was registered with higher
precedence than a @PropertySource annotation declared closer to (or
directly on) the @Configuration class. Consequently, there was no way
for a "local" @PropertySource annotation to override properties
registered via @PropertySource as a meta-annotation.
This commit addresses this issue by introducing a new overloaded
getMergedRepeatableAnnotationAttributes() variant in
AnnotatedTypeMetadata that allows the caller to supply a
sortByReversedMetaDistance flag. When set to `true`, the annotation
search results will be sorted in reversed order based on each
annotation's meta distance, which effectively orders meta-annotations
before annotations that are declared directly on the underlying element.
ConfigurationClassParser and AnnotationConfigUtils have been updated to
use this new repeatable annotation search method for @PropertySource.
Closes gh-31074
Inspired by the recently added support for resource patterns in
@PropertySource locations, this commit adds the same support for
resource locations in @TestPropertySource.
For example, assuming the `config` folder in the classpath contains
only 3 files matching the pattern `file?.properties`,
... the following:
@TestPropertySource("classpath:/config/file1.properties")
@TestPropertySource("classpath:/config/file2.properties")
@TestPropertySource("classpath:/config/file3.properties")
... or:
@TestPropertySource({
"classpath:/config/file1.properties",
"classpath:/config/file2.properties",
"classpath:/config/file3.properties"
})
... can now be replaced by:
@TestPropertySource("classpath*:/config/file?.properties")
See gh-21325
Closes gh-31055
Includes a revision of BeanProperty/DataClassRowMapper with exclusively constructor-based configuration and without JDBC-inherited legacy settings.
Closes gh-27282
Closes gh-26021
Prior to this commit, inlined properties could only be supplied as an
array of Strings as follows.
@TestPropertySource(properties = {
"key1 = value1",
"key2 = value2"
})
Although a user could supply a text block, it was previously rejected
due to a "single key-value pair per string" check in
TestPropertySourceUtils.convertInlinedPropertiesToMap(String...).
This commit removes that restriction and allows the above example to be
refactored to use a text block as follows.
@TestPropertySource(properties = """
key1 = value1
key2 = value2
"""
)
Closes gh-31053
This commit moves ServerWebExchange Kotlin extensions
where they belong: in the spring-web module with the
org.springframework.web.server package, like
ServerWebExchange itself.
The extensions in the wrong location are deprecated
and semi-automated migration to the new variants is
made possible via @Deprecated + ReplaceWith(...).
Some tests have been added as well.
Closes gh-31046
Includes query(Class) method with value and property mapping support on JdbcClient.
JdbcClient's singleColumn/singleValue are declared without a Class parameter now.
Closes gh-26594
See gh-30931
This commit ensures that the Observability instrumentation for
`@JmsListener` does not assume that micrometer-core is on the classpath
and guards against direct usage.
Closes gh-30335
This commit adds observability support for Jakarta JMS support in
spring-jms support. This feature leverages the `JmsInstrumentation`
infrastructure in `io.micrometer:micrometer-core` library.
This instruments the `JmsTemplate` and the `@JmsListener` support to
record observations:
* "jms.message.publish" when the `JmsTemplate` sends a message
* "jms.message.process" when a message is processed by a `@JmsListener`
annotated method
The observation `Convention` and `Context` implementations are shipped
with "micrometer-core".
Closes gh-30335
Prior to this commit, Spring failed to find multiple composed
@ComponentScan and @PropertySource annotations or multiple
@ComponentScans and @PropertySources container annotations. The reason
was due to lacking support in the AnnotatedTypeMetadata API.
This commit introduces support for finding all @ComponentScan and
@PropertySource annotations by making use of the new
getMergedRepeatableAnnotationAttributes() method in
AnnotatedTypeMetadata.
Closes gh-30941
See gh-31041
AnnotatedTypeMetadata has various methods for finding annotations;
however, prior to this commit it did not provide explicit support for
repeatable annotations.
Although it is possible to craft a search "query" for repeatable
annotations using the MergedAnnotations API via getAnnotations(), that
requires intimate knowledge of the MergedAnnotations API as well as the
structure of repeatable annotations.
Furthermore, the bugs reported in gh-30941 result from the fact that
AnnotationConfigUtils attempts to use the existing functionality in
AnnotatedTypeMetadata to find repeatable annotations without success.
This commit introduces a getMergedRepeatableAnnotationAttributes()
method in AnnotatedTypeMetadata that provides dedicated support for
finding merged repeatable annotation attributes with full @AliasFor
semantics.
Closes gh-31041
The Javadoc for getAnnotationAttributes() states that it supports
"attribute overrides on composed annotations"; however, it actually
supports @AliasFor in general, including attribute aliases within a
given annotation.
This commit updates the Javadoc and corresponding tests to reflect that.
Closes gh-31042
This commit adds support for inlined Kotlin value
class properties in SpEL by leveraging Kotlin
reflection instead of Java reflection broken
by the mangled method name.
Closes gh-30468
This commit adds support for Kotlin value classes annotated
with @JvmInline to BeanUtils#findPrimaryConstructor.
This is only the first step, more refinements are expected
to be needed to achieve a comprehensive support of Kotlin
values classes in Spring Framework.
Closes gh-28638
This commit makes the recently introduced
addPropertySourcesToEnvironment(ConfigurableEnvironment, ResourceLoader,
List<PropertySourceDescriptor>) method in TestPropertySourceUtils public
so that it can be used by third parties (for example, Spring Boot).
Closes gh-30981
Java 12 introduced java.lang.Class#componentType() as a shortcut for
getComponentType().
Since we started using arrayType() in fe5560400c, this commit switches
to componentType() for consistent API usage style.
Includes ConfigurableTransactionManager interface for listener registration.
Includes additional introspection methods on TransactionExecution interface.
Includes default method declarations on TransactionStatus/SmartTransactionObject.
Closes gh-27479
Prior to this commit, property files configured (or inferred) via
@TestPropertySource were read using the default encoding of the JVM.
This commit introduces an `encoding` attribute in @TestPropertySource
which allows developers to specify an explicit encoding for test
property files.
Closes gh-30982
This commit changes the `synchronized` usage into a `ReentrantLock`, in
order to guard write operations with a construct that does not pin
virtual threads to the current platform thread on JDK21.
Closes gh-30996
Spring Framework 4.3 introduced the `PropertySourceFactory` SPI for use
with `@PropertySource` on `@Configuration` classes; however, prior to
this commit there was no mechanism to support custom properties file
formats in `@TestPropertySource` for integration tests.
This commit introduces support for configuring a custom
`PropertySourceFactory` via a new `factory` attribute in
`@TestPropertySource` in order to support custom file formats such as
JSON, YAML, etc.
For example, if you create a YamlPropertySourceFactory, you can use it
in integration tests as follows.
@SpringJUnitConfig
@TestPropertySource(locations = "/test.yaml", factory = YamlPropertySourceFactory.class)
class MyTestClass { /* ... /* }
If a custom factory is not specified, traditional `*.properties` and
`*.xml` based `java.util.Properties` file formats are supported, which
was the existing behavior.
Closes gh-30981
This commit allows to configure custom file
extensions in ReloadableResourceBundleMessageSource
thanks to a new setFileExtensions setter.
Combined with setPropertiesPersister, it allows
custom implementations supporting any kind of
property file.
Closes gh-18990
Prior to this commit, if an error was encountered during build-time AOT
processing, the error was logged at WARN/DEBUG level, and processing
continued.
With this commit, test AOT processing now fails on error by default. In
addition, the `failOnError` mode can be disabled by setting the
`spring.test.aot.processing.failOnError` Spring/System property to
`false`.
Closes gh-30977
TransactionalApplicationListener and TransactionalEventListener automatically detect a reactive TransactionContext as the event source and register the synchronization accordingly. TransactionalEventPublisher is a convenient delegate for publishing corresponding events with the current TransactionContext as event source. This can also serve as a guideline for similar reactive event purposes.
Closes gh-27515
Closes gh-21025
Closes gh-30244
Prior to this commit, MappedInterceptor had a getPathPatterns() method
that returned the include patterns.
This commit introduces getIncludePathPatterns() (which effectively
replaces getPathPatterns()) and getExcludePathPatterns(). In addition,
this commit deprecates getPathPatterns().
Closes gh-30971
Where possible, switch to the Long.parseLong variant that accepts a
start and end index for the supplied CharSequence, thus avoiding making
unnecessary copies of the String input.
Closes gh-30710
Delegates to JdbcTemplate/NamedParameterJdbcTemplate underneath the covers.
Supports parameter objects/records through SimplePropertySqlParameterSource.
Closes gh-30931
Includes CompletableFuture-based retrieve operations on Spring's Cache interface.
Includes support for retrieve operations on CaffeineCache and ConcurrentMapCache.
Includes async cache mode option on CaffeineCacheManager.
Closes gh-17559
Closes gh-17920
Closes gh-30122
Includes failOnError method on Errors interface for use with validateObject.
Declares many Errors methods as default methods for lean SimpleErrors class.
Closes gh-19877
Prior to this commit a @CachePut operation would fail if the key
expression is invalid, but guarded with an unless condition as the
former was evaluated too early. This commit makes sure that key for
a put is only evaluated if the put operation is active.
Note that this does not apply for @Cacheable as the key needs to be
computed early to determine if a matching entry exists in the cache.
See gh-22769
This commit changes the default request factory from the
SimpleClientHttpRequestFactory to the JdkClientHttpRequestFactory if
available. It also adds detection logic for OkHttp and Jetty.
AbstractTransactionManagementConfiguration.transactionalEventListenerFactory() creating a RestrictedTransactionalEventListenerFactory now.
See gh-30679
Previously, BeanInstanceSupplier had three variants of the
`withGenerator` callback, one with a bi function, one with a function,
and with a supplier. This could lead to compilation failure when the
target type has a method with the same name and a number of arguments
that match another variant.
It turns out the supplier-based variant is only used a shortcut. This
commit deprecates it and update ghe code generation to use the function
instead.
Closes gh-29278
The method includes logic that is currently in
ViewResolutionResultHandler but fits well in BindingContext and also
includes the call to saveModel method from the InitBinderBindingContext
subclass, which was called too early until now from
RequestMappingHandlerAdapter before the model has been fully updated.
This mirrors a similar method in ModelFactory on the Spring MVC side
which also combines those two tasks.
Closes gh-30821
Now that HttpClientAdapter is deprecated and replaced by HttpExchangeAdapter
and ReactorHttpExchangeAdapter, our tests should use the new contracts.
See gh-30117
Previously, the runtimeHintsTest task configuration made a cross
project task reference to obtain the jar path of spring-core-test
to use in the -javaagent argument.
With this change, a dedicated configuration exists to resolve the
project artifact without the need to reference the jar task of
spring-core-test.
Closes gh-30838
Previously, an afterEvaluate call was used to read the values of the
runtimeHintsAgent extension and the -javaagent parameter supplied to
the runtimeHintsTest task was evaluated eagerly.
With this change the construction of the -javaagent parameter is
deferred until task execution and the extension properties are
evaluated lazily.
See gh-30838
Prior to this change, a build cache miss would occur in
runtimeHintsTest tasks when executing the build from two different
locations, causing the tasks to re-execute. This was due to an
absolute path to the agent jar being included in the -javaagent
argument supplied to the test JVM process.
This change introduces a RuntimeHintsAgentArgumentProvider allowing
finer grained control over the way Gradle computes the build cache
key. With this change, the contents of the agent jar file are
considered, rather than the absolute file location.
See gh-30838
ResolvableTypes are only considered equal if of the very same class now.
As a consequence, a forRawClass result is not equal to forClass anymore.
The new equalsType method is available for plain type equality checks.
Closes gh-28608
Closes gh-27748
This commit introduces an overloaded version of RestClient::exchange,
adding a boolean parameter that indicates whether the connection is
closed after the exchange function is executed.
See gh-29552
This commit creates a placeholder for future RestClient reference
documentation. It also creats a link to RestClient from the RestTemplate
javadoc.
See gh-30826
This commit moves HttpHeaders that are used in multiple places (client
and server, reactive and non-reactive) to a new, separate http.support
package.
Closes gh-30823
This commit ensures that ServerResponse.HeadersBuilder::build can throw
an exception, by introducing a separate functional interface that does
allow for exceptions to be thrown.
Closes gh-30818
As a consequence, the spring-messaging HandlerMethod detects interface parameter annotations as well, and the same is available for other HandlerMethod variants.
Closes gh-30801
This commit introduces the RestClient, a synchronous HTTP client that
offers an API similar to WebClient, using the same infrastructure (i.e.
request factory, error handler, interceptors, etc) as RestTemplate.
Closes gh-29552
Extract the default logic for resolving the name of an @Valid
parameter into an ObjectNameResolver, and use it when there isn't
one configured.
See gh-30644
To handle method validation errors in ResponseEntityExceptionHandler,
MethodValidationException and associated types should not depend on
Bean Validation. To that effect:
1. MethodValidationResult and ParameterValidationResult no longer make
the underlying ConstraintViolation set available, and instead expose
only the adapted validation errors (MessageSourceResolvable, Errors),
analogous to what SpringValidatorAdapter does. And likewise
MethodValidationException no longer extends ConstraintViolationException.
2. MethodValidationPostProcessor has a new property
adaptConstraintViolations to decide whether to simply raise
ConstraintViolationException, or otherwise to adapt the ConstraintViolations
and raise MethodValidationException instead, with the former is the default
for compatibility.
3. As a result, the MethodValidator contract can now expose methods that
return MethodValidationResult, which provided more flexibility for handling,
and it allows MethodValidationAdapter to implement MethodValidator directly.
4. Update Javadoc in method validation classes to reflect this shift, and
use terminology consistent with Spring validation in classes without an
explicit dependency on Bean Validation.
See gh-30644
- Update method order
- Do not automatically create MessageSource arguments in
WebExchangeBindException constructor as they're more likely to be
created via getDetailMessageArguments with MessageSource passed in.
See gh-30644
Remove throwIfViolationsPresent and replace with static factory
methods on MethodValidationException taking MethodValidationResult,
which makes handling more explicit and allows choice of what
exception to raise.
Update MethodValidationResult to expose the target, the method, and
forReturnValue flag, so the code handling an exception will have
access to all details.
See gh-30644
By default, the JDK HttpClient's HttpRequest does not allow Connection,
Content-Length, Expect, Host, or Upgrade headers to be set, but this can
be overriden with the `jdk.httpclient.allowRestrictedHeaders` system
property.
See https://bugs.openjdk.org/browse/JDK-8213696
Closes gh-30787
This commit adds support for WildcardType bounds resolution,
commonly seen in Kotlin due to declaration-site variance,
but also possible in Java even if less common.
Closes gh-22313
- Removed duplicate Client in types names.
- Removed buffering in favor of OutputStream to
Flow.Publisher<ByteBuffer> bridge.
- Made request and types package private.
- Various other small improvements.
Closes gh-30478
This commit updates the `ScheduledTaskObservationDocumentation` to
better align the contributed KeyValues with OpenTelemetry conventions
for observations of code executions.
Instead of a "target.type" key with the bean class simple name, this
is now contributing the canonical class name of the bean under the
"code.namespace" key.
The "method.name" key is renamed to "code.function" and its values
remain unchanged.
Closes gh-30721
This commit adds support for Kotlin parameter default values
in handler methods. It allows to write:
@RequestParam value: String = "default"
as an alternative to:
@RequestParam(defaultValue = "default") value: String
Both Spring MVC and WebFlux are supported, including on
suspending functions.
Closes gh-21139
This commit introduces a Kotlin-specific implementation
of the ExchangeFilterFunction interface that allows for
using coroutines, similar to what CoWebFilter does on
server-side.
Closes gh-30650
This commit enhances the `ScheduledAnnotationBeanPostProcessor` to
instrument `@Scheduled` methods declared on beans. This will create
`"tasks.scheduled.execution"` observations for each execution of a
scheduled method. This supports both blocking and reactive variants.
By default, observations are no-ops; developers must configure the
current `ObservationRegistry` on the `ScheduledTaskRegistrar` by using a
`SchedulingConfigurer`.
Closes gh-29883
This commit changes the Java system property used to
control PreComputeFieldFeature verbose logging from
spring.aot.precompute to spring.native.precompute.log
in order to clarify its purpose and avoid confusion
with AOT processing of JVM bytecode or Java sources.
See gh-30571
This allows re-use of existing MethodParameter instances from controller
methods with cached metadata, and also ensures additional capabilities
such as looking up parameter annotations on interfaces.
See gh-29825
1. Remove list markers (those can be provided in message).
2. Use ", and " between errors for readability.
3. Remove single quotes around errors.
4. If MessageSource is provided, use resolved message as is since in
that case applications have full control over each message.
Closes gh-30198
This commit changes the order of RouterFunctionMapping defined
in WebMvcConfigurationSupport from 3 to -1 in order to achieve
better consistency between WebMVC and WebFlux. It also reduces
the surprise factor. That way, functional routes are always
before annotation-based ones.
Closes gh-30278
This commit makes sure that profiles that have been explicitly enabled
during AOT optimizations are automatically enabled when using those
optimizations.
If other profiles are set at runtime, they take precedence over the ones
defined during AOT processing.
Closes gh-30421
In the previous commit which introduced the new context failure threshold
support in the TestContext framework, the context failure tracking was
tied to an instance of DefaultCacheAwareContextLoaderDelegate.
Consequently, the feature was only supported within a given test class.
This commit therefore moves context failure tracking to the ContextCache
SPI (and DefaultContextCache) so that the feature applies to all test
classes within the current test suite (i.e., JVM).
This commit also includes the total failure count in the statistics
logged by the DefaultContextCache.
See gh-14182
This set of commits introduces ApplicationContext "failure threshold"
support in the Spring TestContext Framework (TCF).
Specifically, this new feature avoids repeated attempts to load a
failing ApplicationContext in the TCF, based on a failure threshold
which defaults to 1 but can be configured via a system property.
See individual commits for details.
Closes gh-14182
This commit makes the failure threshold value configurable via a JVM
system property or Spring property named
"spring.test.context.failure.threshold".
See gh-14182
This commit introduces initial support for a new "context failure
threshold" feature in the Spring TestContext Framework (TCF).
Specifically, DefaultCacheAwareContextLoaderDelegate now tracks how
many times a failure occurs when attempting to load an
ApplicationContext and preemptively throws an IllegalStateException for
subsequent attempts to load the same context if the configured failure
threshold has been exceeded.
See gh-14182
Related to gh-30052, we should improve ParameterNameDiscoverer
Kotlin tests to make sure DefaultParameterNameDiscoverer behaves
as expected and is consistent with
KotlinReflectionParameterNameDiscoverer behavior.
Closes gh-30618
Prior to this commit, only the letters 'A' - 'Z' (ignoring case) were
supported in identifiers (i.e., property, field, and variable names).
This known (yet undocumented) limitation prevented the use of characters
such as 'ü', 'ñ', 'é' as well as letters from other character sets such
as Chinese, Japanese, Cyrillic, etc.
This commit lifts that restriction by delegating to Character.isLetter()
to determine if a character in a SpEL expression is a letter.
Closes gh-30580
This commit adds a note in the reference documentation stating that
`ErrorHandler` infrastructure is not involved when reactive methods send
an error signal: the exception is sent as a message in the pipeline and
is not thrown from the task `Runnable`.
See gh-23533
This commit adds support for `@Scheduled` annotation on reactive
methods and Kotlin suspending functions.
Reactive methods are methods that return a `Publisher` or a subclass
of `Publisher`. The `ReactiveAdapterRegistry` is used to support many
implementations, such as `Flux`, `Mono`, `Flow`, `Single`, etc.
Methods should not take any argument and published values will be
ignored, as they are already with synchronous support.
This is implemented in `ScheduledAnnotationReactiveSupport`, which
"converts" Publishers to `Runnable`. This strategy keeps track of
active Subscriptions in the `ScheduledAnnotationBeanPostProcessor`,
in order to cancel them all in case of shutdown.
The existing scheduling support for tasks is reused, aligning the
triggering behavior with the existing support: cron, fixedDelay and
fixedRate are all supported strategies.
If the `Publisher` errors, the exception is logged at warn level and
otherwise ignored. As a result new `Runnable` instances will be
created for each execution and scheduling will continue.
The only difference with synchronous support is that error signals
will not be thrown by those `Runnable` tasks and will not be made
available to the `org.springframework.util.ErrorHandler` contract.
This is due to the asynchronous and lazy nature of Publishers.
Closes gh-23533
Closes gh-28515
This commit disables support for evaluating SpEL expressions from
untrusted sources by default. Specifically, this applies to the
SpEL-based 'selector' header support in WebSocket messaging, which
includes the DefaultSubscriptionRegistry and the classes used to
configure the 'selector' header name (SimpleBrokerMessageHandler and
SimpleBrokerRegistration).
The selector header support remains in place but will have to be
explicitly enabled beginning with Spring Framework 6.1.
For example, a custom implementation of WebSocketMessageBrokerConfigurer
can override the configureMessageBroker() method and configure the
selector header name as follows.
registry.enableSimpleBroker().setSelectorHeaderName("selector");
Closes gh-30550
This commit ensures that ClientHttpRequest implementations implement
StreamingHttpOutputMessage, so that they do not expose an OutputStream,
but store a handle capable of writing to a stream instead.
Closes gh-30557
This commit polishes the previous change, ensuring that if the request
uses a wildcard subtype with an ndjson suffix then the wildcard isn't
present in the response's Content-Type.
Insteand, in that case we would fall back to `applicatin/x-ndjson` (the
base ndjson media type), assuming that the requester is only interested
in the ndjson nature of the underlying representation and not in the
specific semantics of any subtype.
See commit 9332b3f
See gh-26817
This commit adds support of parsing a simple long from a String and
turning it to an `Instant` by considering it represents a timestamp in
milliseconds (see `Instant.ofEpochMilli`). Failing to parse a long from
the String, the previous algorithm is used: first check for an RFC-1123
representation then an ISO_INSTANT representation.
See gh-30312
Closes gh-30546
This commit ports and adapts spring-jdbc's `BeanPropertyRowMapper` and
`DataClassRowMapper` to spring-r2dbc, allowing to `map` rows or
outParameters to object instances, data classes or records.
See gh-26021
Closes gh-30530
This commit adds `application/*+x-ndjson`, a wildcard media type which
covers all types that can be parsed as nd-json, to the list of media
types the ReactiveTypeHandler considers for a streaming response in
WebMVC.
As a result, a request which for example `Accept` the
`application/vnd.myapp.v1+x-ndjson` media type will generate a response
with the same `Content-Type`, with newline-delimited json objects being
streamed in the response body.
Closes gh-26817
Instead of having antora run always, which happens regardless of
whether anything has changed, we'll have it invoked as part of the CI
build, and we'll have to run it locally ourselves when necessary.
See gh-30481
This commit raises the SnakeYAML baseline version to 2.0.
While most Spring applications are not affected by CVE-2022-1471,
upgrading this version should prevent automated tools from raising this
as a security issue. Such tools usually do not understand that YAML
parsing in Spring is about reading configuration, not parsing untrusted
content.
Closes gh-30048
Prior to this commit, the Observation instrumentation for Reactive
server applications was implemented with a `WebFilter`. This allowed to
record observations and set up a tracing context for the controller
handlers.
The limitation of this approach is that all processing happening at a
lower level is not aware of any observation. Here, the
`HttpWebHandlerAdapter` handles several interesting aspects:
* logging of HTTP requests and responses at the TRACE level
* logging of client disconnect errors
* handling of unresolved errors
With the current instrumentation, these logging statements will miss the
tracing context information. As a result, this commit deprecates the
`ServerHttpObservationFilter` in favor of a more direct instrumentation
of the `HttpWebHandlerAdapter`. This enables a more precise
instrumentattion and allows to set up the current observation earlier in
the reactor context: log statements will now contain the relevant
information.
Fixes gh-30013
Prior to this commit, the SpringExtension looked up the
TestInstance.Lifecycle and ExecutionMode using
TestContextAnnotationUtils; however, using TestContextAnnotationUtils is
problematic since the TestInstance.Lifecycle and ExecutionMode can be
configured globally via configuration parameters instead of locally via
the @TestInstance and @Execution annotations.
This commit addresses these issues by looking up the
TestInstance.Lifecycle and ExecutionMode via JUnit Jupiter's
ExtensionContext which takes into account both global and local
configuration.
See gh-30020
This commit updates the script that builds PRs to add locations to the
installed JDK within the CI image. Without this change, PRs fail to
build because of the recently introduced JDK21 toolchain requirement in
the Spring Framework build.
Closes gh-30472
This commit:
- Refine the wording used in logs and Javadoc
- Avoid calling awaitPreventShutdownBarrier() in afterRestore()
- Add logs to print the restart duration
See gh-29921
Prior to this commit, some FreeMarker tests would fail when involving
property lookup in a template file, where this bean property is linked
with a method implemented as a default method on an interface.
While I did not manage to reproduce this behavior in an independent test
case, this is most likely related to a change in JDK 21:
https://bugs.openjdk.org/browse/JDK-8071693
This commit changes the template expression to using the default method
directly.
This commit makes sure that the SimpleAsyncTaskExecutor only creates a
virtual thread when the virtualThreadDelegate is set, and not an
additional kernel thread as well.
See gh-30241
VirtualThreadDelegate built on JDK 21 for multi-release jar.
Includes dedicated VirtualThreadTaskExecutor as lean option.
Includes setVirtualThreads flag on SimpleAsyncTaskExecutor.
Includes additional default methods on AsyncTaskExecutor.
Closes gh-30241
This commit modifies the way the `@RecordApplicationEvents` annotation
works in tests, allowing for capture of events from threads other than
the main test thread (async events) and for the assertion of captured
event from a separate thread (e.g. when using `Awaitility`).
This is done by switching the `ApplicationEventsHolder` to use an
`InheritedThreadLocal`.
There is a mutual exclusion between support of asynchronous events vs
support of JUnit5 parallel tests with the `@TestInstance(PER_CLASS)`
mode. As a result, we favor the former and now `SpringExtension` will
invalidate a test class that is annotated (or meta-annotated, or
enclosed-annotated) with `@RecordApplicationEvents` AND
`@TestInstance(PER_CLASS)` AND `@Execution(CONCURRENT)`.
See gh-29827
Closes gh-30020
This commit adds support for MethodHandles in SpEL, using the same
syntax as user-defined functions (which also covers reflective Methods).
The most benefit is expected with handles that capture a static method
with no arguments, or with fully bound handles (where all the arguments
have been bound, including a target instance as first bound argument
if necessary). Partially bound MethodHandle should also be supported.
A best effort approach is taken to detect varargs as there is no API
support to determine if an argument is a vararg or an explicit array,
unlike with Method. Argument conversions are also applied. Finally,
array repacking is not always necessary with varargs so it is only
performed when the vararg is the sole argument to the invoked method.
See gh-27099
Closes gh-30045
This commit improves both the javadoc and the reference guide section on
the Elvis SpEL operator to clarify that in addition to `null` objects,
empty Strings also lead the operator to evaluate to its second operand.
The reference guide's advanced snippet is modified to use such an empty
String instead of `null` to make that behavior prominent with some code.
See gh-30318
Closes gh-30352
RuntimeHintsAgentPlugin purpose is to verify that the reflective
invocations expected match the ones performed.
gh-30242 introduces a code path where the reflective invocation
is skipped when running on native.
This issue set the system property "org.graalvm.nativeimage.imagecode"
to "runtime" when running runtime tests with the agent in order to
make sure the code path tested for those tests is the native one.
Closes gh-30422
Prior to this commit, the toString() implementation in ProfilesParser
(which is the internal implementation of Profiles.of()) concatenated
profile expressions with " or ".
For example, the string representation of
Profiles.of("spring & framework", "java | kotlin") was
"spring & framework or java | kotlin".
This commit improves the toString() implementation by wrapping
individual profile expressions in parentheses and concatenating them
with " | ".
For example, the string representation from the previous example is now
"(spring & framework) | (java | kotlin)".
This makes it easier to read (for example, when debugging) and
comprehend.
As an additional benefit, the result of invoking toString() can even be
used as a logically equivalent composite profile expression, though
that is not the primary goal of this change.
Closes gh-30374
This commit enables sub-classes to better customize resource selection
and resource loading in `ReloadableResourceBundleMessageSource`, without
a need to duplicate the caching logic of `refreshProperties`.
See gh-30334
Closes gh-30369
This commit optimizes `DefaultLifecycleProcessor::stopBeans` by using a
`TreeMap` when gathering the `LifecycleGroup`s during stopBeans. It also
switches to a functional style using `computeIfAbsent`.
Finally, it further optimizes `LifecycleGroup` by removing sorting of
`LifecycleGroupMember` members list entirely, turning the class into a
simple record.
This is possible because the members list is already comprised of
members which all share the same phase value, so sorting according to
each member's phase is redundant.
Closes gh-30361
Co-authored-by: Simon Baslé <sbasle@vmware.com>
On windows, the `*` character is not allowed in a directory's name.
When trying to append a glob pattern to a `Path` (`path.resolve("**")`),
if the underlying `Path.getFileSystem()` is windows then an
`InvalidPathException` is thrown.
The NoHttp plugin doesn't really need a `Path` but a glob `String`, so
this commit uses a simple String concatenation in order to append the
wildcard part (with the canonical path separator for good measure).
Closes gh-30355
This commit adds support for the @XmlSeeAlso annotation in the
Jaxb2XmlDecoder. This includes
- Finding the set of possible qualified names given a class name, rather
than a single name.
- Splitting the XMLEvent stream when coming across one of the names in
this set.
Closes gh-30167
- Split Validator::of into two factory methods:
- forInstanceOf using Class::isAssignableFrom
- forType using Class::equals
- Moved anonymous implementation into TypedValidator with default access
Closes gh-30341
This commit introduces `of` method in `Validator` to provide a way to
create a validator for the specific type `<T>` using `BiConsumer<T, Errors>`
and define the validator in a functional way.
This also eliminates the boilerplate for implementing the `supports` method.
This commit removes the `-PmainToolchain` option from our build, since
it was not broadly used. Instead, the language level is now configured
in the `JavaConventions` for JDK 17.
The `-PtestToolchain` option is still available for testing Spring
Framework with other JDKs (i.e., compiling and running tests with a JDK
that's not the baseline).
See gh-30339
This commit moves the checkstyle conventions from the build.gradle
script to a buildSrc convention, ensuring that the same configuration is
applied to all checkstyle tasks.
See gh-30339
# <img src="framework-docs/src/docs/spring-framework.png" width="80" height="80"> Spring Framework [](https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-6.0.x?groups=Build") [](https://ge.spring.io/scans?search.rootProjectNames=spring)
# <img src="framework-docs/src/docs/spring-framework.png" width="80" height="80"> Spring Framework [](https://github.com/spring-projects/spring-framework/actions/workflows/build-and-deploy-snapshot.yml?query=branch%3Amain) [](https://ge.spring.io/scans?search.rootProjectNames=spring)
This is the home of the Spring Framework: the foundation for all [Spring projects](https://spring.io/projects). Collectively the Spring Framework and the family of Spring projects are often referred to simply as "Spring".
Spring provides everything required beyond the Java programming language for creating enterprise applications for a wide range of scenarios and architectures. Please read the [Overview](https://docs.spring.io/spring/docs/current/spring-framework-reference/overview.html#spring-introduction) section as reference for a more complete introduction.
Spring provides everything required beyond the Java programming language for creating enterprise applications for a wide range of scenarios and architectures. Please read the [Overview](https://docs.spring.io/spring-framework/reference/overview.html) section of the reference documentation for a more complete introduction.
## Code of Conduct
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc). By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
This project is governed by the [Spring Code of Conduct](https://github.com/spring-projects/spring-framework/?tab=coc-ov-file#contributor-code-of-conduct). By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to spring-code-of-conduct@spring.io.
## Access to Binaries
@@ -14,7 +14,7 @@ For access to artifacts or a distribution zip, see the [Spring Framework Artifac
## Documentation
The Spring Framework maintains reference documentation ([published](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/) and [source](framework-docs/src/docs/asciidoc)), GitHub [wiki pages](https://github.com/spring-projects/spring-framework/wiki), and an
The Spring Framework maintains reference documentation ([published](https://docs.spring.io/spring-framework/reference/) and [source](framework-docs/modules/ROOT)), GitHub [wiki pages](https://github.com/spring-projects/spring-framework/wiki), and an
[API reference](https://docs.spring.io/spring-framework/docs/current/javadoc-api/). There are also [guides and tutorials](https://spring.io/guides) across Spring projects.
## Micro-Benchmarks
@@ -31,7 +31,7 @@ Information regarding CI builds can be found in the [Spring Framework Concourse
## Stay in Touch
Follow [@SpringCentral](https://twitter.com/springcentral), [@SpringFramework](https://twitter.com/springframework), and its [team members](https://twitter.com/springframework/lists/team/members) on Twitter. In-depth articles can be found at [The Spring Blog](https://spring.io/blog/), and releases are announced via our [news feed](https://spring.io/blog/category/news).
Follow [@SpringCentral](https://twitter.com/springcentral), [@SpringFramework](https://twitter.com/springframework), and its [team members](https://twitter.com/springframework/lists/team/members) on 𝕏. In-depth articles can be found at [The Spring Blog](https://spring.io/blog/), and releases are announced via our [releases feed](https://spring.io/blog/category/releases).
Please, [open a draft security advisory](https://github.com/spring-projects/security-advisories/security/advisories/new) if you need to disclose and discuss a security issue in private with the Spring Framework team. Note that we only accept reports against [supported versions](https://spring.io/projects/spring-framework#support).
For more details, check out our [security policy](https://spring.io/security-policy).
## JAR signing
Spring Framework JARs released on Maven Central are signed.
You'll find more information about the key here: https://spring.io/GPG-KEY-spring.txt
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.0.x[Spring Framework 6.0.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:
| A boolean flag that controls whether errors encountered during AOT processing in the
_Spring TestContext Framework_ should result in an exception that fails the overall process.
See xref:testing/testcontext-framework/aot.adoc[Ahead of Time Support for Tests].
| `spring.test.constructor.autowire.mode`
| The default _test constructor autowire mode_ to use if `@TestConstructor` is not present
on a test class. See xref:testing/annotations/integration-junit-jupiter.adoc#integration-testing-annotations-testconstructor[Changing the default test constructor autowire mode]
.
on a test class. See xref:testing/annotations/integration-junit-jupiter.adoc#integration-testing-annotations-testconstructor[Changing the default test constructor autowire mode].
| `spring.test.context.cache.maxSize`
| The maximum size of the context cache in the _Spring TestContext Framework_. See
<1> References the `businessService` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
<1> References the `businessService` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
======
`@Around("com.xyz.CommonPointcuts.businessService()")` references the `businessService` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
Note that the aspect implements the `Ordered` interface so that we can set the precedence of
the aspect higher than the transaction advice (we want a fresh transaction each time we
@@ -114,70 +30,15 @@ we have exhausted all of our retry attempts.
For this to work, the annotated types must be woven with the AspectJ weaver. You can
either use a build-time Ant or Maven task to do this (see, for example, the
https://www.eclipse.org/aspectj/doc/released/devguide/antTasks.html[AspectJ Development
{aspectj-docs-devguide}/antTasks.html[AspectJ Development
Environment Guide]) or load-time weaving (see xref:core/aop/using-aspectj.adoc#aop-aj-ltw[Load-time Weaving with AspectJ in the Spring Framework]). The
`AnnotationBeanConfigurerAspect` itself needs to be configured by Spring (in order to obtain
a reference to the bean factory that is to be used to configure new objects). If you
use Java-based configuration, you can add `@EnableSpringConfigured` to any
`@Configuration` class, as follows:
a reference to the bean factory that is to be used to configure new objects). You can define
@@ -15,10 +15,13 @@ Applying such optimizations early implies the following restrictions:
* The classpath is fixed and fully defined at build time.
* The beans defined in your application cannot change at runtime, meaning:
** `@Profile`, in particular profile-specific configuration needs to be chosen at build time.
** `@Profile`, in particular profile-specific configuration, needs to be chosen at build time and is automatically enabled at runtime when AOT is enabled.
** `Environment` properties that impact the presence of a bean (`@Conditional`) are only considered at build time.
* Bean definitions with instance suppliers (lambdas or method references) cannot be transformed ahead-of-time (see related https://github.com/spring-projects/spring-framework/issues/29555[spring-framework#29555] issue).
* Make sure that the bean type is as precise as possible.
* Bean definitions with instance suppliers (lambdas or method references) cannot be transformed ahead-of-time.
* Beans registered as singletons (using `registerSingleton`, typically from
`ConfigurableListableBeanFactory`) cannot be transformed ahead-of-time either.
* As we cannot rely on the instance, make sure that the bean type is as precise as
possible.
TIP: See also the xref:core/aot.adoc#aot.bestpractices[] section.
@@ -27,15 +30,15 @@ A Spring AOT processed application typically generates:
* Java source code
* Bytecode (usually for dynamic proxies)
* {api-spring-framework}/aot/hint/RuntimeHints.html[`RuntimeHints`] for the use of reflection, resource loading, serialization, and JDK proxies.
* {spring-framework-api}/aot/hint/RuntimeHints.html[`RuntimeHints`] for the use of reflection, resource loading, serialization, and JDK proxies
NOTE: At the moment, AOT is focused on allowing Spring applications to be deployed as native images using GraalVM.
We intend to support more JVM-based use cases in future generations.
[[aot.basics]]
== AOT engine overview
== AOT Engine Overview
The entry point of the AOT engine for processing an `ApplicationContext` arrangement is `ApplicationContextAotGenerator`. It takes care of the following steps, based on a `GenericApplicationContext` that represents the application to optimize and a {api-spring-framework}/aot/generate/GenerationContext.html[`GenerationContext`]:
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`]:
* Refresh an `ApplicationContext` for AOT processing. Contrary to a traditional refresh, this version only creates bean definitions, not bean instances.
* Invoke the available `BeanFactoryInitializationAotProcessor` implementations and apply their contributions against the `GenerationContext`.
In this mode, xref:core/beans/factory-extension.adoc#beans-factory-extension-factory-postprocessors[`BeanFactoryPostProcessor` implementations] are invoked as usual.
This includes configuration class parsing, import selectors, classpath scanning, etc.
Such steps make sure that the `BeanRegistry` contains the relevant bean definitions for the application.
If bean definitions are guarded by conditions (such as `@Profile`), these are discarded at this stage.
If bean definitions are guarded by conditions (such as `@Profile`), these are evaluated,
and bean definitions that don't match their conditions are discarded at this stage.
If custom code needs to register extra beans programmatically, make sure that custom
registration code uses `BeanDefinitionRegistry` instead of `BeanFactory` as only bean
definitions are taken into account. A good pattern is to implement
`ImportBeanDefinitionRegistrar` and register it via an `@Import` on one of your
configuration classes.
Because this mode does not actually create bean instances, `BeanPostProcessor` implementations are not invoked, except for specific variants that are relevant for AOT processing.
These are:
@@ -81,15 +91,15 @@ Once this part completes, the `BeanFactory` contains the bean definitions that a
[[aot.bean-factory-initialization-contributions]]
== Bean Factory Initialization AOT Contributions
Components that want to participate in this step can implement the {api-spring-framework}/beans/factory/aot/BeanFactoryInitializationAotProcessor.html[`BeanFactoryInitializationAotProcessor`] interface.
Components that want to participate in this step can implement the {spring-framework-api}/beans/factory/aot/BeanFactoryInitializationAotProcessor.html[`BeanFactoryInitializationAotProcessor`] interface.
Each implementation can return an AOT contribution, based on the state of the bean factory.
An AOT contribution is a component that contributes generated code that reproduces a particular behavior.
An AOT contribution is a component that contributes generated code which reproduces a particular behavior.
It can also contribute `RuntimeHints` to indicate the need for reflection, resource loading, serialization, or JDK proxies.
A `BeanFactoryInitializationAotProcessor` implementation can be registered in `META-INF/spring/aot.factories` with a key equal to the fullyqualified name of the interface.
A `BeanFactoryInitializationAotProcessor` implementation can be registered in `META-INF/spring/aot.factories` with a key equal to the fully-qualified name of the interface.
A `BeanFactoryInitializationAotProcessor` can also be implemented directly by a bean.
The `BeanFactoryInitializationAotProcessor` interface can also be implemented directly by a bean.
In this mode, the bean provides an AOT contribution equivalent to the feature it provides with a regular runtime.
Consequently, such a bean is automatically excluded from the AOT-optimized context.
@@ -111,7 +121,7 @@ This interface is used as follows:
* Implemented by a `BeanPostProcessor` bean, to replace its runtime behavior.
For instance xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp-examples-aabpp[`AutowiredAnnotationBeanPostProcessor`] implements this interface to generate code that injects members annotated with `@Autowired`.
* Implemented by a type registered in `META-INF/spring/aot.factories` with a key equal to the fullyqualified name of the interface.
* Implemented by a type registered in `META-INF/spring/aot.factories` with a key equal to the fully-qualified name of the interface.
Typically used when the bean definition needs to be tuned for specific features of the core framework.
[NOTE]
@@ -130,7 +140,7 @@ Taking our previous example, let's assume that `DataSourceConfiguration` is as f
WARNING: Kotlin class names with backticks that use invalid Java identifiers (not starting with a letter, containing spaces, etc.) are not supported.
Since there isn't any particular condition on this class, `dataSourceConfiguration` and `dataSource` are identified as candidates.
The AOT engine will convert the configuration class above to code similar to the following:
@@ -151,11 +176,12 @@ The AOT engine will convert the configuration class above to code similar to the
======
Java::
+
[source,java,indent=0,role="primary"]
[source,java,indent=0]
----
/**
* Bean definitions for {@link DataSourceConfiguration}
*/
@Generated
public class DataSourceConfiguration__BeanDefinitions {
/**
* Get the bean definition for 'dataSourceConfiguration'
@@ -190,11 +216,25 @@ Java::
NOTE: The exact code generated may differ depending on the exact nature of your bean definitions.
TIP: Each generated class is annotated with `org.springframework.aot.generate.Generated` to
identify them if they need to be excluded, for instance by static analysis tools.
The generated code above creates bean definitions equivalent to the `@Configuration` class, but in a direct way and without the use of reflection if at all possible.
There is a bean definition for `dataSourceConfiguration` and one for `dataSourceBean`.
When a `datasource` instance is required, a `BeanInstanceSupplier` is called.
This supplier invokes the `dataSource()` method on the `dataSourceConfiguration` bean.
[[aot.running]]
== 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
on the JVM by setting the `spring.aot.enabled` System property to `true`.
NOTE: When AOT optimizations are included, some decisions that have been taken at build-time
are hard-coded in the application setup. For instance, profiles that have been enabled at
build-time are automatically enabled at runtime as well.
[[aot.bestpractices]]
== Best Practices
@@ -203,11 +243,33 @@ 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
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
beans programmatically, make sure to use a `BeanDefinitionRegistry` to register
bean definitions.
This can typically be done via a `BeanDefinitionRegistryPostProcessor`. Note that, if it
is registered itself as a bean, it will be invoked again at runtime unless you make
sure to implement `BeanFactoryInitializationAotProcessor` as well. A more idiomatic
way is to implement `ImportBeanDefinitionRegistrar` and register it using `@Import` on
one of your configuration classes. This invokes your custom code as part of configuration
class parsing.
If you declare additional beans programmatically using a different callback, they are
likely not going to be handled by the AOT engine, and therefore no hints are going to be
generated for them. Depending on the environment, those beans may not be registered at
all. For instance, classpath scanning does not work in a native image as there is no
notion of a classpath. For cases like this, it is crucial that the scanning happens at
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.
The AOT engine performs additional checks on the bean type, such as detecting the presence of `@Autowired` members or lifecycle callback methods.
For `@Configuration` classes, make sure that the return type of the factory `@Bean` method is as precise as possible.
Consider the following example:
@@ -216,7 +278,7 @@ Consider the following example:
If you are registering bean definitions programmatically, consider using `RootBeanBefinition` as it allows to specify a `ResolvableType` that handles generics.
[[aot.bestpractices.constructors]]
=== Avoid Multiple Constructors
The container is able to choose the most appropriate constructor to use based on several candidates.
However, this is not a best practice and flagging the preferred constructor with `@Autowired` if necessary is preferred.
In case you are working on a code base that you 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
fun customDBEntityManagerFactory(dataSource: DataSource, managedTypes: PersistenceManagedTypes): LocalContainerEntityManagerFactoryBean {
val factoryBean = LocalContainerEntityManagerFactoryBean()
factoryBean.dataSource = dataSource
factoryBean.setManagedTypes(managedTypes)
return factoryBean
}
----
======
[[aot.hints]]
@@ -369,20 +569,27 @@ Java::
Running an application as a native image requires additional information compared to a regular JVM runtime.
For instance, GraalVM needs to know ahead of time if a component uses reflection.
Similarly, classpath resources are not shipped in a native image unless specified explicitly.
Similarly, classpath resources are not included in a native image unless specified explicitly.
Consequently, if the application needs to load a resource, it must be referenced from the corresponding GraalVM native image configuration file.
The {api-spring-framework}/aot/hint/RuntimeHints.html[`RuntimeHints`] API collects the need for reflection, resource loading, serialization, and JDK proxies at runtime.
The {spring-framework-api}/aot/hint/RuntimeHints.html[`RuntimeHints`] API collects the need for reflection, resource loading, serialization, and JDK proxies at runtime.
The following example makes sure that `config/app.properties` can be loaded from the classpath at runtime within a native image:
If at all possible, `@ImportRuntimeHints` should be used as close as possible to the component that requires the hints.
This way, if the component is not contributed to the `BeanFactory`, the hints won't be contributed either.
It is also possible to register an implementation statically by adding an entry in `META-INF/spring/aot.factories` with a key equal to the fullyqualified name of the `RuntimeHintsRegistrar` interface.
It is also possible to register an implementation statically by adding an entry in `META-INF/spring/aot.factories` with a key equal to the fully-qualified name of the `RuntimeHintsRegistrar` interface.
[[aot.hints.reflective]]
=== `@Reflective`
{api-spring-framework}/aot/hint/annotation/Reflective.html[`@Reflective`] provides an idiomatic way to flag the need for reflection on an annotated element.
{spring-framework-api}/aot/hint/annotation/Reflective.html[`@Reflective`] provides an idiomatic way to flag the need for reflection on an annotated element.
For instance, `@EventListener` is meta-annotated with `@Reflective` since the underlying implementation invokes the annotated method using reflection.
By default, only Spring beans are considered and an invocation hint is registered for the annotated element.
This can be tuned by specifying a custom `ReflectiveProcessor` implementation via the
`@Reflective` annotation.
Out-of-the-box, only Spring beans are considered but you can opt-in for scanning using `@ReflectiveScan`.
In the example below, all types of the package `com.example.app` and their subpackages are considered:
include-code::./MyConfiguration[]
Scanning happens during AOT processing and the types in the target packages do not need to have a class-level annotation to be considered.
This performs a "deep scan" and the presence of `@Reflective`, either directly or as a meta-annotation, is checked on types, fields, constructors, methods, and enclosed elements.
By default, `@Reflective` registers an invocation hint for the annotated element.
This can be tuned by specifying a custom `ReflectiveProcessor` implementation via the `@Reflective` annotation.
Library authors can reuse this annotation for their own purposes.
If components other than Spring beans need to be processed, a `BeanFactoryInitializationAotProcessor` can detect the relevant types and use `ReflectiveRuntimeHintsRegistrar` to process them.
An example of such customization is covered in the next section.
[[aot.hints.register-reflection-for-binding]]
=== `@RegisterReflectionForBinding`
[[aot.hints.register-reflection]]
=== `@RegisterReflection`
{api-spring-framework}/aot/hint/annotation/RegisterReflectionForBinding.html[`@RegisterReflectionForBinding`] is a specialization of `@Reflective` that registers the need for serializing arbitrary types.
{spring-framework-api}/aot/hint/annotation/RegisterReflection.html[`@RegisterReflection`] is a specialization of `@Reflective` that provides a declarative way of registering reflection for arbitrary types.
NOTE: As a specialization of `@Reflective`, this is also detected if you're using `@ReflectiveScan`.
In the following example, public constructors and public methods can be invoked via reflection on `AccountService`:
`@RegisterReflection` can be applied to any target type at the class level, but it can also be applied directly to a method to better indicate where the hints are actually required.
`@RegisterReflection` can be used as a meta-annotation to provide more specific needs.
{spring-framework-api}/aot/hint/annotation/RegisterReflectionForBinding.html[`@RegisterReflectionForBinding`] is such composed annotation and registers the need for serializing arbitrary types.
A typical use case is the use of DTOs that the container cannot infer, such as using a web client within a method body.
`@RegisterReflectionForBinding` can be applied to any Spring bean at the class level, but it can also be applied directly to a method, field, or constructor to better indicate where the hints are actually required.
The following example registers `Account` for serialization.
The following example registers `Order` for serialization.
With `RuntimeHintsPredicates`, we can check for reflection, resource, serialization, or proxy generation hints.
This approach works well for unit tests but implies that the runtime behavior of a component is well known.
You can learn more about the global runtime behavior of an application by running its test suite (or the app itself) with the {docs-graalvm}/native-image/metadata/AutomaticMetadataCollection/[GraalVM tracing agent].
You can learn more about the global runtime behavior of an application by running its test suite (or the app itself) with the {graalvm-docs}/native-image/metadata/AutomaticMetadataCollection/[GraalVM tracing agent].
This agent will record all relevant calls requiring GraalVM hints at runtime and write them out as JSON configuration files.
For more targeted discovery and testing, Spring Framework ships a dedicated module with core AOT testing utilities, `"org.springframework:spring-core-test"`.
@@ -478,7 +690,7 @@ If you forgot to contribute a hint, the test will fail and provide some details
.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
https://spring.io/tools[Spring Tools] for Eclipse, Visual Studio Code, and Theia.
****
An alternative to XML setup is provided by annotation-based configuration, which relies
on bytecode metadata for wiring up components instead of XML declarations. Instead of
using XML to describe a bean wiring, the developer moves the configuration into the
component class itself by using annotations on the relevant class, method, or field
declaration. As mentioned in xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp-examples-aabpp[Example: The `AutowiredAnnotationBeanPostProcessor`], using a
`BeanPostProcessor` in conjunction with annotations is a common means of extending the
Spring IoC container. For example, the xref:core/beans/annotation-config/autowired.adoc[`@Autowired`]
annotation provides the same capabilities as described in xref:core/beans/dependencies/factory-autowire.adoc[Autowiring Collaborators] but
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 (for example, 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"]
----
@@ -62,11 +48,11 @@ configuration (notice the inclusion of the `context` namespace):
The `<context:annotation-config/>` element implicitly registers the following post-processors:
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.