Kotlin Gradle Could not find or load main class
Asked Answered
E

6

8

I tried to copy the Spring Boot Kotlin sample project https://github.com/JetBrains/kotlin-examples/tree/master/tutorials/spring-boot-restful. I Added some more dependencies and when I tried to build the executable jar and run it, I got the error:

Could not find or load main class...

Gradle build script:

buildscript {
    ext.kotlin_version = '1.1.3' // Required for Kotlin integration
    ext.spring_boot_version = '1.5.4.RELEASE'
    repositories {
        jcenter()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // Required for Kotlin integration
        classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version" // See https://kotlinlang.org/docs/reference/compiler-plugins.html#kotlin-spring-compiler-plugin
        classpath "org.springframework.boot:spring-boot-gradle-plugin:$spring_boot_version"
    }
}

/*plugins {
    id 'org.springframework.boot' version '2.0.0.RELEASE'
}*/

apply plugin: 'kotlin' // Required for Kotlin integration
apply plugin: "kotlin-spring" // See https://kotlinlang.org/docs/reference/compiler-plugins.html#kotlin-spring-compiler-plugin
apply plugin: 'org.springframework.boot'

jar {
    baseName = 'gs-rest-service'
    version = '0.1.0'
    from {
        (configurations.runtime).collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
    manifest {
        attributes 'Main-Class': 'org.jetbrains.kotlin.demo.Applicationkt'
    }


}

sourceSets {
    main.java.srcDirs += 'src/main/kotlin/'
    test.java.srcDirs += 'src/test/kotlin/'
}

repositories {
    jcenter()
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" // Required for Kotlin integration
    compile("org.springframework.boot:spring-boot-starter-web")

    compile group: 'org.apache.camel', name: 'camel-quartz2', version: '2.20.2'
    compile group: 'org.apache.camel', name: 'camel-http4', version: '2.20.2'
    compile group: 'org.apache.camel', name: 'camel-docker', version: '2.20.2'
    compile group: 'org.apache.camel', name: 'camel-aws', version: '2.20.2'

    testCompile('org.springframework.boot:spring-boot-starter-test')
}
Episodic answered 3/4, 2018 at 6:1 Comment(0)
G
7

Change Applicationkt to ApplicationKt will work, and BTW you may upgrade Kotlin version to 1.3.50.

By Applicationkt I mean the one in this line:

attributes 'Main-Class': 'org.jetbrains.kotlin.demo.Applicationkt'
Gossipy answered 3/4, 2018 at 6:22 Comment(0)
H
6

Kotlin compiles the Application file in two different files:

  • one file called Application.class with the Springboot things
  • another file called ApplicationKt.class with the main method

In this second file is where the main function is located at, so you have to use this name in the build.gradle file.

mainClassName = 'org.jetbrains.kotlin.demo.ApplicationKt'

Hofmannsthal answered 28/2, 2019 at 0:43 Comment(0)
Z
2

Update your build.gradle to

jar {
    manifest {
        attributes 'Main-Class': 'org.jetbrains.kotlin.demo.ApplicationKt'
    }
    from { 
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } 
    }
}

with an upper case K in ApplicationKt.

This is required because of the way Kotlin compiles to Java Bytecode. The fun main() function in Kotlin is not attached to any class, but Java always requires a class and does not support classless functions.

The Kotlin compiler has to create a Java class. Because you already defined a class Application it created one with the suffix Kt for the functions in your Kotlin file org/jetbrains/kotlin/demo/Application.kt. You have to set this class so that the JVM can find it.

BTW a Jar file is just a Zip file, you can unpack it and see for yourself if the ApplicationKt.class is there.

Ziguard answered 3/4, 2018 at 6:24 Comment(7)
I think the first two paragraphs are irrelatedGossipy
Update the answer to explain why Kotlin does require the additional KtZiguard
I changed the extensions to Kt and also upgraded the kotlin version to 1.2.31, but no luck. @Ziguard Can you try by yourself building a fat jar for the above project with additional dependencies.Episodic
I built a 'Hello World' example and it runs as expected. Please update your question with more information, especially the exact error message, the contents of your jar file (is there a class ApplicationKt), etc. Thank you.Ziguard
@Ziguard Did you run ./gradlew clean jar command ? And after that you run the standalone jar file ? Can you try with the above github repository link ?Episodic
Yes I did and a spring boot applications starts. My build.gradle is slightly different though, see updated answer. We will need more details from you (see my previous post) to help you. Thanks.Ziguard
Did you have any success or are there still open questions?Ziguard
P
1

For me the main function needed to be outside the class body

@SpringBootApplication
@Configuration
class Application
(private val locationRepository: LocationRepository,
) : CommandLineRunner {

    override fun run(vararg args: String?) {
        whatever()
    }
}

fun main(args: Array<String>) {
    runApplication<Application>(*args)
}
Photochemistry answered 5/2, 2022 at 18:42 Comment(0)
R
0

Indeed, Kotlin create file ApplicationKt.class in the jar if your main class file is named Application.kt. You have to add the following lines:

apply plugin: 'kotlin'
apply plugin: 'application'
mainClassName = 'org.jetbrains.kotlin.demo.ApplicationKt'

If you use the classic jar plugin, you can do as below (which is described in previous responses):

jar {
    manifest {
        attributes 'Main-Class': 'org.jetbrains.kotlin.demo.ApplicationKt'
    }
    from { 
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } 
    }
}

However, my preference is to use bootJar plugin which is much clear and which allow me to use layered jars for example:

bootJar {
    layered() // Not useful if you don't want to use layered jars
}
Racer answered 13/7, 2020 at 13:22 Comment(0)
C
0

One small (but easily overlooked) thing: Your Application.kt file has a class Application inside which the main function is present.

For example:

class Application {
    fun main(args: Array<String>): Unit {
        // your logic
    }
}

Instead, your main function should be out of the class:


fun main(args: Array<String>) {
    // your logic
}

And now in your build.gradle.kts file:


application {
    mainClass.set("<package>.ApplicationKt")
}

should work

Connivance answered 8/2 at 11:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.