I'm new to Kotlin and Gradle, and tried to follow these steps, so I got the following 2 files:
after running gradle init I changed the build.gradle to be:
// set up the kotlin-gradle plugin
buildscript {
ext.kotlin_version = '1.1.2-2'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
// apply the kotlin-gradle plugin
apply plugin: "kotlin"
apply plugin: 'application'
mainClassName = "hello.main"
// add kotlin-stdlib dependencies.
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
Hello.kt:
package hello
fun main(args: Array<String>) {
println("Hello World!")
}
Then I run the gradle build and got the build\classes\main\hello\HelloKt.class
my question is: Why the file generated is .class not .jar and how to get the .jar file and how to run it, I tried running the generated file using kotlin -classpath HelloKt.class main but got an error error: could not find or load main class hello.main
The classes are the direct output of the Kotlin compiler, and they should be packaged into a JAR by Gradle afterwards. To build a JAR, you can run the jar task, just as you would in a Java project:
gradle jar
This task is usually run during gradle build as well, due to the task dependencies.
This will pack the Kotlin classes into a JAR archive (together with other JVM classes, if you have a multi-language project), normally located at build/libs/yourProjectName.jar.
As to running the JAR, see this Q&A for a detailed explanation: (link)
Thanks for #hotkey answer, it helped me going the correct way.
First of all there is a mistake in the main class declaration, as it should follow the new methodology, that is in the below format:
mainClassName = '[your_namespace].[your_arctifact]Kt'
namespace = package name
arctifact = file name
so, considering the names given in the example above where filename is: Hello.kt, and the namespace is hello, then:
mainClassName = `[hello].[Hello]Kt`
using the previous method, that contains:
apply plugin: 'application'
mainClassName = 'hello.HelloKt'
the generated .jar file is not including the kotlin runtime, so the only way to execute it, is by:
d:/App/build/libs/kotlin -cp App.jar hello.HelloKt
but in order to generate a self contained jar that can be self-executed, and contains the kotlin runtime then the build.gradle should be written as:
// set up the kotlin-gradle plugin
buildscript {
ext.kotlin_version = '1.1.2-2'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
// apply the kotlin-gradle plugin
apply plugin: "kotlin"
// add kotlin-stdlib dependencies.
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
jar {
manifest {
//Define mainClassName as: '[your_namespace].[your_arctifact]Kt'
attributes 'Main-Class': 'hello.HelloKt'
}
// NEW LINE HERE !!!
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
followed by gradle build, the [your_working_folder].jar file will be generated at the build/libs folder, assuming the working folder name is app, then file app.jar will be generated.
To run this file, one of the following 2 commands can be used:
D:\App\build\libs\java -jar App.jar
OR
D:\App\build\libs\kotlin App.jar hello.HelloKt
Related
Gradle Version: 1.12/2.0 (restricted due to Org policies)
JDK: 1.8
I have created a custom gradle plugin that performs some installation using code that has been defined in another sub-project of our source-code. The build.gradle for the plugin is
dependencies {
compile project(path: ':installlib', configuration: 'libConfig')
compile project(path: ':tools', configuration: 'toolConfig')
}
jar {
from {
// LINE#1 source-code of plugin
sourceSets.main.output
zip64 = true
// LINE#2 dependencies
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
baseName = 'myCustomPlugin'
version = '1.0'
destinationDir = new File(project.libDir)
}
The above plugin is consumed as follows - consumer.gradle
buildscript {
repositories { flatDir name: 'libs', dirs: System.env.CODESOURCE + '/lib/')
dependencies {
classpath: ':myCustomPlugin:1.0'
}
}
apply plugin: 'java'
apply plugin: 'myCustomPlugin'
...
...
//rest of the items of this gradle
Case-A
If I run this, I hit > Plugin with id 'myCustomPlugin' not found.
NOTE: I have META-INF/gradle-plugins/myCustomPlugin.properties created correctly with implementation-class pointing to my plugin code and this works fine if I don't get into creating the fat/uber-jar business and just include the sourceSets.main.output statement in my jar task. But since our entire project depends on file based artifacts, I am attempting to create a fat/uber-jar and that's where I start running into these issues.
Case-B
If I move the LINE#2 above the LINE#1, which looks like -
from {
// LINE#2 dependencies
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
// LINE#1 source-code of plugin
sourceSets.main.output
zip64 = true
}
If I run this, I hit ClassNotFoundException for one of the classes coming from the project 'installlib'. I can see the *.class file in the uber jar created but even then the class loader complains about this class.
Could anyone provide some pointers on how to resolve this ? The uber/fat jar creation (or the way I am doing it) is not helping with the plugin-source-code and dependencies of the plugin.
If not a fat jar, could anyone provide some inputs on how to resolve the dependencies in the buildscript of the consuming gradle ?
I am using gradle to package some java code into a jar. I am using some classes from tools.jar. I have had success in gradle building it and making a jar, but when I run that jar using java -jar <package>.jar I get the folowing
java.lang.NoClassDefFoundError: com/sun/tools/attach/VirtualMachine.
Since tools.jar is something you get with a jdk, not a jre. Is there a way I can bundle tools.jar with my package.jar and have my jar work anywhere?
Here is my build.gradle so far.
buildscript {
repositories {
maven {
url 'https://plugins.gradle.org/m2/'
}
}
}
description = "A java program"
apply plugin: 'java'
sourceCompatibility = 1.8
repositories {
mavenCentral()
flatDir {
dirs System.properties['java.home'] + '/../lib'
}
}
jar {
archiveName = "jProg.jar"
manifest {
attributes(
'Dependencies': 'com.sun.tools'
)
}
}
dependencies {
compile group: 'com.sun', name: 'tools'
}
Probably what you need is called 'fat jar' (Gradle packs all dependencies to single jar)
I have a javaFx Kotlin application build with gradle.
It's a file containing main method:
package com.grined.toptal.invoice
import javafx.application.Application
fun main(args: Array<String>) {
Application.launch(App::class.java)
}
Gradle file looks like that:
version = '1.4'
buildscript {
ext.kotlin_version = '1.2.41'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
mainClassName = "com.grined.toptal.invoice.MainKt"
jar {
zip64 = true
manifest {
attributes "Main-Class": "$mainClassName"
}
from {
configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) }
}
}
dependencies {
compile "org.mapdb:mapdb:3.0.5"
...
}
...
I'm calling gradle clean build to produce a jar.
When I'm trying to call java -jar jarName.jar I see that error:
Error: Could not find or load main class com.grined.toptal.invoice.MainKt
I tried to use Main instead of MainKt, the same issue. Also, I checked content of jar file and there is a necessary file in a required place.
The problem was with dependency org.mapdb:mapdb:3.0.5. Removing it - solves the problem.
I have a JavaFx application and I cannot run it from both command line and windows explorer.I built the jar using Gradle, and checked for the manifest and it is correct. I tried everything from StackOverflow but it always complains that it cannot find the entry point from Manifest:
My main is located in src/main/java and it is called Main.
Here is the configuration for gradle:
group 'com'
version '1.0'
apply plugin: 'java'
apply plugin: 'application'
sourceCompatibility = 1.8
mainClassName = 'Main'
repositories {
mavenCentral()
}
jar {
manifest {
attributes('Main-Class': 'Main')
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
Please ignore the dependecies (I build an uber jar).
And here is the content of my manifest(created by gradle with the new line at the end):
Manifest-Version: 1.0
Main-Class: Main
When I try to run it i get all the time this:
Error: Could not find or load main class Main
Because you apply the application plugin, none of the customisations of the jar tasks are required.
So I recommend you remove them and check if it creates a valid jar then.
While I did not confirm by running it locally, I believe the customisation done in from is wrong and creates a busted jar.
I am using the java plugin in my build.gradle.
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile 'xyz:xyz:4.11'
}
sourceSets {
test {
java {
srcDir 'agent'
}
}
}
I am generating the .class files by doing
$ gradle compileJava
Now that the .class files have been generated in build/, how do I run my code? One of the class files contains the main. I want to do something like this from a gradle task:
CLASSPATH=./mysql-connector-java-commercial-5.1.13-bin.jar:. $JAVA_HOME/bin/java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=10000 Collector arg1
You may want to take a look at Gradle Application Plugin.
With it, you will be able to run your application just using a run task.
Based on ghik's answer, I add these to my gradle.build script:
apply plugin:'application'
....
dependencies {
....
runtime 'mysql:mysql-connector-java-commercial:5.1.13'
}
mainClassName = "Collector"
run {
args 'arg1'
jvmArgs '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=10000'
}