Trying to make classes generated by openapi-generator Spring Native capable so that they work in a native image.
The idea is to annotate all generated classes with @Reflective
so that they are automatically generated in reflect-config.json
. However, I can't seem to get through the @Reflective
feature sufficiently and it doesn't work.
I've always done quite well with reflect-config.json
in /resources/META-INF/native-image/
, so my first idea was to get all the POJOs in there.
So I tried the following:
OpenApi Maven Generator configOption for the java generator:
<configOptions>
<additionalModelTypeAnnotations>@org.springframework.aot.hint.annotation.Reflective</additionalModelTypeAnnotations>
</configOptions>
This creates valid annotations on all POJOs. Subsequently:
mvn clean compile spring-boot:process-aot package
and a few smoke tests with :
"C:/Program Files/GraalVM/graalvm-jdk-21/bin/java" \
-Dspring.aot.enabled=true \
-agentlib:native-image-agent=config-output-dir=C:/repos/my-repo/portal-applications/services/my-service/target/native \
-jar target/app.jar
After smoke testing my application, this generates the reflect-config.json
into the folder specified. However none of the @Reflective
annotated types are present.
Perhaps @Reflective
annotations are picked up by mvn clean package -Pnative spring-boot:build-image
, making explicit mentioning in reflect-config.json
obsolete?
Okay I couldn't get it to work using @Reflective
, but what works is this strategy.
RuntimeHintsRegistrar
.org.reflections
to find all POJOs annotated:val reflections = Reflections("define.your.package", Scanners.TypesAnnotated)
val reflectiveClasses = reflections.getTypesAnnotatedWith(Reflective::class.java)
reflectiveClasses.forEach {
hints.reflection().registerType(it, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS)
}
aot.factories
under META-INF/spring
and put this content:org.springframework.aot.hint.RuntimeHintsRegistrar=\
define.your.package.YourClassRuntimeHints
Now when running mvn clean compile spring-boot:process-aot package
your POJOs are present in reflect-config.json
.
For reference:
class YourClassRuntimeHints : RuntimeHintsRegistrar {
override fun registerHints(hints: RuntimeHints, classLoader: ClassLoader?) {
val reflections = Reflections("define.your.package", Scanners.TypesAnnotated)
val reflectiveClasses = reflections.getTypesAnnotatedWith(Reflective::class.java)
reflectiveClasses.forEach {
hints.reflection().registerType(
it,
INVOKE_DECLARED_CONSTRUCTORS,
INTROSPECT_PUBLIC_CONSTRUCTORS,
INVOKE_PUBLIC_METHODS,
INTROSPECT_PUBLIC_METHODS
)
}
}
}
It is not necessary and probably cumbersome to use @Reflective
for that, you can also create your own annotation.