javajared
javajared

Reputation: 383

How to build valid JAR file with gradle from Ktor Kotlin/Java app

I have been trying to create an executable JAR for my Kotlin/Java Ktor project. Creating the actual JAR with my gradle script has been simple, but for whatever reason I can't for the life of me figure out how to get past the error message: "JAR file: cannot find main class routing.MainKt". My Kotlin main function is located in a file named Main.kt in the package routing. Below is my gradle file. What am I doing wrong?

buildscript {
   ext.kotlin_version = '1.2.21'
   ext.ktorVersion = '0.9.0'

repositories {
    mavenCentral()
}
dependencies {
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
  }
}

apply plugin: 'java'
apply plugin: 'kotlin'

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

kotlin {
  experimental {
     coroutines "enable"
  }
}

jar {
  manifest {
     attributes 'Main-Class': "routing.MainKt"
  }

  from {
     configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
  }
}

repositories {
  mavenCentral()
  jcenter()
  maven { url "https://dl.bintray.com/kotlin/kotlinx" }
  maven { url "https://dl.bintray.com/kotlin/ktor" }
  maven { url "http://repository.jetbrains.com/kotlin-nosql" }
  maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}

dependencies {
  //Core Ktor libs
  compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
  compile "io.ktor:ktor-server-core:$ktorVersion"
  compile "io.ktor:ktor-server-netty:$ktorVersion"
  compile "io.ktor:ktor-freemarker:$ktorVersion"
  compile "io.ktor:ktor-locations:$ktorVersion"
  ...Other libs
}

Edit: When I run jar tf on the generated jar I get the following pertinent information:

routing/MainKt$chartsxyzApplication$5.class
routing/MainKt$chartsxyzApplication$5$1.class
routing/MainKt$chartsxyzApplication$4.class
routing/MainKt$chartsxyzApplication$4$1.class
routing/MainKt.class
routing/MainKt$redirect$1.class
routing/MainKt$chartsxyzApplication$5$2.class
routing/MainKt$chartsxyzApplication$2.class
routing/MainKt$chartsxyzApplication$1.class
routing/MainKt$chartsxyzApplication$3.class
routing/MainKt$main$1.class

Edit2: Here are the basics of Main.kt

package routing

import io.ktor.application.*
...

@location("/")
class Index
... A bunch of other locations

fun main(args: Array<String>) {
   embeddedServer(Netty, 8080, module = Application::chartsApplication).start()
}

fun Application.chartsApplication(){
   ...
}

suspend fun ApplicationCall.redirect(location: Any) {
   ...
}

fun ApplicationCall.refererHost() = request.header(HttpHeaders.Referrer)?.let { URI.create(it).host }

Upvotes: 4

Views: 2946

Answers (2)

avolkmann
avolkmann

Reputation: 3105

Here is an alternative to using the shadowjar plugin.

task fatJar(type: Jar) {
    manifest {
        attributes 'Implementation-Title': project.name,
                'Implementation-Version': version,
                'Main-Class': 'class.path.to.MainKt'
    }
    baseName = project.name
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA'
    with jar
}

Upvotes: 1

asm0dey
asm0dey

Reputation: 2931

I think the simple way for you will be to use shadowjar plugin

It will include all your libraries into your jar.

Upvotes: 1

Related Questions