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