Hi, I tried to build a native image from a Spring Boot 3.0.0 project (Webflux based on Netty, Mongo reactive) No problem succeeded on build time. I execute the gradle bootBuildImage command successfully.
Here my Gradle configuration :
springBoot {
mainClass.set("co.skaly.notifications.Notification")
}
bootBuildImage {
builder = "paketobuildpacks/builder:tiny"
environment = [
"BP_NATIVE_IMAGE" : "true",
"BP_NATIVE_IMAGE_BUILD_ARGUMENTS" : "--add-opens=java.base/java.time=ALL-UNNAMED -Djdk.tls.client.protocols=TLSv1.2 --verbose --enable-https -H:+ReportExceptionStackTraces --initialize-at-build-time=ch.qos.logback,slf4j-simple,org.slf4j.MDC --no-fallback"
]
}
sourceCompatibility = '1.17'
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
But when I do a docker run with the generated image, I have the following output :
:: Spring Boot :: (v3.0.0)
23:04:05.538 [main] DEBUG org.springframework.context.aot.AotApplicationContextInitializer - Initializing ApplicationContext with AOT
23:04:05.538 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
java.lang.IllegalArgumentException: Could not find class [co.skaly.notifications.Notification__ApplicationContextInitializer]
Can you help me to debug this please ?
Thanks for your help !
Comment From: philwebb
It looks like AOT processing hasn't run for your build. Have you included the native build tools plugin? You should have a plugin block that looks something like this:
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.0'
id 'io.spring.dependency-management' version '1.1.0'
id 'org.graalvm.buildtools.native' version '0.9.18'
}
Comment From: guillaume-1
Thank you @philwebb for your answer. It's true, I've forgot the native build tool plugin so, AOT processing have not been executed. Now, I have a new error on the AOT process step :
> Task :processAot
__ _ _ _ _ __ _ _ _
/ _\ | ____ _| |_ _ _ __ ___ | |_(_)/ _(_) ___ __ _| |_(_) ___ _ __ ___
\ \| |/ / _` | | | | | | '_ \ / _ \| __| | |_| |/ __/ _` | __| |/ _ \| '_ \/ __|
_\ \ < (_| | | |_| | | | | | (_) | |_| | _| | (_| (_| | |_| | (_) | | | \__ \
\__/_|\_\__,_|_|\__, | |_| |_|\___/ \__|_|_| |_|\___\__,_|\__|_|\___/|_| |_|___/
|___/
2022-12-04T11:41:48.834+01:00 INFO 45852 --- [ main] c.skaly.notifications.SkalyNotification : Starting SkalyNotification using Java 17.0.5 with PID 45852 (/Users/guillaumemartial/projects/skaly/skaly-notifications/build/classes/java/main started by guillaumemartial in /Users/guillaumemartial/projects/skaly/skaly-notifications)
2022-12-04T11:41:48.837+01:00 INFO 45852 --- [ main] c.skaly.notifications.SkalyNotification : The following 1 profile is active: "dev"
2022-12-04T11:41:49.305+01:00 INFO 45852 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Reactive MongoDB repositories in DEFAULT mode.
2022-12-04T11:41:49.405+01:00 INFO 45852 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 96 ms. Found 6 Reactive MongoDB repository interfaces.
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.startsWith(String)" because the return value of "java.lang.Class.getCanonicalName()" is null
at org.springframework.aot.hint.BindingReflectionHintsRegistrar.shouldSkipMembers(BindingReflectionHintsRegistrar.java:74)
at org.springframework.aot.hint.BindingReflectionHintsRegistrar.lambda$registerReflectionHints$0(BindingReflectionHintsRegistrar.java:87)
at org.springframework.aot.hint.ReflectionHints.registerType(ReflectionHints.java:86)
at org.springframework.aot.hint.ReflectionHints.registerType(ReflectionHints.java:109)
at org.springframework.aot.hint.BindingReflectionHintsRegistrar.registerReflectionHints(BindingReflectionHintsRegistrar.java:86)
at org.springframework.aot.hint.BindingReflectionHintsRegistrar.registerReflectionHints(BindingReflectionHintsRegistrar.java:65)
at org.springframework.data.util.TypeContributor.contribute(TypeContributor.java:70)
at org.springframework.data.repository.config.RepositoryRegistrationAotProcessor.contributeType(RepositoryRegistrationAotProcessor.java:171)
at org.springframework.data.repository.config.RepositoryRegistrationAotProcessor.lambda$contribute$1(RepositoryRegistrationAotProcessor.java:85)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at org.springframework.data.repository.config.RepositoryRegistrationAotProcessor.contribute(RepositoryRegistrationAotProcessor.java:85)
at org.springframework.data.mongodb.repository.aot.AotMongoRepositoryPostProcessor.contribute(AotMongoRepositoryPostProcessor.java:35)
at org.springframework.data.repository.config.RepositoryRegistrationAotContribution.lambda$applyTo$0(RepositoryRegistrationAotContribution.java:253)
at java.base/java.util.Optional.ifPresent(Optional.java:178)
at org.springframework.data.repository.config.RepositoryRegistrationAotContribution.applyTo(RepositoryRegistrationAotContribution.java:253)
at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.lambda$generateBeanDefinitionMethod$2(BeanDefinitionMethodGenerator.java:179)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.generateBeanDefinitionMethod(BeanDefinitionMethodGenerator.java:178)
at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.generateBeanDefinitionMethod(BeanDefinitionMethodGenerator.java:102)
at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.lambda$generateRegisterBeanDefinitionsMethod$2(BeanRegistrationsAotContribution.java:85)
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.generateRegisterBeanDefinitionsMethod(BeanRegistrationsAotContribution.java:83)
at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.lambda$applyTo$1(BeanRegistrationsAotContribution.java:67)
at org.springframework.aot.generate.GeneratedMethod.<init>(GeneratedMethod.java:54)
at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:112)
at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:89)
at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.applyTo(BeanRegistrationsAotContribution.java:66)
at org.springframework.context.aot.BeanFactoryInitializationAotContributions.applyTo(BeanFactoryInitializationAotContributions.java:78)
at org.springframework.context.aot.ApplicationContextAotGenerator.lambda$processAheadOfTime$0(ApplicationContextAotGenerator.java:58)
at org.springframework.context.aot.ApplicationContextAotGenerator.withCglibClassHandler(ApplicationContextAotGenerator.java:67)
at org.springframework.context.aot.ApplicationContextAotGenerator.processAheadOfTime(ApplicationContextAotGenerator.java:53)
at org.springframework.context.aot.ContextAotProcessor.performAotProcessing(ContextAotProcessor.java:106)
at org.springframework.context.aot.ContextAotProcessor.doProcess(ContextAotProcessor.java:84)
at org.springframework.context.aot.ContextAotProcessor.doProcess(ContextAotProcessor.java:49)
at org.springframework.context.aot.AbstractAotProcessor.process(AbstractAotProcessor.java:82)
at org.springframework.boot.SpringApplicationAotProcessor.main(SpringApplicationAotProcessor.java:76)
> Task :processAot FAILED
I suppose the problem is about Mongo repositories hints, but I did not find any documentation on this error.
Comment From: philwebb
@guillaume-1 we do have a MongoDB smoke test so we expect things to work. It looks like the problem is coming from org.springframework.data.util.TypeContributor which is part of Spring Data. Could you please raise an issue at https://github.com/spring-projects/spring-data-mongodb/issues and provide a sample application so that that team can take a look.