21

I try to build a jar with Intellij Idea with Kotlin Gradle project. Idea doesn't see my main class when I try to configure Artifact

here's my Gradle :

plugins {
    id 'java'
    id 'org.jetbrains.kotlin.jvm' version '1.3.60'
    id 'application'
}
group 'org.vladdrummer'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

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

jar {
    manifest {
        attributes 'Main-Class': 'MovieQuizBackendKt'
    }
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
    compile "com.sparkjava:spark-kotlin:1.0.0-alpha"
    implementation 'com.google.code.gson:gson:2.8.2'
    runtime 'mysql:mysql-connector-java:5.1.34'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}

Here's structure :

structure

Here's main class :

class MovieQuizBackend {

    fun main(args: Array<String>) {
        Server()
    }
}
CrazyCoder
  • 389,263
  • 172
  • 990
  • 904
Vlad Alexeev
  • 2,072
  • 6
  • 29
  • 59

1 Answers1

28

In Kotlin language entry point is not a method inside the class (a class with the Kt suffix in the name is generated automatically from a file). See the documentation.

Your code inside the MovieQuizBackend.kt file needs to be changed to the following:

fun main(args : Array<String>) {
    Server()
}

Just remove the class MovieQuizBackend { and } at the end.

You can even omit args if you don't plan to pass any:

fun main() {
    Server()
}

Another option is to use @JvmStatic annotation inside the companion object:

class MovieQuizBackend {
    companion object {
        @JvmStatic fun main(args : Array<String>) {
            Server()
        }
    }
}

Note that this way the main class is named just MovieQuizBackend instead of MovieQuizBackendKt, so you will need to change it in build.gradle:

jar {
    manifest {
        attributes 'Main-Class': 'MovieQuizBackend'
    }
}
CrazyCoder
  • 389,263
  • 172
  • 990
  • 904
  • 2
    It's so weird. I was wondering why we need kt files without classes in it and should I add @JvmStatic. But all this looks odd – Vlad Alexeev Dec 17 '19 at 00:15
  • 1
    It may look odd for the long time Java developers, but for the new programmers it's quite natural and allows to save a lot of typing. Try to explain a new student starting to write a code why in Java you need a class and the static main method just to print "hello world". Kotlin tries to simplify things and decrease the amount of code you need to write. – CrazyCoder Dec 17 '19 at 00:23
  • You don't even need `args: Array` if you don't use them. – Alexey Romanov Dec 17 '19 at 07:29
  • Do you build the jar using Gradle or IntelliJ IDEA artifact? – CrazyCoder Dec 17 '19 at 07:42
  • @CrazyCoder artifact via Idea – Vlad Alexeev Dec 17 '19 at 07:43
  • Try Gradle instead, building artifact from IDEA may be complicated because of the included jars order which may override the manifest file. See https://stackoverflow.com/a/54894502/104891. See also https://stackoverflow.com/a/42200519/104891 and https://stackoverflow.com/a/45169655/104891. – CrazyCoder Dec 17 '19 at 07:44
  • @CrazyCoder is it Gradle->Tasks->Build->build ? it says A problem was found with the configuration of task ':startScripts'. > No value has been specified for property 'mainClassName'. – Vlad Alexeev Dec 17 '19 at 08:10
  • To build a proper jar with dependencies using Gradle you will need to adjust the script, see https://medium.com/@preslavrachev/kotlin-basics-create-executable-kotlin-jars-using-gradle-d17e9a8384b9. Or check https://stackoverflow.com/questions/26469365/building-a-self-executable-jar-with-gradle-and-kotlin with the shadow jar example. – CrazyCoder Dec 17 '19 at 08:15