dks551
dks551

Reputation: 1113

Kotlin Gradle Could not find or load main class

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')
}

Upvotes: 8

Views: 20963

Answers (6)

Kumar Shubham
Kumar Shubham

Reputation: 504

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

Upvotes: 0

midi
midi

Reputation: 4058

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)
}

Upvotes: 1

veben
veben

Reputation: 22292

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
}

Upvotes: 0

ice1000
ice1000

Reputation: 6569

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'

Upvotes: 7

Antonio Martin
Antonio Martin

Reputation: 531

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'

Upvotes: 6

phisch
phisch

Reputation: 4731

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.

Upvotes: 2

Related Questions