Prior to this commit, annotations were not found on parameters in an
overridden method unless the method was public. Specifically, the
search algorithm in AnnotatedMethod did not consider a protected or
package-private method in a superclass to be a potential override
candidate. This affects parameter annotation searches in
spring-messaging, spring-webmvc, spring-webflux, and any other
components that use or extend AnnotatedMethod.
To address that, this commit revises the search algorithm in
AnnotatedMethod to consider all non-final declared methods as potential
override candidates, thereby aligning with the search logic in
AnnotationsScanner for the MergedAnnotations API.
Closes gh-35349
Prior to this commit, gh-32097 added native support for Jetty for both
client and server integrations. The `JettyDataBufferFactory` was
promoted as a first class citizen, extracted from a private class in the
client support. To accomodate with server-side requirements, an extra
`buffer.retain()` call was performed.
While this is useful for server-side support, this introduced a bug in
the data buffer factory, as wrapping an existing chunk means that this
chunk is already retained.
This commit fixes the buffer factory implementation and moved existing
tests from mocks to actual pooled buffer implementations from Jetty.
The extra `buffer.retain()` is now done from the server support, right
before wrapping the buffer.
Fixes gh-35319
Prior to this commit, the MergedAnnotations support (specifically
AnnotationsScanner) and AnnotatedMethod did not find annotations on
overridden methods in type hierarchies with unresolved generics.
The reason for this is that ResolvableType.resolve() returns null for
such an unresolved type, which prevents the search algorithms from
considering such methods as override candidates.
For example, given the following type hierarchy, the compiler does not
generate a method corresponding to processOneAndTwo(Long, String) for
GenericInterfaceImpl. Nonetheless, one would expect an invocation of
processOneAndTwo(Long, String) to be @Transactional since it is
effectively an invocation of processOneAndTwo(Long, C) in
GenericAbstractSuperclass, which overrides/implements
processOneAndTwo(A, B) in GenericInterface, which is annotated with
@Transactional.
However, the MergedAnnotations infrastructure currently does not
determine that processOneAndTwo(Long, C) is @Transactional since it is
not able to determine that processOneAndTwo(Long, C) overrides
processOneAndTwo(A, B) because of the unresolved generic C.
interface GenericInterface<A, B> {
@Transactional
void processOneAndTwo(A value1, B value2);
}
abstract class GenericAbstractSuperclass<C> implements GenericInterface<Long, C> {
@Override
public void processOneAndTwo(Long value1, C value2) {
}
}
static GenericInterfaceImpl extends GenericAbstractSuperclass<String> {
}
To address such issues, this commit changes the logic in
AnnotationsScanner.hasSameGenericTypeParameters() and
AnnotatedMethod.isOverrideFor() so that they use
ResolvableType.toClass() instead of ResolvableType.resolve(). The
former returns Object.class for an unresolved generic which in turn
allows the search algorithms to properly detect method overrides in
such type hierarchies.
Closes gh-35342
Backport Bot / build (push) Has been cancelledDetails
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Has been cancelledDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:ubuntu-latest name:Linux]) (push) Has been cancelledDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:21], map[id:ubuntu-latest name:Linux]) (push) Has been cancelledDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:23], map[id:ubuntu-latest name:Linux]) (push) Has been cancelledDetails
Deploy Docs / Dispatch docs deployment (push) Has been cancelledDetails
Build and Deploy Snapshot / Verify (push) Has been cancelledDetails
Refine the StringUtils#uriDecode method in the following ways:
- Use a StringBuilder instead of ByteArrayOutputStream, and only decode
%-encoded sequences.
- Use HexFormat.fromHexDigits to decode hex sequences.
- Decode to a byte array that is only allocated if encoded sequences are
encountered.
This commit adds another optimization mainly for the use case where
there is no encoded sequence, and updates the Javadoc of both
StringUtils#uriDecode and UriUtils#decode to match the implementation.
Signed-off-by: Patrick Strawderman <pstrawderman@netflix.com>
Co-Authored-by: Sebastien Deleuze <sebastien.deleuze@broadcom.com>
Closes gh-35253
If an application depends on automatic type conversion from
java.time.Instant to java.sql.Timestamp, the ObjectToObjectConverter
performs the conversion based on convention, by using reflection to
invoke Timestamp.from(Instant).
However, when running in a native image a user needs to explicitly
register runtime hints for that particular use of reflection.
To assist users who are running their applications in a native image,
this commit automatically registers the necessary runtime hints for
Timestamp.from(Instant) so that users do not have to.
See gh-35175
Closes gh-35156
In order to avoid unnecessary use of reflection and to simplify native
image deployments, this commit introduces explicit support for
automatic conversions from java.util.Date to java.time.Instant and vice
versa.
To achieve that, this commit introduces an InstantToDateConverter and a
DateToInstantConverter and registers them automatically in
DefaultConversionService.
See gh-35156
Closes gh-35175
Update `SpringFactoriesLoader` so that the cache stores only the
factories and not the complete loader.
Prior to this commit, if a cache entry was added with the thread
context classloader, the loader instance would be added and the
classloader stored. If the thread context classloader subsequently
changes, and a call is made to `forDefaultResourceLocation` with
`null` for the classloader, the cached entry would be used which
contains the older classloader.
Closes gh-34732
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to runDetails
Build and Deploy Snapshot / Verify (push) Blocked by required conditionsDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:ubuntu-latest name:Linux]) (push) Waiting to runDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:21], map[id:ubuntu-latest name:Linux]) (push) Waiting to runDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:23], map[id:ubuntu-latest name:Linux]) (push) Waiting to runDetails
Deploy Docs / Dispatch docs deployment (push) Waiting to runDetails
This commit simplifies our dependency management for JUnit artifacts by
making use of the junit-jupiter and junit-platform-suite aggregator
artifacts.
Closes gh-35127
Add optimized DataBufferInputStream overrides for readNBytes, skip, and transferTo; all of them
allocate byte buffers which we can either avoid (in the case of skip) or size more precisely since
the number of remaining bytes is known.
Closes gh-34799
Signed-off-by: Patrick Strawderman <pstrawderman@netflix.com>
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to runDetails
Build and Deploy Snapshot / Verify (push) Blocked by required conditionsDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:ubuntu-latest name:Linux]) (push) Waiting to runDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:21], map[id:ubuntu-latest name:Linux]) (push) Waiting to runDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:23], map[id:ubuntu-latest name:Linux]) (push) Waiting to runDetails
Deploy Docs / Dispatch docs deployment (push) Waiting to runDetails
NonClosingInputStream extends FilterInputStream, which does not forward some
newer InputStream methods such as transferTo and readAllBytes. Specific InputStream
implementations may have more optimized methods (e.g., FileInputStream).
Closes gh-34893
Signed-off-by: Patrick Strawderman <pstrawderman@netflix.com>
Spring Framework 6.2 introduced support for an escape character for
property placeholders (by default '\'). However, as of Spring Framework
6.2.6, there was no way to either escape the escape character or disable
escape character support.
For example, given a `username` property configured with the value of
`Jane.Smith` and a `DOMAIN\${username}` configuration string, property
placeholder replacement used to result in `DOMAIN\Jane.Smith` prior to
6.2 but now results in `DOMAIN${username}`. Similarly, an attempt to
escape the escape character via `DOMAIN\\${username}` results in
`DOMAIN\${username}`.
In theory, one should be able to disable use of an escape character
altogether, and that is currently possible by invoking
setEscapeCharacter(null) on AbstractPropertyResolver and
PlaceholderConfigurerSupport (the superclass of
PropertySourcesPlaceholderConfigurer).
However, in reality, there are two hurdles.
- As of 6.2.6, an invocation of setEscapeCharacter(null) on a
PropertySourcesPlaceholderConfigurer applied to its internal
top-level PropertySourcesPropertyResolver but not to any nested
PropertySourcesPropertyResolver, which means that the `null` escape
character could not be effectively applied.
- Users may not have an easy way to explicitly set the escape character
to `null` for a PropertyResolver or
PropertySourcesPlaceholderConfigurer. For example, Spring Boot
auto-configures a PropertySourcesPlaceholderConfigurer with the
default escape character enabled.
This first issue above has recently been addressed by gh-34861.
This commit therefore addresses the second issue as follows.
- To allow developers to easily revert to the pre-6.2 behavior without
changes to code or configuration strings, this commit introduces a
`spring.placeholder.escapeCharacter.default` property for use with
SpringProperties which globally sets the default escape character that
is automatically configured in AbstractPropertyResolver and
PlaceholderConfigurerSupport.
- Setting the property to an empty string sets the default escape
character to `null`, effectively disabling the default support for
escape characters.
spring.placeholder.escapeCharacter.default =
- Setting the property to any other character sets the default escape
character to that specific character.
spring.placeholder.escapeCharacter.default = ~
- Setting the property to a string containing more than one character
results in an exception.
- Developers are still able to configure an explicit escape character
in AbstractPropertyResolver and PlaceholderConfigurerSupport if they
choose to do so.
- Third-party components that wish to rely on the same feature can
invoke AbstractPropertyResolver.getDefaultEscapeCharacter() to obtain
the globally configured default escape character.
See gh-9628
See gh-34315
See gh-34861
Closes gh-34865
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to runDetails
Build and Deploy Snapshot / Verify (push) Blocked by required conditionsDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:ubuntu-latest name:Linux]) (push) Waiting to runDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:21], map[id:ubuntu-latest name:Linux]) (push) Waiting to runDetails
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:23], map[id:ubuntu-latest name:Linux]) (push) Waiting to runDetails
Deploy Docs / Dispatch docs deployment (push) Waiting to runDetails
This commit introduces a new constructor for CompositePropertySource
that accepts a `String name` and an Iterable<PropertySource<?>>, which
allows a CompositePropertySource to be constructed from existing
property sources, such as an instance of MutablePropertySources.
Closes gh-34862