Document how to register runtime hints for convention-based conversion
Backport Bot / build (push) Waiting to run Details
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to run Details
Build and Deploy Snapshot / Verify (push) Blocked by required conditions Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:ubuntu-latest name:Linux]) (push) Waiting to run Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:21], map[id:ubuntu-latest name:Linux]) (push) Waiting to run Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:23], map[id:ubuntu-latest name:Linux]) (push) Waiting to run Details
Deploy Docs / Dispatch docs deployment (push) Waiting to run Details

Closes gh-35178
This commit is contained in:
Sam Brannen 2025-07-10 11:36:01 +02:00
parent e3445b17a7
commit 983fdebdbb
1 changed files with 55 additions and 0 deletions

View File

@ -665,6 +665,61 @@ This registers hints for constructors, fields, properties, and record components
Hints are also registered for types transitively used on properties and record components.
In other words, if `Order` exposes others types, hints are registered for those as well.
[[aot.hints.convention-based-conversion]]
=== Runtime Hints for Convention-based Conversion
Although the core container provides built-in support for automatic conversion of many
common types (see xref:core/validation/convert.adoc[Spring Type Conversion]), some
conversions are supported via a convention-based algorithm that relies on reflection.
Specifically, if there is no explicit `Converter` registered with the `ConversionService`
for a particular source → target type pair, the internal `ObjectToObjectConverter`
will attempt to use conventions to convert a source object to a target type by delegating
to a method on the source object or to a static factory method or constructor on the
target type. Since this convention-based algorithm can be applied to arbitrary types at
runtime, the core container is not able to infer the runtime hints necessary to support
such reflection.
If you encounter convention-based conversion issues within a native image resulting from
lacking runtime hints, you can register the necessary hints programmatically. For
example, if your application requires a conversion from `java.time.Instant` to
`java.sql.Timestamp` and relies on `ObjectToObjectConverter` to invoke
`java.sql.Timestamp.from(Instant)` using reflection, you could implement a custom
`RuntimeHintsRegitrar` to support this use case within a native image, as demonstrated in
the following example.
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
public class TimestampConversionRuntimeHints implements RuntimeHintsRegistrar {
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
ReflectionHints reflectionHints = hints.reflection();
reflectionHints.registerTypeIfPresent(classLoader, "java.sql.Timestamp", hint -> hint
.withMethod("from", List.of(TypeReference.of(Instant.class)), ExecutableMode.INVOKE)
.onReachableType(TypeReference.of("java.sql.Timestamp")));
}
}
----
======
`TimestampConversionRuntimeHints` can then be registered declaratively via
<<aot.hints.import-runtime-hints>> or statically via a `META-INF/spring/aot.factories`
configuration file.
[NOTE]
====
The above `TimestampConversionRuntimeHints` class is a simplified version of the
`ObjectToObjectConverterRuntimeHints` class that is included in the framework and
registered by default.
Thus, this specific `Instant`-to-`Timestamp` use case is already handled by the framework.
====
[[aot.hints.testing]]
=== Testing Runtime Hints