9

I'm very new to Kotlin and Ktor and Gradle. Was able to create embedded server as explained in Ktor site, with the following code:

BlogApp.kt:

package blog

import org.jetbrains.ktor.netty.*
import org.jetbrains.ktor.routing.*
import org.jetbrains.ktor.application.*
import org.jetbrains.ktor.features.*
import org.jetbrains.ktor.host.*
import org.jetbrains.ktor.http.*
import org.jetbrains.ktor.response.*

fun Application.module() {
    install(DefaultHeaders)
    install(CallLogging)
    install(Routing) {
        get("/") {
            call.respondText("My Example Blog  sfs 122", ContentType.Text.Html)
        }
    }
}

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

and build.gradle:

group 'Example'
version '1.0-SNAPSHOT'

buildscript {
    ext.kotlin_version = '1.1.4-3'

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

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

sourceCompatibility = 1.8
ext.ktor_version = '0.4.0'

repositories {
    mavenCentral()
    maven { url  "http://dl.bintray.com/kotlin/ktor" }
    maven { url "https://dl.bintray.com/kotlin/kotlinx" }
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
    compile "org.jetbrains.ktor:ktor-core:$ktor_version"
    compile "org.jetbrains.ktor:ktor-netty:$ktor_version"
    compile "ch.qos.logback:logback-classic:1.2.1"
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
kotlin {
    experimental {
        coroutines "enable"
    }
}

The server run fine at: localhost:8080

and the I can see the below files in the out folder:

C:\Users\Home\IdeaProjects\Example\out\production\classes\blog

How can I know create an executable file .jar of this server, so I can distribute it to the user?

enter image description here

Opal
  • 81,889
  • 28
  • 189
  • 210
Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203

2 Answers2

11

What you need to do is to add the following piece of code to build.gradle file:

jar {
    baseName '<jar_name>'
    manifest {
        attributes 'Main-Class': 'blog.BlogAppKt'
    }

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

Then run: gradle clean jar. After it's finished navigate to: build/libs and run java -jar <jar_name>.jar.

Or run it using javaw -jar <jar_name>.jar instead of java (you might need to make sure its on the path if the JAVA_HOME is not defined well). This will run it without any console.

P.S. You can also use application plugin or shadowJar.

Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203
Opal
  • 81,889
  • 28
  • 189
  • 210
  • 1
    When I run it from IJ terminal, I got this error: 'gradle' is not recognized as an internal or external command, operable program or batch file. – Hasan A Yousef Sep 22 '17 at 17:51
  • 1
    when I run it from cmd, I got this: * What went wrong: Task 'clean' not found in root project 'blog'. – Hasan A Yousef Sep 22 '17 at 17:53
  • @HasanAYousef, are you sure you run it from correct location and have java and kotlin plugins applied? – Opal Sep 22 '17 at 18:13
  • 1
    Something looks to be wrong in my setup, once I used text editor and command line only, creating the files with `gradle init --type java-library` then creating my files, and compile them `gradle clean jar` everything gone smooth as you described. – Hasan A Yousef Sep 23 '17 at 08:51
  • @HasanAYousef, no idea what may caused the problem but I'm glad it works now! – Opal Sep 23 '17 at 08:53
0

There is alternative version for build.gradle.kts (kotlin-based gradle file).

tasks.jar {
  // for the case if inside your project there is some duplicate
  duplicatesStrategy = DuplicatesStrategy.EXCLUDE
  manifest.attributes["Main-Class"] = "blog.BlogAppKt"
  configurations["compileClasspath"].forEach { file: File ->
    from(zipTree(file.absoluteFile))
  }
  archiveBaseName.set(project.name + "-all")
}

The result is ./build/libs/${project.name}-all.jar file.

For running:

java -jar ./build/libs/${project.name}-all.jar
Alykoff Gali
  • 1,121
  • 17
  • 32