To support additional use cases, this commit introduces a
withAssignmentDisabled() method in the Builder for
SimpleEvaluationContext.
See gh-33319
Closes gh-33321
(cherry picked from commit e74406afd0)
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.
See gh-33319
Closes gh-33321
(cherry picked from commit 0127de5a7a)
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.
See gh-33310
Closes gh-33311
(cherry picked from commit c57c2272a1)
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
(cherry picked from commit cb6a5baac5)
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.
See gh-33013
Closes gh-33189
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-33207
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-33185
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-33128
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-32986
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
(cherry picked from commit e9de426eb5)
Prior to this commit, the Spring Expression Language (SpEL) failed to
compile an expression that indexed into an 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
(cherry picked from commit cda577d1aa)
This covers AspectJ transaction and caching aspects when encountered by Spring AOP.
Closes gh-32882
See gh-32793
(cherry picked from commit 6d7cd9c7dc)
- 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
Includes JAXBContext locking revision (avoiding synchronization) and consistent treatment of DocumentBuilderFactory (in terms of caching as well as locking).
Closes gh-32851
(cherry picked from commit a4c2f291d9)
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-32848
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
(cherry picked from commit 7536980be9)
This commit fixes the artifact properties we set for "framework-docs"
artifacts. These have a different name as of 6.1.x and were backported
as is.
Closes gh-32780
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
(cherry picked from commit 4baad16437)
This commit changes the guard against multiple subscriptions, as the
previously used doOnSubscribe hook could not function as guard in
certain scenarios.
See gh-32727
Closes gh-32732
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-32701
Co-authored-by: Juergen Hoeller <juergen.hoeller@broadcom.com>
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.
See gh-31217
Closes gh-32638
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-32617
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
(cherry picked from commit e702733c7b)
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
(cherry picked from commit ef02f0bad8)
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-32399
webmvc.fn now also uses the StandardServletAsyncWebRequest wrapped response
to enforce lifecycle rules from Servlet spec (section 2.3.3.4).
See gh-32341
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-32341
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
See gh-32317
Closes gh-32321
Commit 375e0e6827 introduced a regression in
ContentCachingResponseWrapper (CCRW). Specifically, CCRW no longer
honors Content-Type and Content-Length headers that have been set in
the wrapped response and now incorrectly returns null for those header
values if they have not been set directly in 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 in the CCRW.
- In copyBodyToResponse(), the Content-Type in the wrapped response is
only overridden if the Content-Type has been set directly in the CCRW.
Furthermore, 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 CCRW.
This commit fixes that by returning a unique set from getHeaderNames().
This commit also updates ContentCachingResponseWrapperTests to verify
the expected behavior for Content-Type and Content-Length headers that
are set in the wrapped response as well as in CCRW.
See gh-32039
See gh-32317
Closes gh-32321
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.
gh-32314 is expected to remove the need for such
substitutions which are not great for maintainability
by design.
Closes gh-32312
This notably enables Jackson to reflectively call a user-provided
builder class and invoke its declared methods (setters and build) in
a native app.
See gh-32238
Closes gh-32257
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-32197
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-32160
Before this commit, the JDK and Jetty connectors do not have any
safeguards against multiple body subscriptions. Such as check has now
been added.
See gh-32100
Closes gh-32102
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-32063
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.
See gh-32039
Closes gh-32050
ResponseEntityExceptionHandler should not set the exception attribute
when there is a response body, and the response is fully handled.
Closes gh-31541
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-31989
(Backport of 598c972a78)
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-31975
(cherry picked from commit 318d460256)
Includes TypeVariable bypass for reflection-free annotation retrieval.
Includes info log message for annotation attribute retrieval failure.
Closes gh-27182
(cherry picked from commit 70247c4a94)
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-31946
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-31894
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.
See gh-31848
Closes gh-31859
This commit introduces an integration test for the regression fixed in
the previous commit (76bc9cf325).
See gh-31826
Closes gh-31828
(cherry picked from commit 8d4deca2a6)
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.
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
(cherry picked from commit 75da9c3c47)
This commit fixes a bug in DefaultPartHttpMessageReader's
MultipartParser, due to which the last token in a part window was not
properly indicated.
See gh-30953
Closes gh-31766
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-31715
Fixes gh-31716
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-31708
This commit supports the scroll() and scroll(ScrollMode) methods from
Hibernate's Query API in SharedEntityManagerCreator's query-terminating
methods set.
See gh-31682
Closes gh-31683
(cherry picked from commit a15f472898)
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-31646
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-31656
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
(cherry picked from commit 695559879e)
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-31629
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.
See gh-31623
Closes gh-31624
(cherry picked from commit 7d2ea7e7e1)
Expose methods to set and reset cache to use from a Filter instead
of a method to create such a Filter. Also use cached results only
if they match by dispatcher type and requestURI.
See gh-31588
This commit updates PathMatchingResourcePatternResolver to avoid
returning duplicate resources on MS Windows when searching using the
`classpath*:` prefix and a wildcard pattern that matches resources
which are directly present in a JAR as well as present via classpath
manifest entries.
Closes gh-31598
Prior to this commit, the `ConcurrentReferenceHashMap#Segment` would
recalculate its element count during the restructure phase by
subtracting the number of polled elements from the queue to the current
count.
Later, the newly restructured `references` array would only contain
references that 1) are not in the set of elements to purge and
2) that hold a non-null value.
The issues with this approach are multiple. The newly calculated count
is only an estimate, as some situations can make it invalid, even
temporarily.
* since we initially collected all elements to be purged from the queue,
the GC might have collected new values. This means that we might
filter out more references that we initially intended to
* because the restructure operation re-creates new references for all
elements in the original array, we might later get references from the
queue that are not in the array anymore. This could lead to
"duplicate" removals for the same value
Because several methods in the Segment class have special no-op behavior
when `count == 0`, an invalid count can lead to keys appearing missing
when they are actually still present. In some scenarios, this can
decrease the performance of the cache since values need to be
recalculated.
This commit fixes this inconsistency count issue by first using an
estimate in order to decide whether the array needs a resize and then by
counting the actual numbers of elements inserted in the restructured
array as the new count.
Fixes gh-31373
This commit adds a warning in the reference guide to address the
use cases where users might be tempted to use several property
placeholder configurers.
Closes gh-14623
Prior to this commit, HTTP server observations for Spring WebFlux could
be recorded twice for a single request in some cases. The "COMPLETE" and
"CANCEL" signals would race in the reactive pipeline and would trigger
both the `doOnComplete()` and ` `doOnCancel()` operators, each calling
`observation.stop()` on the current observation.
This would in fact publish two different observations for the same
request.
This commit ensures that the instrumentation uses the `Mono#tap`
operator to guard against this case and only call `Observation#stop`
once for each request.
Fixes gh-31417
Prior to this commit, a cancelled exchange would always result in an
`"status":"UNKNOWN"` KeyValue. This only applied to reactive variants,
as cancelled exchanges are not currently detected for Servlet
implementations.
In some cases, exchanges can be cancelled by clients before they are
completed, but the response was actually received by the client. The
response status information has been set by the application and the
response has been committed. For those cases, we shouldn't assume an
"UNKNOWN" value.
This commit assumes that committed responses have a response status set
by the application and that the observations should reflect that. From
now on, we only assume an "UNKNOWN" status if the response has not been
commited.
Fixes gh-31388
Due to the changes in gh-31341, if the repeat count in a SpEL
expression (using the repeat operator '*') is negative, we throw a
SpelEvaluationException with the MAX_REPEATED_TEXT_SIZE_EXCEEDED
message which is incorrect and misleading.
Prior to gh-31341, a negative repeat count resulted in an
IllegalArgumentException being thrown by String#repeat(), which was
acceptable in terms of diagnostics, but that did not make it
immediately clear to the user what the underlying cause was.
In light of the above, this commit improves diagnostics for a negative
repeated text count in SpEL expressions by throwing a
SpelEvaluationException with a new NEGATIVE_REPEATED_TEXT_COUNT error
message.
Closes gh-31342
If the resulting size of repeated text in a SpEL expression (using the
repeat operator '*') would exceed MAX_REPEATED_TEXT_SIZE, we currently
throw a SpelEvaluationException with the
MAX_REPEATED_TEXT_SIZE_EXCEEDED message.
However, if the calculation of the repeated text size results in
integer overflow, our max size check fails to detect that, and
String#repeat(int) throws a preemptive OutOfMemoryError from which the
application immediately recovers.
To improve diagnostics for users, this commit ensures that we
consistently throw a SpelEvaluationException with the
MAX_REPEATED_TEXT_SIZE_EXCEEDED message when integer overflow occurs.
Closes gh-31341
Prior to this commit the Spring Expression Language (SpEL) was able to
properly parse an expression that uses the safe navigation operator
(?.) with a method that has a `void` return type (for example,
"myObject?.doSomething()"); however, SpEL was not able to evaluate or
compile such expressions.
This commit addresses the evaluation issue by selectively not boxing
the exit type descriptor (for inclusion in the generated bytecode) when
the method's return type is `void`.
This commit addresses the compilation issue by pushing a null object
reference onto the stack in the generated byte code when the method's
return type is `void`.
Closes gh-27421
Prior to this commit, if a Spring Expression Language (SpEL) expression
contained property, field, or method references using the null-safe
navigation operator (?.), the generated AST String representation
incorrectly omitted the '?' characters.
For example, 'myProperty?.myMethod()' had a generated AST string
representation of 'myProperty.myMethod()'.
This commit addresses this by introducing isNullSafe() in
MethodReference and reworking the logic in
CompoundExpression.toStringAST().
Closes gh-31326
Since the rewrite of ConcurrentLruCache in Spring Framework 6.0, an
attempt to create a ConcurrentLruCache with zero capacity results in an
IllegalArgumentException even though the documentation states that zero
capacity indicates "no caching, always generating a new value".
This commit restores the ability to configure a ConcurrentLruCache with
zero capacity and introduces corresponding tests (which were first
verified against the 5.3.x branch to ensure backward compatibility).
See gh-26320
Closes gh-31317
Previously, MessagingMessageListenerAdapter or any adapter relying on
the default MessagingMessageConverter would log an incoming message
with a toString of the Message that does not provide any extra
information. This is due to the default implementation providing a
lazy resolution message that only attempts to extract the payload
when necessary.
This commit implements a toString method that uses the raw JMS message
if the payload is not available. If it is, the payload is used instead.
Closes gh-21265
Given a @Configuration class named org.example.AppConfig which
contains @Bean methods, in Spring Framework 5.3.x and previous
versions, the following classes were created when generating the CGLIB
proxy.
org.example.AppConfig$$EnhancerBySpringCGLIB$$fd7e9baa
org.example.AppConfig$$FastClassBySpringCGLIB$$3fec86e
org.example.AppConfig$$EnhancerBySpringCGLIB$$fd7e9baa$$FastClassBySpringCGLIB$$82534900
Those class names indicate that 1 class was generated for the proxy for
the @Configuration class itself and that 2 additional FastClass
classes were generated to support proxying of @Bean methods in
superclasses.
However, since Spring Framework 6.0, the following classes are created
when generating the CGLIB proxy.
org.example.AppConfig$$SpringCGLIB$$0
org.example.AppConfig$$SpringCGLIB$$1
org.example.AppConfig$$SpringCGLIB$$2
The above class names make it appear that 3 proxy classes are generated
for each @Configuration class, which is misleading.
To address that and to align more closely with how such generated
classes were named in previous versions of the framework, this commit
modifies SpringNamingPolicy so that generated class names once again
include "FastClass" when the generated class is for a CGLIB FastClass
as opposed to the actual proxy for the @Configuration class.
Consequently, with this commit the following classes are created when
generating the CGLIB proxy.
org.example.AppConfig$$SpringCGLIB$$0
org.example.AppConfig$$SpringCGLIB$$FastClass$$0
org.example.AppConfig$$SpringCGLIB$$FastClass$$1
Closes gh-31272
For equivalence, we only need to compare the preInstantiationPointcut
fields since they include the declaredPointcut fields. In addition, we
should not compare the aspectInstanceFactory fields since
LazySingletonAspectInstanceFactoryDecorator does not implement equals().
See gh-31238
This commit expands the scope of equality checks in the implementation
of equals() for PerTargetInstantiationModelPointcut to include all
fields instead of just the pointcut expression for the declared
pointcut.
See gh-31238
The introduction of AdvisedSupport.AdvisorKeyEntry in Spring Framework
6.0.10 resulted in a regression regarding caching of CGLIB generated
proxy classes. Specifically, equality checks for the proxy class cache
became based partially on identity rather than equivalence. For
example, if an ApplicationContext was configured to create a
class-based @Transactional proxy, a second attempt to create the
ApplicationContext resulted in a duplicate proxy class for the same
@Transactional component.
On the JVM this went unnoticed; however, when running Spring
integration tests within a native image, if a test made use of
@DirtiesContext, a second attempt to create the test
ApplicationContext resulted in an exception stating, "CGLIB runtime
enhancement not supported on native image." This is because Test AOT
processing only refreshes a test ApplicationContext once, and the
duplicate CGLIB proxy classes are only requested in subsequent
refreshes of the same ApplicationContext which means that duplicate
proxy classes are not tracked during AOT processing and consequently
not included in a native image.
This commit addresses this regression as follows.
- AdvisedSupport.AdvisorKeyEntry is now based on the toString()
representations of the ClassFilter and MethodMatcher in the
corresponding Pointcut instead of the filter's and matcher's
identities.
- Due to the above changes to AdvisorKeyEntry, ClassFilter and
MethodMatcher implementations are now required to implement equals(),
hashCode(), AND toString().
- Consequently, the following now include proper equals(), hashCode(),
and toString() implementations.
- CacheOperationSourcePointcut
- TransactionAttributeSourcePointcut
- PerTargetInstantiationModelPointcut
Closes gh-31238
This commit reviews when an AOT-generated bean definition defines a
beanClass or targetType. Previously, a beanClass was not consistently
set which could lead to issues.
Closes gh-31242
Prior to this commit, the `RuntimeHintsPredicates` would assume that
registering introspection or invocation hints for "all declared methods"
on a type would also include "all public methods". This is not true, as
the Java reflection API itself behaves differently.
`getDeclaredMethods()` does not return a superset of `getMethods()`, as
the latter can return inherited methods, but not the former.
Same reasoning applies to fields.
This commit fixes the hints predicates to only match if the correct hint
has been registered.
Fixes gh-31224
This commit refines CORS wildcard processing Javadoc to
provides more details on how wildcards are handled for
Access-Control-Allow-Methods, Access-Control-Allow-Headers
and Access-Control-Expose-Headers CORS headers.
For Access-Control-Expose-Headers, it is not possible to copy
the response headers which are not available at the point
when the CorsProcessor is invoked. Since all the major browsers
seem to support wildcard including on requests with credentials,
and since this is ultimately the user-agent responsibility to
check on client-side what is authorized or not, Spring Framework
continues to support this use case.
See gh-31143
Prior to this commit, it was unclear to users and third parties that it
is necessary to manually configure a StandardTypeLocator with a
specific ClassLoader to ensure that the SpEL expression parser is able
to reliably locate user types.
For example, the StandardBeanExpressionResolver in the spring-context
module configures a StandardTypeLocator using the bean ClassLoader of
the corresponding BeanFactory.
This commit improves the documentation to raise awareness of this fact.
Closes gh-26253
gh-30810 introduced explicit support for collections and maps in
ObjectUtils.nullSafeConciseToString() by invoking isEmpty() on a Map or
Collection to determine which concise string representation should be
used. However, this caused a regression in which an exception was
thrown if the Map or Collection was a proxy generated by
AbstractFactoryBean to support <util:set />, <util:list />, and
<util:map /> in XML configuration.
This commit addresses this set of regressions by always returning
"[...]" or "{...}" for a Collection or Map, respectively, disregarding
whether the map is empty or not.
Closes gh-31138
This commit prints a log message at debug level without
a stacktrace for TypeNotPresentException and uses
warn level instead of error level for other exceptions
since the processing of such bean will just be skipped.
Closes gh-31147
This commit revises the FilePatternResourceHintsRegistrar API and
introduces List<String> overrides of various var-args methods used with
the new builder API.
Closes gh-29161
Due to the introduction of the `framework-api` project in the main branch,
we now have 3 `framework-*` projects that should be ignored. I have
therefore removed `/framework-bom/build` and `/framework-docs/build` and
added `/framework-*/build` to ignore all 3 framework projects.
See gh-31049
This commit refines Reactor field precomputing on native
to only compute at build-time fields in the reactor.core
package, since doing so in reactor.netty has unwanted side
effects like Epoll always disabled.
Closes gh-31141
* pr/29753:
Polish "Make sure NoUniqueBeanDefinitionException to be serializable"
Make sure NoUniqueBeanDefinitionException to be serializable
Closes gh-29753
The tests were ignored due to "Fails against TestNG 6.11"; however,
these tests pass against the current version of TestNG that we build
against (7.8.0).
Prior to this commit, when PathMatchingResourcePatternResolver
processed a `file:` pattern (for example, `file:/app-config/**`) for a
`rootPath` that did not exist in the filesystem, the resolver attempted
to search the directory and logged a WARNING message similar to the
following when it failed to do so.
Failed to search in directory [/app-config/] for files matching pattern
[**]: java.nio.file.NoSuchFileException: /app-config/
To avoid unnecessary attempts to search a nonexistent directory,
PathMatchingResourcePatternResolver now skips searching of a nonexistent
directory and preemptively logs an INFO message similar to the
following.
Skipping search for files matching pattern [**]: directory [/app-config]
does not exist
Closes gh-31111
This commit ensures that PathMatchingResourcePatternResolver's
doFindPathMatchingFileResources() method returns a mutable Set in order
to comply with the documented contract.
This commit optimizes ClassUtils#getMostSpecificMethod which is
a method frequently invoked in typical Spring applications.
It refines ClassUtils#isOverridable by considering static and
final modifiers as non overridable and optimizes its implementation.
Closes gh-30272
This commit adds @Nullable to the argValue parameters in the
doSetValue() methods in ArgumentPreparedStatementSetter and
ArgumentTypePreparedStatementSetter.
Closes gh-31086
Prior to this commit, a dynamic property registered via a
@DynamicPropertySource method in a @Nested test class was not able to
override a property registered via a @DynamicPropertySource method in
the enclosing class.
See gh-26091
Closes gh-31083
This commit contributes proxy hints needed by
SharedEntityManagerCreator for
org.hibernate.query.sql.internal.NativeQueryImpl interfaces.
A related smoke test has been contributed via
spring-projects/spring-aot-smoke-tests#188.
Closes gh-29603
This commit turns TypeMismatchException thrown in
ModelAttributeMethodArgumentResolver#createAttribute into
proper ServerWebInputException in order get HTTP response
with 400 Bad Request status code instead of 500 Internal error.
Closes gh-31045
This commit contributes proxy hints needed by
SharedEntityManagerCreator for
org.hibernate.query.sqm.internal.QuerySqmImpl interfaces.
Until Hibernate 6.1, those hints were erroneously provided
at GraalVM reachability metadata level. As of Hibernate 6.2,
they are not, hence the need to contribute them at Spring
Framework level.
A related smoke test has been contributed via
spring-projects/spring-aot-smoke-tests#188.
Closes gh-31050
Reuses ValidationAnnotationUtils which is slightly optimized for the detection of Spring's Validated annotation now, also to the benefit of common web scenarios.
Closes gh-21852
This commit changes Any to Any? in ProceedingJoinPoint
Kotlin examples in order to be consistent with Java
and avoid a "NullPointerException: pjp.proceed() must
not be null" error.
Closes gh-31015
This commit changes Any to Any? in ProceedingJoinPoint
Kotlin examples in order to be consistent with Java
and avoid a "NullPointerException: pjp.proceed() must
not be null" error.
See gh-31015
Prior to this commit, the ignoreResourceNotFound flag in
@PropertySource was ignored by PropertySourceProcessor if a
PropertySourceFactory threw an exception which wrapped an exception
that would otherwise be ignored -- for example, a FileNotFoundException.
To address this issue, this commit updates PropertySourceFactory so
that it catches RuntimeException and IOException and then checks if the
exception or its cause is an "ignorable" exception in terms of
ignoreResourceNotFound semantics.
Closes gh-22276
When the content length is known, use readNBytes on the InputStream in
StringHttpMessageConverter, which avoids some extra copying and allocations.
Closes gh-30942
This commit updates WebMVC converters and WebFlux
encoders/decoders to support custom serializers
with Kotlin Serialization when specified via
a custom SerialFormat.
It also turns the serializers cache to a non-static
field in order to allow per converter/encoder/decoder
configuration.
Closes gh-30870
Prior to this commit, the `SseEventBuilder` would be used to create SSE
events and write them to the connection using the `ResponseBodyEmitter`.
This would send each data item one by one, effectively writing and
flushing to the network for each. Since multiple data lines are prepared
by the `SseEventBuilder`, a typical write of an SSE event performs
multiple flushes operations.
This commit adds a method on `ResponseBodyEmitter` to perform batch
writes (given a `Set<DataWithMediaType>`) and only flush once all
elements of the set have been written.
This also applies in case of early writes, where now all buffered
elements are written then flushed altogether.
Fixes gh-30912
In order to reduce the surface area of published APIs in the affected
classes, this commit:
- Reverts the changes made to GeneratedClasses in c354b1014d.
- Reverts the changes made to DefaultGenerationContext in a28ec3a0a8.
- Makes the DefaultGenerationContext(DefaultGenerationContext, String)
constructor protected.
- Reworks the internals of TestContextGenerationContext to align with
the above changes.
See gh-30861
Closes gh-30895
Closes gh-30897
Aligned with shortcut handling in AutowiredAnnotationBeanPostProcessor.
Includes minor MethodInvoker optimization for pre-resolved targetClass.
Closes gh-30883
Prior to this commit, test AOT processing failed if a feature name for
generated class names was used for more than one ApplicationContext.
For example, when generating code for org.example.MessageService with a
"Management" feature name, the "BeanDefinitions" class was named as
follows (without a uniquely identifying TestContext###_ feature name
prefix).
org/example/MessageService__ManagementBeanDefinitions.java
When another attempt was made to generate code for the MessageService
using the same "Management" feature name, a FileAlreadyExistsException
was thrown denoting that the class/file name was already in use.
To avoid such naming collisions, this commit introduces a
TestContextGenerationContext which provides a custom implementation of
withName(String) that prepends an existing feature name (if present) to
a new feature name, thereby treating any existing feature name as a
prefix to a new, nested feature name.
Consequently, code generation for the above example now results in
unique class/file names like the following (which retain the uniquely
identifying TestContext###_ prefixes).
org/example/MessageService__TestContext002_ManagementBeanDefinitions.java
org/example/MessageService__TestContext003_ManagementBeanDefinitions.java
Closes gh-30861
This commit introduces a `failOnError` flag in TestContextAotGenerator.
When set to `true`, any error encountered during AOT processing will
result in an exception that fails the overall process. When set to
`false` (the default), the previous behavior remains unchanged: a DEBUG
or WARN message will be logged, and processing will continue.
This feature is currently only used for internal testing.
See gh-30861
Closes gh-30898
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
After further consideration, the team has decided to remove the
getAutodetectMode() method since its return type conflicts with the
parameter type in setAutodetectMode(int), making it an invalid bean
property.
See gh-30855
This commit changes the documentation to advise using
https://github.com/stomp-js/stompjs library on client
side and to configure by default WebSocket without
SockJS as browsers and proxies now have a pretty good
WebSocket support.
Closes gh-30857
Prior to this commit, MBeanExporter used
org.springframework.core.Constants which used reflection to find
constant fields in the MBeanExporter class. Consequently, one had to
register reflection hints in order to use MBeanExporter in a GraalVM
native image.
This commit addresses this by replacing the use of the `Constants`
class with a simple java.util.Map which maps constant names to constant
values for the autodetect constants defined in MBeanExporter.
See gh-30851
Closes gh-30846
This merges the existing support for the legacy JSR-250 PostConstruct/PreDestroy annotations into CommonAnnotationBeanPostProcessor itself, opening up the InitDestroyAnnotationBeanPostProcessor base class for multiple init/destroy methods in a single post-processor. This removes the need for a separate JSR-250 InitDestroyAnnotationBeanPostProcessor in AnnotationConfigUtils.
Closes gh-30695
This commit documents the fact that the Servlet Filter based
observations for MVC applications is limited by the Servlet Filter
contract in the first place. All processing and logging that happens
outside of the scope of the filter is not observed.
Log statements from the catalina engine (in the case of Tomcat), or any
container-specific infrastructure, is not covered by the
instrumentation.
Closes gh-29398
This commit improves the documentation for the
`ShallowEtagHeaderFilter`, stating that it is only meant to support a
subset of conditional HTTP requests: GET requests with "If-None-Match"
headers. Other headers and state changing HTTP methods are not supported
here, as the filter only operates on the content of the response and has
no knowledge of the resource being served.
Closes gh-30517
Prior to this commit, there was no explicit support for arrays,
collections, and maps in nullSafeConciseToString(). This lead to string
representations such as the following, regardless of whether the array,
collection, or map was empty.
- char[]@1623b78d
- java.util.ImmutableCollections$List12@74fe5c40
- java.util.ImmutableCollections$MapN@10e31a9a
This commit introduces explicit support for arrays, collections, and
maps in nullSafeConciseToString(), which results in the following
empty/non-empty string representations.
- array: {} / {...}
- collection: [] / [...]
- map: {} / {...}
The reason a string representation of an array uses "{}" instead of
"[]" (like in Arrays.toString(...)) is that
ObjectUtils.nullSafeToString(<array>) already follows that convention,
and the implementation of nullSafeConciseToString() aligns with that
for the sake of consistency.
Closes gh-30810
We would preferably use ObjectUtils.nullSafeConciseToString(rejectedValue) here but revert to the full nullSafeToString representation for strict backwards compatibility (programmatic toString calls as well as exception messages).
Closes gh-30799
In addition to the previously addressed removal of bean definitions, this is able to deal with prototype factory methods returning non-null after null or also null after non-null. Stale cached values are getting refreshed rather than bypassed.
Closes gh-30794
This commit extends the list of explicitly supported types in
ObjectUtils.nullSafeConciseToString() with the following.
- Optional
- File
- Path
- InetAddress
- Charset
- Currency
- TimeZone
- ZoneId
- Pattern
Closes gh-30805
This commit also reverts to using ReflectionUtils.findMethod in order
to make the check more robust in case the Micrometer team refactors the
code base and declares the `getObservationRegistry()` method in a super
type.
Prior to this commit, the required runtime dependencies were checked
via reflection each time an attempt was made to instantiate
MicrometerObservationRegistryTestExecutionListener.
Since it's sufficient to check for the presence of required runtime
dependencies only once, this commit caches the results of the
dependency checks in a static field.
This commit also introduces automated tests for the runtime dependency
checks in MicrometerObservationRegistryTestExecutionListener.
See gh-30747
Prior to this commit, dependency checks in the static initialization
block for MicrometerObservationRegistryTestExecutionListener resulted
in an ExceptionInInitializerError which led to verbose logging in
TestContextFailureHandler.
This commit improves the logging for missing dependencies in
MicrometerObservationRegistryTestExecutionListener by moving the
dependency checks to the constructor and by throwing a
NoClassDefFoundError instead of an IllegalStateException. This allows
TestContextFailureHandler to log a concise DEBUG message denoting that
the listener is being skipped due to missing dependencies.
This commit also now checks for the presence of
io.micrometer.context.ThreadLocalAccessor in addition to
io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor.
Furthermore, this commit now explicitly mentions the need for
io.micrometer:context-propagation in the error message.
The following demonstrate the generated DEBUB message when
ObservationThreadLocalAccessor and ThreadLocalAccessor are missing,
respectively.
Skipping candidate TestExecutionListener [org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener] due to a missing dependency. Specify custom TestExecutionListener classes or make the default TestExecutionListener classes and their required dependencies available. Offending class: io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor. MicrometerObservationRegistryTestExecutionListener requires io.micrometer:micrometer-observation:1.10.8 or higher and io.micrometer:context-propagation:1.0.3 or higher.
Skipping candidate TestExecutionListener [org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener] due to a missing dependency. Specify custom TestExecutionListener classes or make the default TestExecutionListener classes and their required dependencies available. Offending class: io.micrometer.context.ThreadLocalAccessor. MicrometerObservationRegistryTestExecutionListener requires io.micrometer:micrometer-observation:1.10.8 or higher and io.micrometer:context-propagation:1.0.3 or higher.
Closes gh-30747
Prior to this commit, private (and non-visible package-private)
init/destroy methods were not supported in AOT mode. The reason is that
such methods are tracked using their fully-qualified method names, and
the AOT support for init/destroy methods previously did not take
fully-qualified method names into account. In addition, the invocation
order of init/destroy methods differed vastly between standard JVM mode
and AOT mode.
This commit addresses these issues in the following ways.
- AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(),
DisposableBeanAdapter.determineDestroyMethod(), and
BeanDefinitionPropertiesCodeGenerator.addInitDestroyHint() now parse
fully-qualified method names to locate the correct init/destroy
methods.
- AbstractAutowireCapableBeanFactory and DisposableBeanAdapter delegate
to a new MethodDescriptor record which encapsulates the parsing of
fully-qualified method names; however,
BeanDefinitionPropertiesCodeGenerator duplicates this logic since it
resides in a different package, and we do not currently want to make
MethodDescriptor public.
- Init/destroy methods detected via annotations (such as @PostConstruct
and @PreDestroy) are now invoked prior to init/destroy methods that
are explicitly configured by name or convention. This aligns with the
invocation order in standard JVM mode; however,
InitializingBean#afterPropertiesSet() and DisposableBean#destroy()
are still invoked before annotated init/destroy methods in AOT mode
which differs from standard JVM mode.
- Unit and integration tests have been updated to test the revised
behavior.
Closes gh-30692
This commits changes the return type from Publisher<?> to
Object in order to avoid potential compatibility issues when
the Reactive Streams dependency is not in the classpath.
Closes gh-30716
This commit updates AbstractMessageListenerContainer's Javadoc
regarding the log level used in invokeErrorHandler() so that the
documentation aligns with the implementation, namely that errors will
logged at WARN level if no ErrorHandler has been registered.
Closes gh-30730
In the original implementation of
MicrometerObservationRegistryTestExecutionListener I accidentally
imported JUnit 5's org.junit.platform.launcher.TestExecutionListener
instead Spring's
org.springframework.test.context.TestExecutionListener. The code
therefore attempts to use the ClassLoader for the JUnit Platform's
TestExecutionListener which may fail to see the required types. In
addition, if the JUnit Platform's TestExecutionListener is not on the
classpath, the attempt to access its ClassLoader will fail.
This commit addresses this by properly using the ClassLoader for
Spring's TestExecutionListener to detect dependencies of the
MicrometerObservationRegistryTestExecutionListener.
Closes gh-30726
Prior to this commit, if an init/destroy method was package-private and
declared in a superclass in a package different from the package in
which the registered bean resided, a local init/destroy method with the
same name would effectively "shadow" the method from the different
package, resulting in only the local init/destroy method being invoked.
This commit addresses this issue by tracking package-private init
methods from different packages using their fully-qualified method
names, analogous to the existing support for private init/destroy
methods.
Closes gh-30718
Previously, a bean definition that is optimized AOT could have
different metadata based on whether its resolved type had a generic or
not. This is due to RootBeanDefinition taking either a Class or a
ResolvableType doing fundamentally different things. While the former
sets the bean class which is to little use with an instance supplier,
the latter specifies the target type of the bean.
This commit sets the target type of the bean, using the existing
setter methods that take either a class or a ResolvableType and set the
same attribute consistently.
Closes gh-30689
This commit only tests which init/destroy methods are "registered" in
AOT mode.
This commit does NOT test that the registered methods can actually be
invoked in AOT mode: that will be addressed in a separate commit.
See gh-30692
# <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%3A6.0.x) [](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".
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:
In most application scenarios, explicit user code is not required to instantiate one or
more instances of a Spring IoC container. For example, in a web application scenario, a
simple eight (or so) lines of boilerplate web descriptor XML in the `web.xml` file
of the application typically suffices (see xref:core/beans/context-introduction.adoc#context-create[Convenient ApplicationContext Instantiation for Web Applications]). If you use the
https://spring.io/tools[Spring Tools for Eclipse] (an Eclipse-powered development
environment), you can easily create this boilerplate configuration with a few mouse clicks or
keystrokes.
of the application typically suffices (see
xref:core/beans/context-introduction.adoc#context-create[Convenient ApplicationContext Instantiation for Web Applications]).
If you use the https://spring.io/tools[Spring Tools for Eclipse] (an Eclipse-powered
development environment), you can easily create this boilerplate configuration with a
few mouse clicks or keystrokes.
The following diagram shows a high-level view of how Spring works. Your application classes
are combined with configuration metadata so that, after the `ApplicationContext` is
@@ -139,9 +140,11 @@ Kotlin::
[NOTE]
====
After you learn about Spring's IoC container, you may want to know more about Spring's
`Resource` abstraction (as described in xref:web/webflux-webclient/client-builder.adoc#webflux-client-builder-reactor-resources[Resources]), which provides a convenient
mechanism for reading an InputStream from locations defined in a URI syntax. In particular,
`Resource` paths are used to construct applications contexts, as described in xref:core/resources.adoc#resources-app-ctx[Application Contexts and Resource Paths].
`Resource` abstraction (as described in
xref:core/resources.adoc[Resources])
which provides a convenient mechanism for reading an InputStream from locations defined
in a URI syntax. In particular, `Resource` paths are used to construct applications contexts,
as described in xref:core/resources.adoc#resources-app-ctx[Application Contexts and Resource Paths].
====
The following example shows the service layer objects `(services.xml)` configuration file:
@@ -208,9 +211,9 @@ XML configuration file represents a logical layer or module in your architecture
You can use the application context constructor to load bean definitions from all these
XML fragments. This constructor takes multiple `Resource` locations, as was shown in the
xref:core/beans/basics.adoc#beans-factory-instantiation[previous section]. Alternatively, use one or more
occurrences of the `<import/>` element to load bean definitions from another file or
and {api-spring-framework}/core/Ordered.html[`Ordered`] interfaces. See also the note
on xref:core/beans/factory-extension.adoc#beans-factory-programmatically-registering-beanpostprocessors[programmatic registration of `BeanPostProcessor` instances]
.
and {api-spring-framework}/core/Ordered.html[`Ordered`] interfaces. See also the note on
xref:core/beans/factory-extension.adoc#beans-factory-programmatically-registering-beanpostprocessors[programmatic registration of `BeanPostProcessor` instances].
[NOTE]
====
@@ -280,11 +279,12 @@ and {api-spring-framework}/core/Ordered.html[`Ordered`] interfaces for more deta
====
If you want to change the actual bean instances (that is, the objects that are created
from the configuration metadata), then you instead need to use a `BeanPostProcessor`
(described earlier in xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp[Customizing Beans by Using a `BeanPostProcessor`]). While it is technically possible
to work with bean instances within a `BeanFactoryPostProcessor` (for example, by using
`BeanFactory.getBean()`), doing so causes premature bean instantiation, violating the
standard container lifecycle. This may cause negative side effects, such as bypassing
bean post processing.
(described earlier in
xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp[Customizing Beans by Using a `BeanPostProcessor`]).
While it is technically possible to work with bean instances within a `BeanFactoryPostProcessor`
(for example, by using `BeanFactory.getBean()`), doing so causes premature bean instantiation,
violating the standard container lifecycle. This may cause negative side effects, such as
bypassing bean post processing.
Also, `BeanFactoryPostProcessor` instances are scoped per-container. This is only relevant
if you use container hierarchies. If you define a `BeanFactoryPostProcessor` in one
@@ -331,8 +331,7 @@ with placeholder values is defined:
However, the first of the two preceding definitions does not couple the code to Spring.
TIP: You can assign the `destroy-method` attribute of a `<bean>` element a special
`(inferred)` value, which instructs Spring to automatically detect a public `close` or
`shutdown` method on the specific bean class. (Any class that implements
`java.lang.AutoCloseable` or `java.io.Closeable` would therefore match.) You can also set
this special `(inferred)` value on the `default-destroy-method` attribute of a
`<beans>` element to apply this behavior to an entire set of beans (see
xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-default-init-destroy-methods[Default Initialization and Destroy Methods]). Note that this is the
default behavior with Java configuration.
Note that Spring also supports inference of destroymethods, detecting a public `close` or
`shutdown` method. This is the default behavior for `@Bean` methods in Java configuration
classes and automatically matches `java.lang.AutoCloseable` or `java.io.Closeable`
implementations, not coupling the destruction logic to Spring either.
TIP: For destroy method inference with XML, you may assign the `destroy-method` attribute
of a `<bean>` element a special `(inferred)` value, which instructs Spring to automatically
detect a public `close` or `shutdown` method on the bean class for a specific bean definition.
You can also set this special `(inferred)` value on the `default-destroy-method` attribute
of a `<beans>` element to apply this behavior to an entire set of bean definitions (see
xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-default-init-destroy-methods[Default Initialization and Destroy Methods]).
[NOTE]
====
For extended shutdown phases, you may implement the `Lifecycle` interface and receive
an early stop signal before the destroy methods of any singleton beans are called.
You may also implement `SmartLifecycle` for a time-bound stop step where the container
will wait for all such stop processing to complete before moving on to destroy methods.
The Spring Framework's JDBC abstraction framework consists of four different packages:
* `core`: The `org.springframework.jdbc.core` package contains the `JdbcTemplate` class and its
various callback interfaces, plus a variety of related classes. A subpackage named
`org.springframework.jdbc.core.simple` contains the `SimpleJdbcInsert` and
* `core`: The `org.springframework.jdbc.core` package contains the `JdbcTemplate` class
and its various callback interfaces, plus a variety of related classes. A subpackage
named `org.springframework.jdbc.core.simple` contains the `SimpleJdbcInsert` and
`SimpleJdbcCall` classes. Another subpackage named
`org.springframework.jdbc.core.namedparam` contains the `NamedParameterJdbcTemplate`
class and the related support classes. See xref:data-access/jdbc/core.adoc[Using the JDBC Core Classes to Control Basic JDBC Processing and Error Handling], xref:data-access/jdbc/advanced.adoc[JDBC Batch Operations], and
xref:data-access/jdbc/simple.adoc[Simplifying JDBC Operations with the `SimpleJdbc` Classes].
* `datasource`: The `org.springframework.jdbc.datasource` package contains a utility class for easy
`DataSource` access and various simple `DataSource` implementations that you can use for
testing and running unmodified JDBC code outside of a Jakarta EE container. A subpackage
named `org.springfamework.jdbc.datasource.embedded` provides support for creating
* `datasource`: The `org.springframework.jdbc.datasource` package contains a utility class
for easy `DataSource` access and various simple `DataSource` implementations that you can
use for testing and running unmodified JDBC code outside of a Jakarta EE container. A subpackage
named `org.springframework.jdbc.datasource.embedded` provides support for creating
embedded databases by using Java database engines, such as HSQL, H2, and Derby. See
xref:data-access/jdbc/connections.adoc[Controlling Database Connections] and xref:data-access/jdbc/embedded-database-support.adoc[Embedded Database Support].
* `object`: The `org.springframework.jdbc.object` package contains classes that represent RDBMS
queries, updates, and stored procedures as thread-safe, reusable objects. See
* `object`: The `org.springframework.jdbc.object` package contains classes that represent
RDBMS queries, updates, and stored procedures as thread-safe, reusable objects. See
xref:data-access/jdbc/object.adoc[Modeling JDBC Operations as Java Objects]. This approach is modeled by JDO, although objects returned by queries
are naturally disconnected from the database. This higher-level of JDBC abstraction
depends on the lower-level abstraction in the `org.springframework.jdbc.core` package.
* `support`: The `org.springframework.jdbc.support` package provides `SQLException` translation
functionality and some utility classes. Exceptions thrown during JDBC processing are
translated to exceptions defined in the `org.springframework.dao` package. This means
* `support`: The `org.springframework.jdbc.support` package provides `SQLException`
translation functionality and some utility classes. Exceptions thrown during JDBC processing
are translated to exceptions defined in the `org.springframework.dao` package. This means
that code using the Spring JDBC abstraction layer does not need to implement JDBC or
RDBMS-specific error handling. All translated exceptions are unchecked, which gives you
the option of catching the exceptions from which you can recover while letting other
@@ -11,11 +11,13 @@ specification effort to standardize access to SQL databases using reactive patte
The Spring Framework's R2DBC abstraction framework consists of two different packages:
* `core`: The `org.springframework.r2dbc.core` package contains the `DatabaseClient`
class plus a variety of related classes. See xref:data-access/r2dbc.adoc#r2dbc-core[Using the R2DBC Core Classes to Control Basic R2DBC Processing and Error Handling].
class plus a variety of related classes. See
xref:data-access/r2dbc.adoc#r2dbc-core[Using the R2DBC Core Classes to Control Basic R2DBC Processing and Error Handling].
* `connection`: The `org.springframework.r2dbc.connection` package contains a utility class
for easy `ConnectionFactory` access and various simple `ConnectionFactory` implementations
that you can use for testing and running unmodified R2DBC. See xref:data-access/r2dbc.adoc#r2dbc-connections[Controlling Database Connections].
that you can use for testing and running unmodified R2DBC. See
Used at the class level as above, the annotation indicates a default for all methods of
the declaring class (as well as its subclasses). Alternatively, each method can be
annotated individually. See xref:data-access/transaction/declarative/annotations.adoc#transaction-declarative-annotations-method-visibility[null] for
annotated individually. See xref:data-access/transaction/declarative/annotations.adoc#transaction-declarative-annotations-method-visibility[method visibility] for
further details on which methods Spring considers transactional. Note that a class-level
annotation does not apply to ancestor classes up the class hierarchy; in such a scenario,
inherited methods need to be locally redeclared in order to participate in a
@@ -124,7 +124,6 @@ In XML configuration, the `<tx:annotation-driven/>` tag provides similar conveni
----
<1> The line that makes the bean instance transactional.
TIP: You can omit the `transaction-manager` attribute in the `<tx:annotation-driven/>`
tag if the bean name of the `TransactionManager` that you want to wire in has the name
`transactionManager`. If the `TransactionManager` bean that you want to dependency-inject
@@ -194,74 +193,63 @@ Kotlin::
======
Note that there are special considerations for the returned `Publisher` with regards to
Reactive Streams cancellation signals. See the xref:data-access/transaction/programmatic.adoc#tx-prog-operator-cancel[Cancel Signals] section under
"Using the TransactionalOperator" for more details.
Micrometer defines an https://micrometer.io/docs/observation[Observation concept that enables both Metrics and Traces] in applications.
Metrics support offers a way to create timers, gauges or counters for collecting statistics about the runtime behavior of your application.
Metrics can help you to track error rates, usage patterns, performance and more.
Metrics support offers a way to create timers, gauges, or counters for collecting statistics about the runtime behavior of your application.
Metrics can help you to track error rates, usage patterns, performance, and more.
Traces provide a holistic view of an entire system, crossing application boundaries; you can zoom in on particular user requests and follow their entire completion across applications.
Spring Framework instruments various parts of its own codebase to publish observations if an `ObservationRegistry` is configured.
@@ -36,16 +36,16 @@ https://micrometer.io/docs/concepts#_naming_meters[to the format preferred by th
[[observability.concepts]]
== Micrometer Observation concepts
If you are not familiar with Micrometer Observation, here's a quick summary of the new concepts you should know about.
If you are not familiar with Micrometer Observation, here's a quick summary of the concepts you should know about.
* `Observation` is the actual recording of something happening in your application. This is processed by `ObservationHandler` implementations to produce metrics or traces.
* Each observation has a corresponding `ObservationContext` implementation; this type holds all the relevant information for extracting metadata for it.
In the case of an HTTP server observation, the context implementation could hold the HTTP request, the HTTP response, any Exception thrown during processing...
* Each `Observation` holds `KeyValues` metadata. In the case of a server HTTP observation, this could be the HTTP request method, the HTTP response status...
In the case of an HTTP server observation, the context implementation could hold the HTTP request, the HTTP response, any exception thrown during processing, and so forth.
* Each `Observation` holds `KeyValues` metadata. In the case of an HTTP server observation, this could be the HTTP request method, the HTTP response status, and so forth.
This metadata is contributed by `ObservationConvention` implementations which should declare the type of `ObservationContext` they support.
* `KeyValues` are said to be "low cardinality" if there is a low, bounded number of possible values for the `KeyValue` tuple (HTTP method is a good example).
Low cardinality values are contributed to metrics only.
High cardinality values are on the other hand unbounded (for example, HTTP request URIs) and are only contributed to Traces.
Conversely, "high cardinality" values are unbounded (for example, HTTP request URIs) and are only contributed to traces.
* An `ObservationDocumentation` documents all observations in a particular domain, listing the expected key names and their meaning.
@@ -63,16 +63,16 @@ Each instrumented component will provide two extension points:
=== Using custom Observation conventions
Let's take the example of the Spring MVC "http.server.requests" metrics instrumentation with the `ServerHttpObservationFilter`.
This observation is using a `ServerRequestObservationConvention` with a `ServerRequestObservationContext`; custom conventions can be configured on the Servlet filter.
This observation uses a `ServerRequestObservationConvention` with a `ServerRequestObservationContext`; custom conventions can be configured on the Servlet filter.
If you would like to customize the metadata produced with the observation, you can extend the `DefaultServerRequestObservationConvention` for your requirements:
You can also achieve similar goals using a custom `ObservationFilter` - adding or removing key values for an observation.
You can also achieve similar goals using a custom `ObservationFilter` – adding or removing key values for an observation.
Filters do not replace the default convention and are used as a post-processing component.
include-code::./ServerRequestObservationFilter[]
@@ -83,20 +83,24 @@ You can configure `ObservationFilter` instances on the `ObservationRegistry`.
[[observability.http-server]]
== HTTP Server instrumentation
HTTP server exchanges observations are created with the name `"http.server.requests"` for Servlet and Reactive applications.
HTTP server exchange observations are created with the name `"http.server.requests"` for Servlet and Reactive applications.
[[observability.http-server.servlet]]
=== Servlet applications
Applications need to configure the `org.springframework.web.filter.ServerHttpObservationFilter` Servlet filter in their application.
It is using the `org.springframework.http.server.observation.DefaultServerRequestObservationConvention` by default, backed by the `ServerRequestObservationContext`.
It uses the `org.springframework.http.server.observation.DefaultServerRequestObservationConvention` by default, backed by the `ServerRequestObservationContext`.
This will only record an observation as an error if the `Exception` has not been handled by the web Framework and has bubbled up to the Servlet filter.
This will only record an observation as an error if the `Exception` has not been handled by the web framework and has bubbled up to the Servlet filter.
Typically, all exceptions handled by Spring MVC's `@ExceptionHandler` and xref:web/webmvc/mvc-ann-rest-exceptions.adoc[`ProblemDetail` support] will not be recorded with the observation.
You can, at any point during request processing, set the error field on the `ObservationContext` yourself:
include-code::./UserController[]
NOTE: Because the instrumentation is done at the Servlet Filter level, the observation scope only covers the filters ordered after this one as well as the handling of the request.
Typically, Servlet container error handling is performed at a lower level and won't have any active observation or span.
For this use case, a container-specific implementation is required, such as a `org.apache.catalina.Valve` for Tomcat; this is outside of the scope of this project.
By default, the following `KeyValues` are created:
.Low cardinality Keys
@@ -104,7 +108,7 @@ By default, the following `KeyValues` are created:
|===
|Name | Description
|`exception` _(required)_|Name of the exception thrown during the exchange, or `KeyValue#NONE_VALUE`} if no exception happened.
|`method` _(required)_|Name of HTTP request method or `"none"` if the request was not received properly.
|`method` _(required)_|Name of HTTP request method or `"none"` if not a well-known method.
|`outcome` _(required)_|Outcome of the HTTP server exchange.
|`status` _(required)_|HTTP response raw status code, or `"UNKNOWN"` if no response was created.
|`uri` _(required)_|URI pattern for the matching handler if available, falling back to `REDIRECTION` for 3xx responses, `NOT_FOUND` for 404 responses, `root` for requests with no path info, and `UNKNOWN` for all other requests.
@@ -122,9 +126,9 @@ By default, the following `KeyValues` are created:
=== Reactive applications
Applications need to configure the `org.springframework.web.filter.reactive.ServerHttpObservationFilter` reactive `WebFilter` in their application.
It is using the `org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention` by default, backed by the `ServerRequestObservationContext`.
It uses the `org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention` by default, backed by the `ServerRequestObservationContext`.
This will only record an observation as an error if the `Exception` has not been handled by the web Framework and has bubbled up to the `WebFilter`.
This will only record an observation as an error if the `Exception` has not been handled by the web framework and has bubbled up to the `WebFilter`.
Typically, all exceptions handled by Spring WebFlux's `@ExceptionHandler` and xref:web/webflux/ann-rest-exceptions.adoc[`ProblemDetail` support] will not be recorded with the observation.
You can, at any point during request processing, set the error field on the `ObservationContext` yourself:
@@ -137,7 +141,7 @@ By default, the following `KeyValues` are created:
|===
|Name | Description
|`exception` _(required)_|Name of the exception thrown during the exchange, or `"none"` if no exception happened.
|`method` _(required)_|Name of HTTP request method or `"none"` if the request was not received properly.
|`method` _(required)_|Name of HTTP request method or `"none"` if not a well-known method.
|`outcome` _(required)_|Outcome of the HTTP server exchange.
|`status` _(required)_|HTTP response raw status code, or `"UNKNOWN"` if no response was created.
|`uri` _(required)_|URI pattern for the matching handler if available, falling back to `REDIRECTION` for 3xx responses, `NOT_FOUND` for 404 responses, `root` for requests with no path info, and `UNKNOWN` for all other requests.
@@ -153,9 +157,9 @@ By default, the following `KeyValues` are created:
[[observability.http-client]]
== HTTP Client instrumentation
== HTTP Client Instrumentation
HTTP client exchanges observations are created with the name `"http.client.requests"` for blocking and reactive clients.
HTTP client exchange observations are created with the name `"http.client.requests"` for blocking and reactive clients.
Unlike their server counterparts, the instrumentation is implemented directly in the client so the only required step is to configure an `ObservationRegistry` on the client.
[[observability.http-client.resttemplate]]
@@ -164,13 +168,13 @@ Unlike their server counterparts, the instrumentation is implemented directly in
Applications must configure an `ObservationRegistry` on `RestTemplate` instances to enable the instrumentation; without that, observations are "no-ops".
Spring Boot will auto-configure `RestTemplateBuilder` beans with the observation registry already set.
Instrumentation is using the `org.springframework.http.client.observation.ClientRequestObservationConvention` by default, backed by the `ClientRequestObservationContext`.
Instrumentation uses the `org.springframework.http.client.observation.ClientRequestObservationConvention` by default, backed by the `ClientRequestObservationContext`.
.Low cardinality Keys
[cols="a,a"]
|===
|Name | Description
|`method` _(required)_|Name of HTTP request method or `"none"` if the request could not be created.
|`method` _(required)_|Name of HTTP request method or `"none"` if not a well-known method.
|`uri` _(required)_|URI template used for HTTP request, or `"none"` if none was provided. Only the path part of the URI is considered.
|`client.name` _(required)_|Client name derived from the request URI host.
|`status` _(required)_|HTTP response raw status code, or `"IO_ERROR"` in case of `IOException`, or `"CLIENT_ERROR"` if no response was received.
@@ -193,13 +197,13 @@ Instrumentation is using the `org.springframework.http.client.observation.Client
Applications must configure an `ObservationRegistry` on the `WebClient` builder to enable the instrumentation; without that, observations are "no-ops".
Spring Boot will auto-configure `WebClient.Builder` beans with the observation registry already set.
Instrumentation is using the `org.springframework.web.reactive.function.client.ClientRequestObservationConvention` by default, backed by the `ClientRequestObservationContext`.
Instrumentation uses the `org.springframework.web.reactive.function.client.ClientRequestObservationConvention` by default, backed by the `ClientRequestObservationContext`.
.Low cardinality Keys
[cols="a,a"]
|===
|Name | Description
|`method` _(required)_|Name of HTTP request method or `"none"` if the request could not be created.
|`method` _(required)_|Name of HTTP request method or `"none"` if not a well-known method.
|`uri` _(required)_|URI template used for HTTP request, or `"none"` if none was provided. Only the path part of the URI is considered.
|`client.name` _(required)_|Client name derived from the request URI host.
|`status` _(required)_|HTTP response raw status code, or `"IO_ERROR"` in case of `IOException`, or `"CLIENT_ERROR"` if no response was received.
@@ -10,7 +10,7 @@ Resource locations are typically XML configuration files or Groovy scripts locat
classpath, while component classes are typically `@Configuration` classes. However,
resource locations can also refer to files and scripts in the file system, and component
classes can be `@Component` classes, `@Service` classes, and so on. See
xref:testing/testcontext-framework/ctx-management/javaconfig.adoc#testcontext-ctx-management-javaconfig-component-classes[null] for further details.
xref:testing/testcontext-framework/ctx-management/javaconfig.adoc#testcontext-ctx-management-javaconfig-component-classes[Component Classes] for further details.
The following example shows a `@ContextConfiguration` annotation that refers to an XML
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.