@@ -665,6 +665,61 @@ This registers hints for constructors, fields, properties, and record components
665
665
Hints are also registered for types transitively used on properties and record components.
666
666
In other words, if `Order` exposes others types, hints are registered for those as well.
667
667
668
+ [[aot.hints.convention-based-conversion]]
669
+ === Runtime Hints for Convention-based Conversion
670
+
671
+ Although the core container provides built-in support for automatic conversion of many
672
+ common types (see xref:core/validation/convert.adoc[Spring Type Conversion]), some
673
+ conversions are supported via a convention-based algorithm that relies on reflection.
674
+
675
+ Specifically, if there is no explicit `Converter` registered with the `ConversionService`
676
+ for a particular source → target type pair, the internal `ObjectToObjectConverter`
677
+ will attempt to use conventions to convert a source object to a target type by delegating
678
+ to a method on the source object or to a static factory method or constructor on the
679
+ target type. Since this convention-based algorithm can be applied to arbitrary types at
680
+ runtime, the core container is not able to infer the runtime hints necessary to support
681
+ such reflection.
682
+
683
+ If you encounter convention-based conversion issues within a native image resulting from
684
+ lacking runtime hints, you can register the necessary hints programmatically. For
685
+ example, if your application requires a conversion from `java.time.Instant` to
686
+ `java.sql.Timestamp` and relies on `ObjectToObjectConverter` to invoke
687
+ `java.sql.Timestamp.from(Instant)` using reflection, you could implement a custom
688
+ `RuntimeHintsRegitrar` to support this use case within a native image, as demonstrated in
689
+ the following example.
690
+
691
+ [tabs]
692
+ ======
693
+ Java::
694
+ +
695
+ [source,java,indent=0,subs="verbatim,quotes"]
696
+ ----
697
+ public class TimestampConversionRuntimeHints implements RuntimeHintsRegistrar {
698
+
699
+ public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
700
+ ReflectionHints reflectionHints = hints.reflection();
701
+
702
+ reflectionHints.registerTypeIfPresent(classLoader, "java.sql.Timestamp", hint -> hint
703
+ .withMethod("from", List.of(TypeReference.of(Instant.class)), ExecutableMode.INVOKE)
704
+ .onReachableType(TypeReference.of("java.sql.Timestamp")));
705
+ }
706
+ }
707
+ ----
708
+ ======
709
+
710
+ `TimestampConversionRuntimeHints` can then be registered declaratively via
711
+ <<aot.hints.import-runtime-hints>> or statically via a `META-INF/spring/aot.factories`
712
+ configuration file.
713
+
714
+ [NOTE]
715
+ ====
716
+ The above `TimestampConversionRuntimeHints` class is a simplified version of the
717
+ `ObjectToObjectConverterRuntimeHints` class that is included in the framework and
718
+ registered by default.
719
+
720
+ Thus, this specific `Instant`-to-`Timestamp` use case is already handled by the framework.
721
+ ====
722
+
668
723
[[aot.hints.testing]]
669
724
=== Testing Runtime Hints
670
725
0 commit comments