Open akefirad opened 2 years ago
Looks like we deduce the wrong class name for the application context initializer: com.example.demo.DemoApplication$Companion__ApplicationContextInitializer
because of the Kotlin Companion Object. The generated initializer is called DemoApplication__ApplicationContextInitializer
.
Workaround until fixed:
@SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
which is the default code the initializer generates.
You're right. The workaround doesn't work for me since I have to set the main class in bootRun
task in build.gradle
, unless there's a way to set the main class in the task when the main method is a free one.
There is. The default class name for free functions is the filename + "Kt", so in your case DemoApplicationKt
:
springBoot {
mainClass.set("com.example.demo.DemoApplicationKt")
}
You can rename the class by using
@file:JvmName("SomeOtherClassName")
springBoot {
mainClass.set("com.example.demo.SomeOtherClassName")
}
See here: https://kotlinlang.org/docs/java-to-kotlin-interop.html#package-level-functions
Got it. Thanks for the link. 🙏
The workaround doesn't work for me since I have to set the main class in
bootRun
task
This shouldn't be necessary. bootRun
should be automatically configured to use the right main class when using either a companion object or a package-level function.
I wonder if we should set the main class in the Kotlin extension. Things are a little odd at the moment, even without AOT, as the companion object's class is used for logging:
2022-11-03T19:46:16.594Z INFO 33846 --- [ main] e.k.KotlinMainClassApplication$Companion : Starting KotlinMainClassApplication.Companion using Java 17.0.5 with PID 33846 (/Users/awilkinson/dev/temp/kotlin-main-class/build/classes/kotlin/main started by awilkinson in /Users/awilkinson/dev/temp/kotlin-main-class)
If we set the main class, it looks like this instead:
2022-11-03T19:48:04.743Z INFO 35059 --- [ main] c.e.k.KotlinMainClassApplication : Starting KotlinMainClassApplication using Java 17.0.5 with PID 35059 (/Users/awilkinson/dev/temp/kotlin-main-class/build/classes/kotlin/main started by awilkinson in /Users/awilkinson/dev/temp/kotlin-main-class)
That's after making these changes to the extensions:
diff --git a/spring-boot-project/spring-boot/src/main/kotlin/org/springframework/boot/SpringApplicationExtensions.kt b/spring-boot-project/spring-boot/src/main/kotlin/org/springframework/boot/SpringApplicationExtensions.kt
index 8a1269d06b..3ae3cdbc6c 100644
--- a/spring-boot-project/spring-boot/src/main/kotlin/org/springframework/boot/SpringApplicationExtensions.kt
+++ b/spring-boot-project/spring-boot/src/main/kotlin/org/springframework/boot/SpringApplicationExtensions.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2017 the original author or authors.
+ * Copyright 2012-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,8 +26,12 @@ import org.springframework.context.ConfigurableApplicationContext
* @author Sebastien Deleuze
* @since 2.0.0
*/
-inline fun <reified T : Any> runApplication(vararg args: String): ConfigurableApplicationContext =
- SpringApplication.run(T::class.java, *args)
+inline fun <reified T : Any> runApplication(vararg args: String): ConfigurableApplicationContext {
+ val application = SpringApplication(T::class.java)
+ application.setMainApplicationClass(T::class.java)
+ return application.run(*args)
+}
+
/**
* Top level function acting as a Kotlin shortcut allowing to write
@@ -38,5 +42,8 @@ inline fun <reified T : Any> runApplication(vararg args: String): ConfigurableAp
* @author Sebastien Deleuze
* @since 2.0.0
*/
-inline fun <reified T : Any> runApplication(vararg args: String, init: SpringApplication.() -> Unit): ConfigurableApplicationContext =
- SpringApplication(T::class.java).apply(init).run(*args)
+inline fun <reified T : Any> runApplication(vararg args: String, init: SpringApplication.() -> Unit): ConfigurableApplicationContext {
+ val application = SpringApplication(T::class.java).apply(init)
+ application.setMainApplicationClass(T::class.java)
+ return application.run(*args)
+}
WDYT, @sdeleuze, does this make sense?
Looking more closely, I think this is a bug in the code where we deduce the main application class. It can effect Java too if you write some (convoluted) code that has a similar structure to the code the Kotlin's compiler generates:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
Companion.main(args);
}
static class Companion {
static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
}
SpringApplicaton
will deduce the main class to be DemoApplication$Companion
but the MainClassFinder
that's used by our Maven and Gradle plugins will correctly identify that it's DemoApplication
.
At the moment we identify the main class by walking the stack and finding the first frame for a method named main
. In the example above, we really need to look for the last frame. However, by doing that we risk picking up another main method that's then called the application's main method to start it. @SpringBootTest
s configured to use the main method would be affected by this were it not for the fact that they explicitly set the main application class.
We can't narrow things down by looking for a particular type of method as it doesn't work with Graal. For the reasons above, I'm also not sure that we can safely look for the last method named main
rather than the first. I'm back to thinking that a Kotlin-specific fix may be our best option.
Here's a change that corrects the main class only when a companion object is used:
diff --git a/spring-boot-project/spring-boot/src/main/kotlin/org/springframework/boot/SpringApplicationExtensions.kt b/spring-boot-project/spring-boot/src/main/kotlin/org/springframework/boot/SpringApplicationExtensions.kt
index 8a1269d06b..2405a00f2e 100644
--- a/spring-boot-project/spring-boot/src/main/kotlin/org/springframework/boot/SpringApplicationExtensions.kt
+++ b/spring-boot-project/spring-boot/src/main/kotlin/org/springframework/boot/SpringApplicationExtensions.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2017 the original author or authors.
+ * Copyright 2012-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,8 +26,15 @@ import org.springframework.context.ConfigurableApplicationContext
* @author Sebastien Deleuze
* @since 2.0.0
*/
-inline fun <reified T : Any> runApplication(vararg args: String): ConfigurableApplicationContext =
- SpringApplication.run(T::class.java, *args)
+inline fun <reified T : Any> runApplication(vararg args: String): ConfigurableApplicationContext {
+ val application = SpringApplication(T::class.java)
+ val possibleCompanionClass = object{}.javaClass.enclosingClass
+ if (possibleCompanionClass.enclosingClass != null && possibleCompanionClass.kotlin.isCompanion) {
+ application.setMainApplicationClass(possibleCompanionClass.enclosingClass)
+ }
+ return application.run(*args)
+}
+
/**
* Top level function acting as a Kotlin shortcut allowing to write
@@ -38,5 +45,11 @@ inline fun <reified T : Any> runApplication(vararg args: String): ConfigurableAp
* @author Sebastien Deleuze
* @since 2.0.0
*/
-inline fun <reified T : Any> runApplication(vararg args: String, init: SpringApplication.() -> Unit): ConfigurableApplicationContext =
- SpringApplication(T::class.java).apply(init).run(*args)
+inline fun <reified T : Any> runApplication(vararg args: String, init: SpringApplication.() -> Unit): ConfigurableApplicationContext {
+ val application = SpringApplication(T::class.java).apply(init)
+ val possibleCompanionClass = object{}.javaClass.enclosingClass
+ if (possibleCompanionClass.enclosingClass != null && possibleCompanionClass.kotlin.isCompanion) {
+ application.setMainApplicationClass(possibleCompanionClass.enclosingClass)
+ }
+ return application.run(*args)
+}
It's pretty gross. It's using an anonymous inner class (object{}
) and then getting the enclosing class to identify the class into which the function has been inlined. We can then check if it's a companion class and set the main application class if it is.
I had the same problem in Java and found a workaround. Maybe that'll help you somehow.
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
Companion.main(args);
}
static class Companion {
static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(DemoApplication.class);
springApplication.setMainApplicationClass(DemoApplication.class);
springApplication.run(args);
}
}
}
Have the same problem. No luck with workarounds that were mentioned here.
java.lang.IllegalArgumentException: Could not find class [xyz.app.ApplicationKt__ApplicationContextInitializer]
at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:333)
at org.springframework.context.aot.AotApplicationContextInitializer.instantiateInitializer(AotApplicationContextInitializer.java:80)
at org.springframework.context.aot.AotApplicationContextInitializer.initialize(AotApplicationContextInitializer.java:71)
at org.springframework.context.aot.AotApplicationContextInitializer.lambda$forInitializerClasses$0(AotApplicationContextInitializer.java:61)
at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:605)
at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:385)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:309)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1304)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1293)
at xyz.app.ApplicationKt.main(Application.kt:13)
Caused by: java.lang.ClassNotFoundException: xyz.app.ApplicationKt__ApplicationContextInitializer
at java.base@17.0.6/java.lang.Class.forName(DynamicHub.java:1132)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:283)
at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:323)
build.gradle.kts
plugins {
id("org.springframework.boot") version "3.0.5"
id("io.spring.dependency-management") version "1.0.13.RELEASE"
kotlin("jvm") version "1.8.10"
kotlin("plugin.spring") version "1.8.10"
kotlin("kapt") version "1.8.10"
}
...
tasks.bootBuildImage {
builder.set("paketobuildpacks/builder:tiny")
environment.set(
mapOf(
"BP_NATIVE_IMAGE" to "true",
"BP_NATIVE_IMAGE_BUILD_ARGUMENTS" to
"""
--verbose
--no-fallback
--initialize-at-build-time=org.slf4j.LoggerFactory,ch.qos.logback
--trace-class-initialization=ch.qos.logback.classic.Logger
--initialize-at-run-time=io.netty
""".trimIndent()
)
)
}
We can confirm @takanoro's problem, even tried the approach to rename the kotlin main class accordingly
DemoMain.kt
@file:JvmName("DemoMain")
package at.demo
import org.springframework.boot.runApplication
fun main(args: Array<String>) {
runApplication<DemoApp>(*args)
}
DemoApp.kt
@EnableScheduling
@SpringBootApplication(
...
)
@ConfigurationPropertiesScan
...
class DemoApp
build.gradle:
plugins {
id 'org.springframework.boot' version '3.1.0'
id 'io.spring.dependency-management'
id 'org.asciidoctor.jvm.convert' version "2.4.0"
id 'org.graalvm.buildtools.native' version '0.9.22'
}
....
springBoot {
mainClass = 'at.demo.DemoMain'
}
....
bootBuildImage {
enabled = true
builder = "paketobuildpacks/builder:tiny"
imageName = "ghcr.io/demo/demo:native"
environment = [
"BP_NATIVE_IMAGE" : "true",
"BP_NATIVE_IMAGE_BUILD_ARGUMENTS": "" +
"--verbose " +
"--no-fallback " +
"--enable-https " +
"-Djdk.tls.client.protocols=TLSv1.2 " +
"--add-opens=java.base/java.time=ALL-UNNAMED " +
"--add-opens=java.base/java.nio=ALL-UNNAMED " +
"--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED " +
"--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED " +
"--trace-class-initialization=ch.qos.logback.classic.Logger " +
'--trace-object-instantiation=ch.qos.logback.core.AsyncAppenderBase$Worker ' +
"--initialize-at-build-time=org.slf4j.LoggerFactory,ch.qos.logback " +
"--initialize-at-run-time=io.netty " +
"--report-unsupported-elements-at-runtime "
]
}
I tried both with 3.0 and 3.1 spring versions. Which finally results in a built image which cannot start its main class:
2023-06-09T12:19:17.190254236Z . ____ _ __ _ _
2023-06-09T12:19:17.190256831Z /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
2023-06-09T12:19:17.190258664Z ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
2023-06-09T12:19:17.190260327Z \\/ ___)| |_)| | | | | || (_| | ) ) ) )
2023-06-09T12:19:17.190261900Z ' |____| .__|_| |_|_| |_\__, | / / / /
2023-06-09T12:19:17.190263794Z =========|_|==============|___/=/_/_/_/
2023-06-09T12:19:17.190265387Z :: Spring Boot :: (v3.1.0)
2023-06-09T12:19:17.190267571Z
2023-06-09T12:19:17.191701237Z 12:19:17.190 [main] ERROR org.springframework.boot.SpringApplication -- Application run failed
2023-06-09T12:19:17.191726434Z java.lang.IllegalArgumentException: Could not find class [at.demo.DemoMain__ApplicationContextInitializer]
2023-06-09T12:19:17.191730531Z at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:334)
2023-06-09T12:19:17.191734148Z at org.springframework.context.aot.AotApplicationContextInitializer.instantiateInitializer(AotApplicationContextInitializer.java:80)
2023-06-09T12:19:17.191737675Z at org.springframework.context.aot.AotApplicationContextInitializer.initialize(AotApplicationContextInitializer.java:71)
2023-06-09T12:19:17.191741051Z at org.springframework.context.aot.AotApplicationContextInitializer.lambda$forInitializerClasses$0(AotApplicationContextInitializer.java:61)
2023-06-09T12:19:17.191744327Z at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:606)
2023-06-09T12:19:17.191747433Z at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:386)
2023-06-09T12:19:17.191764495Z at org.springframework.boot.SpringApplication.run(SpringApplication.java:310)
2023-06-09T12:19:17.191770025Z at org.springframework.boot.SpringApplication.run(SpringApplication.java:1305)
2023-06-09T12:19:17.191775255Z at org.springframework.boot.SpringApplication.run(SpringApplication.java:1294)
2023-06-09T12:19:17.191779933Z at at.demo.DemoMain.main(DemoMain.kt:11)
2023-06-09T12:19:17.191784502Z Caused by: java.lang.ClassNotFoundException: at.demo.DemoMain__ApplicationContextInitializer
2023-06-09T12:19:17.191788910Z at java.base@17.0.7/java.lang.Class.forName(DynamicHub.java:1132)
2023-06-09T12:19:17.191793268Z at org.springframework.util.ClassUtils.forName(ClassUtils.java:284)
2023-06-09T12:19:17.191797226Z at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:324)
2023-06-09T12:19:17.191800812Z ... 9 common frames omitted
so is there any temporary solution to this problem?
@SpringBootApplication
class Sb32918Application
fun main(args: Array<String>) {
runApplication<Sb32918Application>(*args)
}
works for me, try for yourself: sb-32918.zip
Could you please attach a sample for a non-working app?
@mhalbritter my mistake, it missed mainClass because of I configured the native-maven-plugin incorrectly, thanks for your help.
This happened when upgrading to spring-boot 3.2.0-M1
.
I think I'm facing the same issue with Spring 3.1.2.
The application compiles but when I run it I get an error.
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.1.2)
02:12:34.177 [main] ERROR org.springframework.boot.SpringApplication -- Application run failed
java.lang.IllegalArgumentException: Could not find class [dev.mbo.linkshortener2.ApplicationKt__ApplicationContextInitializer]
at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:334)
at org.springframework.context.aot.AotApplicationContextInitializer.instantiateInitializer(AotApplicationContextInitializer.java:80)
at org.springframework.context.aot.AotApplicationContextInitializer.initialize(AotApplicationContextInitializer.java:71)
at org.springframework.context.aot.AotApplicationContextInitializer.lambda$forInitializerClasses$0(AotApplicationContextInitializer.java:61)
at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:607)
at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:387)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
at dev.mbo.linkshortener2.ApplicationKt.main(Application.kt:29)
Caused by: java.lang.ClassNotFoundException: dev.mbo.linkshortener2.ApplicationKt__ApplicationContextInitializer
at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:123)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:87)
at java.base@17.0.8/java.lang.Class.forName(DynamicHub.java:1322)
at java.base@17.0.8/java.lang.Class.forName(DynamicHub.java:1311)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:284)
at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:324)
... 9 common frames omitted
My build.gradle.kts:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
// https://plugins.gradle.org/plugin/org.springframework.boot
id("org.springframework.boot") version "3.1.2"
// https://plugins.gradle.org/plugin/io.spring.dependency-management
id("io.spring.dependency-management") version "1.1.3"
// https://github.com/graalvm/native-build-tools
id("org.graalvm.buildtools.native") version "0.9.24"
// https://plugins.gradle.org/plugin/org.jetbrains.kotlin.jvm
kotlin("jvm") version "1.9.0"
// https://plugins.gradle.org/plugin/org.jetbrains.kotlin.plugin.spring
kotlin("plugin.spring") version "1.9.0"
}
group = "dev.mbo"
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-data-redis-reactive")
implementation("org.springframework.boot:spring-boot-starter-mail")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
// https://mvnrepository.com/artifact/io.netty/netty-resolver-dns-native-macos
implementation("io.netty:netty-resolver-dns-native-macos:4.1.96.Final:osx-aarch_64")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
developmentOnly("org.springframework.boot:spring-boot-devtools")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.boot:spring-boot-testcontainers")
testImplementation("io.projectreactor:reactor-test")
testImplementation("org.springframework.security:spring-security-test")
testImplementation("org.testcontainers:junit-jupiter")
}
tasks {
withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
jvmTarget = "17"
}
}
withType<Test> {
useJUnitPlatform()
}
withType<Copy> {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
bootJar {
archiveFileName = "${project.name}-all.jar"
exclude("application-sec*.yml")
}
withType<Wrapper> {
// https://gradle.org/releases/
gradleVersion = "8.2.1"
distributionType = Wrapper.DistributionType.ALL
}
graalvmNative {
binaries {
named("main") {
mainClass.set("dev.mbo.linkshortener2.ApplicationKt")
}
}
}
}
Without setting the main class like a few lines above the nativeCompile task fails.
My main looks like this:
package dev.mbo.linkshortener2
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class Application
fun main(args: Array<String>) {
runApplication<Application>(*args)
}
Starting the application from the bootJar works fine. Setting mainClass.set("dev.mbo.linkshortener2.Application") complained about not finding the main method.
Can you share the code with us so I can take a look?
Having the same issue on Spring Boot 3.1.0, Kotlin , Gradle.
I don't use nativeImage plugin, I use buildpacks. I get with bootBuildImage
a built docker image, which can't start with the same error:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.1.0)
15:49:31.620 [main] ERROR org.springframework.boot.SpringApplication -- Application run failed
java.lang.IllegalArgumentException: Could not find class [com.***.ManagementApplicationKt__ApplicationContextInitializer]
at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:334)
at org.springframework.context.aot.AotApplicationContextInitializer.instantiateInitializer(AotApplicationContextInitializer.java:80)
at org.springframework.context.aot.AotApplicationContextInitializer.initialize(AotApplicationContextInitializer.java:71)
at org.springframework.context.aot.AotApplicationContextInitializer.lambda$forInitializerClasses$0(AotApplicationContextInitializer.java:61)
at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:606)
at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:386)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:310)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1305)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1294)
at com.deliveryhero.vms.VendorManagementApplicationKt.main(VendorManagementApplication.kt:33)
Caused by: java.lang.ClassNotFoundException: com.***.ManagementApplicationKt__ApplicationContextInitializer
at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:123)
at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:87)
at java.base@17.0.7/java.lang.Class.forName(DynamicHub.java:1324)
at java.base@17.0.7/java.lang.Class.forName(DynamicHub.java:1313)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:284)
at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:324)
... 9 common frames omitted
my root class:
@SpringBootApplication
@EnableConfigurationProperties(
...
)
@EnableAsync
class ***ManagementApplication
fun main(args: Array<String>) {
runApplication<***ManagementApplication>(*args)
}
This is my gradle.build part related to the graalvm and native image
plugins {
kotlin("jvm")
kotlin("plugin.spring")
id("io.spring.dependency-management")
id("org.springframework.boot")
id("org.graalvm.buildtools.native") version "0.9.23"
id("com.avast.gradle.docker-compose")
id("com.adarshr.test-logger")
jacoco
}
tasks.named<BootBuildImage>("bootBuildImage") {
environment.set(
environment.get() + mapOf(
"BP_NATIVE_IMAGE" to "true",
"BP_NATIVE_IMAGE_BUILD_ARGUMENTS" to "--initialize-at-build-time=org.slf4j.impl.StaticLoggerBinder,org.slf4j.LoggerFactory,ch.qos.logback.classic.Logger,ch.qos.logback.core.spi.AppenderAttachableImpl,ch.qos.logback.core.status.StatusBase,ch.qos.logback.classic.Level,ch.qos.logback.core.status.InfoStatus,ch.qos.logback.classic.PatternLayout,ch.qos.logback.core.CoreConstants,ch.qos.logback.core.util.StatusPrinter,ch.qos.logback.core.util.Loader"
)
)
}
@mhalbritter uploaded to https://github.com/mbogner/link-shortener2
highly work in progress but it runs as jar on my mac M1. didn't work on the dockerisation scripts yet that are included
I compared my build with a hello-world project generated from start.spring.io. They bootBuildImage
task generates this classes for the hello world project like
but it's not generated for my current project.
PS: I also use a multimodule gradle project and build like:
./gradlew -Pversion=v1 :management-service:bootBuildImage --runImage=paketobuildpacks/run:full-cnb
PPS: Somehow after
./gradlew -Pversion=v1 :management-service:bootBuildImage --runImage=paketobuildpacks/run:full-cnb
the folder build/generated
with all AOT classes is missing for me
I tried various workarounds, none worked.
@file:JvmName("MyApp")
package com.example.my
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
@SpringBootApplication
@EnableWebFluxSecurity
class MyApplication
fun main(args: Array<String>) {
runApplication<MyApplication>(*args)
}
application {
mainClass.set("com.example.my.MyApp")
}
When running :nativeRun
:
Caused by: java.lang.ClassNotFoundException: com.example.my.MyApp__ApplicationContextInitializer
I tried with 3.1.2 and 3.1.0
EDIT: I gave another shot - I rewrote main in Java and it seems that the same error (ClassNotFoundException: com.example.my.MyApp__ApplicationContextInitializer
) occurs. FYI @wilkinsona
I made a project that reproduces this issue - it has two branches: one with Kotlin main and another with Java main. Both fail with the same error. https://github.com/kkocel/classnotfoundrepero
@kkocel I played around with your main
branch to understand why it happens and noticed that when I only downgrade to Kotlin 1.8.22 your example builds and run without the exception.
kotlin("jvm") version "1.8.22"
kotlin("plugin.spring") version "1.8.22"
docker run --rm -p 8080:8080 docker.io/library/classnotfoundrepero:0.0.1-SNAPSHOT
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.1.2)
2023-08-22T14:38:01.076Z INFO 1 --- [ main] c.e.c.ClassnotfoundreperoApplicationKt : Starting AOT-processed ClassnotfoundreperoApplicationKt using Java 17.0.7 with PID 1 (/workspace/com.example.classnotfoundrepero.ClassnotfoundreperoApplicationKt started by cnb in /workspace)
2023-08-22T14:38:01.076Z INFO 1 --- [ main] c.e.c.ClassnotfoundreperoApplicationKt : No active profile set, falling back to 1 default profile: "default"
2023-08-22T14:38:01.116Z INFO 1 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 1 endpoint(s) beneath base path '/actuator'
2023-08-22T14:38:01.136Z INFO 1 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port 8080
2023-08-22T14:38:01.137Z INFO 1 --- [ main] c.e.c.ClassnotfoundreperoApplicationKt : Started ClassnotfoundreperoApplicationKt in 0.074 seconds (process running for 0.079)
Thanks for analyzing, @rt-works!
@mhalbritter So is there a chance that this issue will get resolved soon?
In my case my problem was just solved by upgrading to id("org.graalvm.buildtools.native") version "0.9.24"
. After the the application could start but there are a lot of other errors to solve in runtime.
@rt-works do you have a minimal working example? do yo use kotlin 1.9 + native buildtools 0.9.24?
it works for me with kotlin 1.8.22 + native buildtools 0.9.24. I'll prepare the example
sorry for the confusion. I thought you managed to run this against Kotlin 1.9.0.
So for now we pin-pointed that Kotlin 1.9.0 is causing this issue.
Any update for Kotlin 1.9.*
?
Having a simple project, I have the same issue, I'm on:
# .kts
springBoot {
mainClass.set("com.iptiq.apptemplate.AppTemplateApplicationKt")
}
graalvmNative {
binaries {
named("main") {
mainClass = "foo.baz.apptemplate.AppTemplateApplicationKt"
buildArgs(
"-H:+ReportExceptionStackTraces",
"-H:EnableURLProtocols=http,https",
"--initialize-at-run-time=io.netty.handler.ssl.BouncyCastleAlpnSslUtils",
"--initialize-at-build-time=org.slf4j.impl.StaticLoggerBinder,org.slf4j.LoggerFactory,ch.qos.logback.core.spi.AppenderAttachableImpl,ch.qos.logback.core.status.StatusBase,ch.qos.logback.classic.Level,ch.qos.logback.core.status.InfoStatus,ch.qos.logback.classic.PatternLayout,ch.qos.logback.core.CoreConstants,ch.qos.logback.classic.Logger,ch.qos.logback.core.util.Loader,ch.qos.logback.core.util.StatusPrinter"
)
}
}
}
I do just nativeCompile
task and run the binary on M1
same stuff but ./gradlew bootBuildImage -i -s
- works, it starts in docker
I can confirm that this issue no longer occurs as of SB 3.2 + Kotlin 1.9.20.
Main:
package com.example.graalvmrepro
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class GraalvmreproApplication
fun main(args: Array<String>) {
runApplication<GraalvmreproApplication>(*args)
}
gradle script:
application {
mainClass.set("com.example.graalvmrepro.GraalvmreproApplicationKt")
}
@kkocel thanks, but, as far as I can tell, the issue as originally reported still occurs with Spring Boot 3.2 and Kotlin 1.9.20. In fact, it's got slightly worse as the error message is no longer as helpful as it was:
> Task :nativeRun FAILED
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.2.0)
2023-12-04T12:25:16.225Z ERROR 83509 --- [ main] o.s.boot.SpringApplication : Application run failed
java.lang.IllegalStateException: You are starting the application with AOT mode enabled but AOT processing hasn't happened. Please build your application with enabled AOT processing first, or remove the system property 'spring.aot.enabled' to run the application in regular mode
at org.springframework.util.Assert.state(Assert.java:76) ~[na:na]
at org.springframework.boot.SpringApplication.addAotGeneratedInitializerIfNecessary(SpringApplication.java:440) ~[gh-32918:3.2.0]
at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:396) ~[gh-32918:3.2.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) ~[gh-32918:3.2.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1342) ~[gh-32918:3.2.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1331) ~[gh-32918:3.2.0]
at com.example.gh32918.Gh32918Application$Companion.main(Gh32918Application.kt:15) ~[na:na]
at com.example.gh32918.Gh32918Application.main(Gh32918Application.kt) ~[gh-32918:na]
I think we should consider refining or reverting https://github.com/spring-projects/spring-boot/pull/38188, particularly while this issue is unresolved.
Bug Report for Spring Boot 3 Native (GraalVM 22.3) Having a simple Spring Boot application (generated on start.spring.io), changing the main class to:
And building the native image (via
./gradlew nativeCompile
) gives you an executable that fails to start with:Let me know if you need more information. Thanks.