Prior to this commit, searches for non-public repeatable annotations
failed with error messages similar to the following, since the
repeatable annotation's container's `value()` method could not be
invoked via reflection.
JDK 8:
java.lang.IllegalAccessError: tried to access class
org.springframework.core.annotation.NestedRepeatableAnnotationsTests$A
from class com.sun.proxy.$Proxy12
JDK 17:
java.lang.IllegalAccessError: failed to access class
org.springframework.core.annotation.NestedRepeatableAnnotationsTests$A
from class jdk.proxy2.$Proxy12
(org.springframework.core.annotation.NestedRepeatableAnnotationsTests$A
is in unnamed module of loader 'app'; jdk.proxy2.$Proxy12 is in module
jdk.proxy2 of loader 'app')
This commit makes it possible to search for non-public repeatable
annotations by first attempting to invoke the repeatable annotation's
container's `value()` method via the container's InvocationHandler (if
the container is a JDK dynamic proxy) and then falling back to
reflection for the method invocation if an error occurs (such as a
SecurityException).
Closes gh-29301
This commit is a follow up to 828f74f71a
and applies to same fix for getMergedRepeatableAnnotations().
See the previous commit for details.
Closes gh-20279
Prior to this commit, the findMergedRepeatableAnnotations() methods in
AnnotatedElementUtils failed to find repeatable annotations declared
on other repeatable annotations (i.e., when one repeatable annotation
type was used as a meta-annotation on a different repeatable annotation
type).
The reason is that
findMergedRepeatableAnnotations(element, annotationType, containerType)
always used RepeatableContainers.of(annotationType, containerType) to
create a RepeatableContainers instance, even if the supplied
containerType was null. Doing so restricts the search to supporting
only repeatable annotations whose container is the supplied
containerType and prevents the search from finding repeatable
annotations declared as meta-annotations on other types of repeatable
annotations.
Note, however, that direct use of the MergedAnnotations API already
supported finding nested repeatable annotations when using
RepeatableContainers.standardRepeatables() or
RepeatableContainers.of(...).and(...).and(...). The latter composes
support for multiple repeatable annotation types and their containers.
This commit addresses the issue for findMergedRepeatableAnnotations()
when the containerType is null or not provided.
However, findMergedRepeatableAnnotations(element, annotationType, containerType)
still suffers from the aforementioned limitation, and the Javadoc has
been updated to make that clear.
Closes gh-20279
In order to keep the maximum of flexibility, this commit makes
shouldSkipType and shouldSkipMembers methods private.
That will allow for example to refactor
BindingReflectionHintsRegistrar in order to support skipping
custom classes specified via @RegisterReflectionForBinding
without having to subclass it.
See gh-29279
This commit also removes ResourcePropertiesPersister which
was introduced in 5.3 specifically for spring.xml.ignore
flag and which is expected to be used only internally by
Spring Framework. DefaultPropertiesPersister should be used
instead.
Closes gh-29277
This commit introduces a shouldSkipType(Class<?> type) method
and changes shouldRegisterMembers(Class<?> type) to
shouldSkipMembers(Class<?> type).
Closes gh-29279
Prior to this commit, if a FileSystemResource was created from a
java.nio.file.Path or java.nio.file.FileSystem, the URI returned from
getURI() was based on the semantics of Path#toUri() which always
includes the "authority component" (i.e., "//") after the scheme (e.g.,
"file://..."). In contrast, if a FileSystemResource is created from a
java.io.File or String, the URI returned from getURI() never includes
the "authority component" due to the semantics of File#toURI().
Consequently, invoking myFileSystemResource.getURI().toString() could
result in "file:/my/path" or "file:///my/path", depending on how the
FileSystemResource was created.
This behavior is not new; however, recent changes in
PathMatchingResourcePatternResolver -- which result in a
FileSystemResource being created from a java.nio.file.Path instead of
from a java.io.File -- make this difference more noticeable to users
and may in fact surface as a breaking change.
To address that issue, this commit revises the implementation of
FileSystemResource.getURI() by normalizing any `file:` URIs that it
returns. Effectively, URIs like "file:///my/path" will now take the
form "file:/my/path".
See gh-29163
Closes gh-29275
Prior to this commit, if two ClassPathResource instances were
constructed differently (one from an absolute path and one from a path
relative to a Class) but had the same absolute path and the same
ClassLoader, they were effectively equal, but ClassPathResource#equals
returned false.
This commit addresses this by revising the logic in
ClassPathResource#equals accordingly.
Closes gh-29263
Prior to this commit, UrlResource#getFilename() returned the filename
of the resource URL-encoded which is in contrast to what
FileSystemResource#getFilename() returns for an equivalent resource.
In addition, users most likely expect that a filename returned from a
method defined in the Resource interface is unencoded.
This commit therefore revises UrlResource#getFilename() so that it
always returns the filename URL-decoded.
Closes gh-29261
This commit introduces assertions that verify that the sub-path is
properly URL-decoded when a path contains `#`. The additional assertions
are necessary since the existing assertions use Resource#getFilename
which already implicitly decodes the path.
See gh-29243
This commit introduces tests which serve as "regression tests" for the
behavior of PathMatchingResourcePatternResolver in Spring Framework
5.3.x with regard to URL-encoding and Unicode normalization of resource
paths.
Specifically, the new tests demonstrate that resource paths do NOT need
to be decoded or normalized in 5.3.x.
See gh-29243
Prior to this commit, the parsing algorithm in
`StringUtils#parseLocaleString` would skip empty tokens, turning
`en__VARIANT` into `en_VARIANT` when parsed.
This commit ensures that such cases are now supported and that more
invalid formats are rejected by the parser.
Fixes gh-29248
This commit adapts AccessVisibility so that it can determine if the
member or type signature is accessible from a given package. This lets
implementers figure out if reflection is necessary without assuming that
package private visibility is OK.
Closes gh-29245
In addition to consistent use of cleaned file paths, this revision avoids FileSystem SPI interaction, resolving NIO Path instances from URI (and FileSystemResource from Path).
See gh-29226
Prior to this commit, the AOT infrastructure would rely on the fact that
native runtime reflection on a type would only consider
methods/fields/constructors that had specific hints contributed. When
listing them through the reflection API on the type, the native image
would only return those for which we had hints contributed.
This behavior will soon change in GraalVM and will better align with the
JVM behavior: when asking for all declared methods on a type in a native
image, we should get all existing methods, not just the ones registered
previously in the native image.
This commit aligns the behavior of the `RuntimeHintsAgent` and removes
the now misleading predicates as a consequence.
Closes gh-29205
Commit 0eb66789ed which introduced generic FileSystem support in
PathMatchingResourcePatternResolver also introduced a regression in that
a matching folder is now returned in the results.
This commit address this by additionally using Files#isRegularFile() in
the predicate used to filter candidates.
Closes gh-29163
The upgrade to SLF4J 2 via gh-29152 has broken
ConstantFieldSubstitutionProcessor when the class processed
has both a static boolean field to make constant at build
time and a static logger.
This issue is about catching and logging those errors,
skipping the processing of such fields which will be
then evaluated at runtime.
Closes gh-29219
The JDK has decent support for walking a file system (via the
FileSystem API in java.nio.file), but prior to this commit Spring still
used hand-rolled pre-Java 7 code. Also, in principle, FileSystem can be
an abstraction used to express any hierarchy of resources through their
URIs. This is a good fit with the Spring Resource abstraction, and for
instance would mean that GraalVM native images could potentially do
classpath scanning through a custom URI and FileSystem already provided
by GraalVM.
In light of the above, this commit overhauls the implementation of
PathMatchingResourcePatternResolver to use a java.nio.file.FileSystem
to find matching resources within a file system.
As a side effect, several obsolete `protected` methods have been
removed from PathMatchingResourcePatternResolver.
See gh-29163
This commit improves GeneratedClass to support inner classes, allowing
them to be registered by name with a type customizer, as
GeneratedClasses does for top level classes.
BeanDefinitionMethodGenerator leverages this feature to create a
matching structure for configuration classes that contain inner classes.
Closes gh-29213
This commit adds an overloaded version of invokeSuspendingFunction
that specifies a CoroutineContext, instead of using
Dispatchers.Unconfined.
Closes gh-27193
This commit updates ClassNameGenerator so that it uses a ClassName for
its default target. This makes sure that a target that has been
generated can be used.
See gh-29027
In general, `Stream#toList()` is not a transparent replacement for
`.collect(Collectors.toList()))`, as the former returns an immutable
list.
This commit reverts some of those changes, where the returned `List`
instance was expected to be mutable.
See gh-29203
Prior to this commit, resource handling would not serve empty files and
return instead HTTP 404 responses. This would only happen for files
contained by JARs, but not on the filesystem.
This can be tracked to changes done in `AbstractFileResolvingResource`
where we avoid serving empty files for directories, see gh-21372.
This commit improves the `checkReadable` method to align this behavior
between file system and JAR files.
Closes gh-28850
Prior to this commit, the following exception was thrown when using the
PathMatchingResourcePatternResolver to scan for class path resources
using the `classpath*:` prefix within a native image.
com.oracle.svm.core.jdk.UnsupportedFeatureError: JRT file system is disabled
com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89)
jdk.internal.module.SystemModuleFinders$SystemImage.reader(SystemModuleFinders.java:139)
jdk.internal.module.SystemModuleFinders$ModuleContentSpliterator.<init>(SystemModuleFinders.java:527)
jdk.internal.module.SystemModuleFinders$SystemModuleReader.list(SystemModuleFinders.java:502)
org.springframework.core.io.support.PathMatchingResourcePatternResolver.lambda$findAllModulePathResources$6(PathMatchingResourcePatternResolver.java:819)
This commit addresses this by not attempting to scan the module path
when running in a GraalVM native image.
Closes gh-29183
In preparation for gh-29163, this commit revamps
PathMatchingResourcePatternResolverTests as follows.
- organizes tests into @Nested test classes
- reintroduces the @Disabled classpathStarWithPatternOnFileSystem() test
- stops asserting the protocol of Resource URLs, since the protocol is
dependent on the environment -- for example, file: and jar: URLs are
actually resource: URLs within a GraalVM native image
- simplifies implementation of test methods and assertFilenames()
Previously, only the first occurance of `@Reflective` and its
processor was considered. When `@Reflective` appeared twice on a type
due to meta-annotations or inheritance, this resulted in other
processors being ignored and hints were missing as a result.
This commit updates ReflectiveRuntimeHintsRegistrar to consider
every occurance of `@Reflective` found in the type hierarchy,
and to then use the processors from each of them.
Fixes gh-29193
gh-28506 introduces a big footprint regression on
native, so it should for now be skipped when
compiling to native images. Such support could
potentially be re-introduced via gh-29081.
Closes gh-29183
This commit fixes an issue in StringDecoder, where, if the buffer did
not contain any delimiters, it was released before it was relayed to
any subscribers.
Closes gh-29119
This commit adds predicates variants that accept `String className`
instead of actual `Class<?>` when checking for fields and method hints.
This is useful when the type under test is not visible from the current
test class.
Closes gh-29143
Prior to this commit, the Javadoc for the getPath() method in
ClassPathResource stated the following.
> Return the path for this resource (as resource path within the class path).
That implied the returned path was an "absolute path" within the class
path; however, that was not always true.
If the resource was created using ClassPathResource(String) or
ClassPathResource(String, ClassLoader), the returned path was a cleaned
version of the ABSOLUTE PATH supplied to the constructor, WITHOUT a
leading slash.
If the resource was created using ClassPathResource(String, Class) with
an absolute path, the returned path was a cleaned version of the
ABSOLUTE PATH supplied to the constructor, WITH a leading slash.
If the resource was created using ClassPathResource(String, Class) with
a relative path, the returned path was a cleaned version of the
RELATIVE PATH supplied to the constructor.
In addition, ClassPathResource does not provide public access the Class
passed to the ClassPathResource(String, Class) constructor.
Consequently, the path returned by getPath() could not be reliably used
with ClassLoader.getResource(String) or with the recently introduced
registerResource(Resource) method in ResourceHints.
This commit addresses this issue by ensuring that getPath()
consistently returns the absolute path within the class path without a
leading slash.
See gh-29083
Reverts gh-29094
Closes gh-29099
Previously, a shortcut method for the default ExecutableMode was
provided, but we found out that the shortcut makes it harder to
determine the intent.
This commit harmonizes hints registration for types, methods, and
fields. An ExecutableMode is now mandatory to register a method or
constructor. Previous methods that infer a mode or provided a
customizer of the builder are deprecated.
Closes gh-29135
In recent GraalVM versions, allowWrite and allowUnsafeAccess have been
deprecated and are no longer use. This commit updates FieldHint to
remove the irrelevant properties.
See gh-29130
Update StreamUtils.drain to use InputStream.transferTo with a null
OutputStream. This avoids allocating buffers for cases where the
supplied InputStream has an optimized transferTo method (e.g.,
ByteArrayInputStream and FileInputStream).
Additionally, update StreamUtils.emptyInput to simply call
InputStream.nullInputStream.
Closes gh-28961
This commit records `@PropertySource` declarations defined on
configuration classes so that these are contributed to the environment
of a context that is initialized by generated code.
Closes gh-28976
This commit moves MethodReference to an interface with a default
implementation that relies on a MethodSpec. Such an arrangement avoid
the need of specifying attributes of the method such as whether it is
static or not.
The resolution of the invocation block now takes an
ArgumentCodeGenerator rather than the raw arguments. Doing so gives
the opportunity to create more flexible signatures.
See gh-29005
This commit updates GeneratedMethod and its underlying infrastructure
to be able to produce a MethodReference. This simplifies the need when
such a reference needs to be created manually and reuses more of what
MethodReference has to offer.
See gh-29005
This commit renames registerResourceIfNecessary() to registerResource()
and throws an exception if the class path resource does not exist.
Closes gh-29083
This aligns the buffer size used in StreamUtils with the buffer sizes
used throughout the JDK (see InputStream, BufferedInputStream, Files).
Closes gh-28965
As of Java 18, the serial lint warning in javac has been expanded to
check for class fields that are not marked as `Serializable`.
See https://www.oracle.com/java/technologies/javase/18all-relnotes.html#JDK-8202056
In the Spring Framework codebase, this can happen with `Map`, `Set` or
`List` attributes which are often assigned with an unmodifiable
implementation variant. Such implementations are `Serializable` but
cannot be used as field types.
This commit ensures that the following changes are applied:
* fields are marked as transient if they can't be serialized
* classes are marked as `Serializable` if this was missing
* `@SuppressWarnings("serial")` is applied where relevant
Prior to this commit, the `RuntimeHintsAgent` and its testing
infrastructure would assume that calling `MyClass.class.getMethods()`
requires a reflection hint on the class for introspecting public/private
methods.
GraalVM does not require this, in fact this call only returns methods
that have reflection hints in the native image.
This commit refines the agent behavior for `Class.getMethods()`,
`Class.getDeclaredMethods()`, `Class.getFields()` and
`Class.getDeclaredFields()`. With this change, registering at least one
method/field for reflection is enough to match.
During the execution of Java tests, all methods and fields will be
provided, regardless of hints being registered or not. This could cause
false negatives where we're missing reflection hints on methods or
fields.
This risk is mitigated thanks to additional instrumentation on
`Method.getAnnotations()`, `Method.getParameterTypes()` and
`Method.invoke()`. If a method is found reflectively, chances are it
will be used for further reflection.
Closes gh-29091
Since getPath() returns a relative path if the resource was created
using the ClassPathResource(String,Class) constructor, there was
previously no way to consistently obtain the absolute path to the
resource within the class path.
This commit addresses this shortcoming by introducing a new
getAbsolutePath() for consistently obtaining the absolute path to the
resource within the class path.
See gh-29083
Closes gh-29094
This commit introduces a new registerResourceIfNecessary() method in
RuntimeHintsUtils that simplifies the registration of hints for
`classpath:` resources.
Closes gh-29083
Prior to this commit, if a ResourcePatternHint was created with a
resource pattern with a leading slash, the hint was registered and
eventually converted to configuration for the GraalVM native image
compiler.
However, such a resource pattern is invalid for GraalVM. Consequently,
the registered resources were not available within the compiled native
image.
This commit ensures that registered patterns are applicable in a native
image by preventing creation of a ResourcePatternHint with a pattern
with a leading slash.
Closes gh-29088
Prior to this commit, if the TypeReference supplied to
ResourceHintsPredicates.forResource(TypeReference,String) was for a
class declared in the default package (i.e., without a package), the
resolveAbsoluteResourceName() method incorrectly prepended two leading
slashes (//) to the absolute resource name, causing correct matches to
fail.
This commit fixes this by adding special handling for a TypeReference
without a package name. In addition, this commit introduces lenient
handling of resource names by consistently removing a leading slash in
ResourceHintsPredicates.forResource(*) methods. The latter aligns with
absolute resource path handling in other places in the framework, such
as ClassPathResource.
Closes gh-29086
This commit adds support generating graalvm `jni-config.json` file.
Configuration format for jni/reflection in graalvm is documented
to be exactly same so we can re-use facilities for reflection hints
which should be relatively clean for a user as also graalvm uses same
classes for both jni/reflection.
Closes gh-29007
This annotation and the related processor allows to
register reflection hints for data binding purpose
(class, fields, properties, record components for
the whole type hierarchy)
Closes gh-28979
This commit provides an alternative
java.beans.Introspector#findCustomizerClass implementation
via a GraalVM substitution that avoids to include thousands
of unused AWT classes in the native image.
Closes gh-29060
Since Spring no longer adds the SynthesizedAnnotation interface to the
JDK dynamic proxy used to synthesize an annotation, this commit
officially deprecates SynthesizedAnnotation and related methods in
RuntimeHintsUtils.
See gh-29041, gh-29054
Closes gh-29053
SynthesizedAnnotation was originally introduced as a convenience for
easily detecting if an annotation had been synthesized by Spring via a
simple `if (myAnnotation instanceof SynthesizedAnnotation)` check.
However, the introduction of SynthesizedAnnotation in the JDK dynamic
proxy for a synthesized annotation results in a separate proxy class
for each annotation synthesized by Spring, and this causes issues with
GraalVM native images since users and framework developers must always
ensure that the additional proxy classes are registered.
This commit completely removes the use of SynthesizedAnnotation in
synthesized annotation proxies. This change allows the proxy class for
an annotation to be reused for a synthesized annotation of the same
annotation type.
Consequently:
- Extra proxy classes are not generated on the JVM or in a native image.
- Extra proxy classes are not required to be registered for a native image.
Closes gh-29041
Add `MemberCategory` and `FieldMode` shortcuts for type registration.
Helper `builtWith` methods have also been extracted to the Hint types
to allow general reuse (for example with `registerTypes`).
See gh-29011
Add a `FieldMode` enum analogous to `ExecutableHint` and update
`FieldHint` to ensure that registration cannot downgrade `WRITE`
to `READ`.
Fixes gh-29055
Reduce the visibility of hint factory methods that return a `Builder`.
Since the `build()` method of the `Builder` is package-private the
factory methods can also be package-private.
Since SynthesizedAnnotation will be deprecated (and potentially
completely removed) in Spring Framework 6.0, this commit introduces
AnnotationUtils.isSynthesizedAnnotation(Annotation) in 5.3.x to allow
people to migrate away from relying on SynthesizedAnnotation.
Closes gh-29054
Prior to this commit, the `ConcurrentLruCache` implementation would not
perform well under certain conditions. As long as the cache capacity was
not reached, the cache would avoid maintaining an eviction queue
(reordering entries depending with least/most recently read). When the
cache capacity was reached, the LRU queue was updated for each
read/write operation. This decreased performance significantly under
contention when the capacity was reached.
This commit completely rewrites the internals of `ConcurrentLruCache`.
`ConcurrentLruCache` is now a specialized version of the
`ConcurrentLinkedHashMap` [1]. This change focuses on buferring read and
write operations, only processing them at certain times to avoid
contention.
When a cached entry is read, a read operation is queued and buffered
operations are drained if the buffer reached a fixed limit. When a new
cache entry is added or removed, a write operation is queued and
triggers a drain attempt. When the capacity is outgrown, the cache polls
items from the eviction queue, which maintains elements with the
least recently used ones first. Entries are removed until the capacity
is under control.
The behavior described here and the buffer sizes are optimized with the
number of available processors in mind. Work is localized as much as
possible on a per-thread basis to avoid contention on the eviction queue.
The new implementation has been tested with the JMH benchmark provided
here, comparing the former `COncurrentLruCache`, the new implementation
as well as the `ConcurrentLinkedHashMap` [1].
When testing with a cache reaching capacity, under contention, with a
10% cache miss, we're seeing a 40x improvement compared to the previous
implementation and performance on par with the reference.
See [2] for how to replicate the benchmark.
[1] https://github.com/ben-manes/concurrentlinkedhashmap
[2] https://github.com/spring-projects/spring-framework/wiki/Micro-Benchmarks
Closes gh-26320
This commit introduces support for Netty 5's Buffer, in the form of
Netty5DataBuffer. Because of the new API offered by Buffer, several
changes have been made to the DataBuffer API:
- CloseableDataBuffer is a simpler alternative to PooledDataBuffer, and
implemented by Netty5DataBuffer. DataBufferUtils::release can now
handle CloseableDataBuffer as well as PooledDataBuffer.
- PooledDataBuffer::touch has been moved into a separate interface:
TouchableDataBuffer, which is implemented by Netty5DataBuffer.
- The capacity of DataBuffers can no longer be reduced, they can only
grow larger. As a consequence, DataBuffer::capacity(int) has been
deprecated, but ensureWritable (formally ensureCapacity) still exists.
- DataBuffer::slice and retainedSlice have been deprecated in favor of
split, a new method that ensures that memory regions do not overlap.
- DataBuffer::asByteBuffer has been deprecated in favor of toByteBuffer,
a new method that returns a copy, instead of shared data.
- DataBufferFactory::allocateBuffer has been deprecated in favor of
allocateBuffer(int).
Closes gh-28874
This commit adapts the registration of fields, constructors, and methods
to provide the same convenience than the reflection-based one available
in ReflectionHints.
See gh-29011
This commit harmonizes the registration of an executable so that
the default method and the method that takes an empty customizer
produces the same hint. The same applies to the readable flag of
a field hint.
Rather than returning a list of executable modes, the "highest" mode
is retained.
See gh-29011
Prior to this commit, if infrastructure code working directly with an
instance of DefaultGenerationContext invoked withName() on that
instance, the new GenerationContext had to be cast from
GenerationContext to DefaultGenerationContext in order for the
infrastructure to continue working with the DefaultGenerationContext
API -- for example, the writeGeneratedContent() method which is not
defined in the GenerationContext API.
This commit makes use of a covariant return type by declaring that
DefaultGenerationContext.withName() returns a DefaultGenerationContext.
Prior to this commit, it was possible to create a DefaultGenerationContext
based on a ClassNameGenerator and GeneratedFiles; however, there was no way
to create a DefaultGenerationContext that reused an existing RuntimeHints
instance which is necessary in certain use cases -- for example, in the
TestContext framework where multiple GenerationContexts are created
based on shared instances of GeneratedFiles and RuntimeHints.
This commit addresses this by introducing a public
DefaultGenerationContext(ClassNameGenerator,GeneratedFiles,RuntimeHints)
constructor.
Based on the feedback in #28977 an easy way to create a list of
type references based on a vararg of classes is helpful when
registering the same hints for several types.
This commit updates RuntimeHintsUtils to focus on registering a JDK
proxy only as annotations of annotated elements that have at least
an introspection hints are visible out-of-the-box.
This commit also removes unnecessary hints and adapt `@Reflective` to
detect if a hint is required using the introduced
MergedAnnotation#isSynthesizable.
See gh-28967
This commit adds the ability to check if a the annotation managed by
a MergedAnnotation is synthesizable. This makes it easier to register
a JDK proxy hint if necessary
See gh-28967
The DefaultGenerationContext constructor which accepts an instance of
GeneratedClasses is now package private since GeneratedClasses can only
be created within the `org.springframework.aot.generate` package.
This commit updates ApplicationContextAotGenerator to register a
handler that process Cglib generated classes. The handler registers
such classes to the GeneratedFiles and provide a hint so that it
can be instantiated using reflection.
Closes gh-28954
Includes runtime storing of generated classes to a directory specified by the "cglib.generatedClasses" system property. Avoids lazy CGLIB fast-class generation and replaces generated Enhancer and MethodWrapper key classes with equivalent record types. Introduces support for early type determination in InstantiationStrategy, AopProxy and SmartInstantiationAwareBeanPostProcessor - in order to trigger CGLIB class generation in refreshForAotProcessing (through early determineBeanType calls for bean definitions).
Closes gh-28115
NestedIOException has been removed in Spring Framework 6 and this commit
marks it as deprecated in 5.x. Users that were relying on this exception
should use IOException directly.
Closes gh-28929
Prior to this commit, the `AbstractFileResolvingResource` would
provide a default implementation for `customizeConnection` which only
sets the HTTP request method as "HEAD".
While this is consistent with its usage within that class (in
`exists()`, `contentLength()` or `lastModified()`), this is not opened
for general usage by sub-classes.
`UrlResource` is an example of that, where its `getInputStream()` method
does not call this customization method.
This not only prevents implementations from calling
`customizeConnection` in various cases, but it also misleads developers
as they might think that customizations will be applied automatically.
This commit ensures that `customizeConnection` is called in all relevant
places and that the configuration of the HTTP method is instead done in
each method as it is use case specific.
Fixes gh-28909
Add a new `ShadowSource` Gradle task and update `spring-core.gradle`
to include source for cglib, javapoet and objenesis.
Closes gh-28892
Co-authored-by: Andy Wilkinson <wilkinsona@vmware.com>
This commit adds a dedicated method for annotations that are used as
meta-annotation when the composed annotation does not require to be
visible at runtime.
Closes gh-28887
Prior to this commit, the ApiDiff Gradle task would be configured for
all submodules of the Spring Framework project and would assume that
they all existed for the baseline version considered for the API diff.
This would cause issues when:
* the sub-project is not published as it's not an official "spring-*"
module
* the "spring-*" module is new and did not exist for the baseline
version
This commit ensures that only "spring-*" modules are considered for this
task and that we trigger an early resolution of the baseline version -
if the version doesn't exist, a warn message is logged and we assume
that this is a new module, to be compared with an empty configuration.
This commit also renames the "spring-core-graalvm" project to
"graalvm-feature", since this sub-project is not an official module
published to Maven Central, but rather an internal dependency.
Fixes gh-28818
This commit deprecates ListenableFuture in favor of CompletableFuture.
ListenableFuture was introduced in Spring Framework 4.0, when
CompletableFuture was not yet available. Spring now requires JDK 17, so
having our own type no longer seems necessary.
Major changes in this commit include:
- Deprecation of ListenableFuture and related types
(ListenableFutureCallback, SettableListenableFuture, etc.)
- Deprecation of AsyncListenableTaskExecutor in favor of default methods
in AsyncTaskExecutor (submitCompletable).
- AsyncHandlerMethodReturnValueHandler now has toCompletableFuture
instead of toListenableFuture.
- WebSocketClient now has execute methods, which do the same as
doHandshake, but return CompletableFutures (cf. the reactive
WebSocketClient).
All other changes
- add an overloaded method that takes a CompletableFuture parameter
instead of ListenableFuture, and/or
- add a method with a 'Async' suffix that returns a CompletableFuture
instead of a ListenableFuture (connectAsync, sendAsync).
Closes gh-27780
This commit polishes DefaultGenerationContext to make the method
that flushes generated classes more explicit. It now throws an
IOException and TestGenerationContext has been updated to handle
that to ease its use in code that can't throw such an exception.
As this use case is likely to happen outside the Spring Framework,
this commit adds such a convenience to spring-test as well.
Closes gh-28877
Migrate all AOT tests to make use of `GeneratedClasses` rather than
directly generating Java files. This commit also refines and polishes
AOT APIs to being greater consistency.
Specifically:
- The `MethodGenerator` interface has been removed in favor of
working directly with `GeneratedMethods`.
- The visibility of several constructors and methods has been
reduced to package-private.
- The `using(...)` and `builder` methods have been removed in
favor of setting the `Consumer` callbacks directly as
constructor arguments.
- Variable names for builders are now named `type` or `method`
depending on what they're building.
Closes gh-28831