I am trying to use kotlin with gradle, but I am unable to succesfully create a project with Intellij Idea 15.
I've create simple project with two modules hello-java and hello-kotlin.
hello-java is plain java project and it is compiling and running perfectly fine.
hello-kotlin is simple kotin module, with just one *.kt file and build.gradle file.
Here are the sources:
build.gradle
group 'pl.fzymek.kotlin'
version '1.0-SNAPSHOT'
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.10.4"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
mainClassName = 'HelloKotlinKt'
repositories {
mavenCentral()
}
jar {
manifest {
attributes 'Main-Class': mainClassName
}
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:0.10.4"
}
HelloKotlin.kt
fun main(args: Array<String>) {
println("Hello, Kotlin!")
}
main module settings.gradle
include 'hello-java'
include 'hello-kotlin'
When running gradlew clean build all projects are compiled successfully, but when running java -jar hello-kotlin-1.0-SNAPSHOT.jar I get following error:
Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
at HelloKotlinKt.main(HelloKotlin.kt)
Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
What is more, Intellij seems not to recognize src/main/kotlin directory as source directory (it's not marked in blue) and I am not able to use auto-complete feature when editing HelloKotlin.kt file.
Here's my project structure in Intellij project window
I've tried using Intellij option to configure modules with Kotlin(Tools->Kotlin->Configure project with Kotlin), but it gives me error that "All modules with kotlin files are configured"
Help me stackoverflow, you are my only help.
When running gradlew clean build all projects are compiled successfully, but when running java -jar hello-kotlin-1.0-SNAPSHOT.jar I get following error...
jar {
manifest {
attributes 'Main-Class': 'HelloKotlinKt'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
What is more, Intellij seems not to recognize src/main/kotlin directory as source directory (it's not marked in blue)...
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
Documentation and useful resources can be found here and there.
Why doesn't my application run?
The Jar you're creating doesn't include the kotlin runtime as Gradle will only build a Jar with your class files in it. I see you're using the application plugin so either doing $ gradle run or creating a distribution and executing through the provided shell script should work ok. If you want to ship kotlin with your Jar you'll need to create a fat jar.
Why doesn't IDEA recognise the source directory?
I suspect this is down to the fact you haven't applied the idea plugin in your build file. I haven't done any work with Kotlin, but with other languages this is required to set up the workspace correctly.
I just do that documentation says, and all work fine.
"Kotlin sources can be mixed with Java sources in the same folder, or in different folders. The default convention is using different folders:
project
- src
- main (root)
- kotlin
- java
The corresponding sourceSets property should be updated if not using the default convention:
sourceSets {
main.kotlin.srcDirs += 'src/main/myKotlin'
main.java.srcDirs += 'src/main/myJava'
}
Hope it helps for you.
Related
I've tried everything by now, so I hope someone in here can tell me more...
Im trying to produce an executable .jar from a IntelliJ Gradle JavaFX project. I used the standard setup that IntelliJ provided, I changed the Gradle.build file however.
The new file I got from here: Non-Modular Gradle (openjfx.io)
I have a main class that has some basic code in it and a launcher class that does not extend Application and is specified as the Main class in the jar manifest.
For now I only use javafx.controls and basically everything is as the example they provided here.
When doing the ./gradlew jar command I get the error:
no module-info.java found
Which - as I understand - is not required if I use the Non-Modular approach?
However if I add it I get the error:
Entry module-info.class is a duplicate but no duplicate handling strategy has been set.
I tried every other option out there, all of them lead to either the 2. error or the jar was produced but not executable due to the fact that it can't find the Application class...
Any help is greatly appreciated.
I just want to point out that I've never really used Gradle before and have never formally learned any coding, but can fiddle my way around usually.
For the sake if it my build file:
plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.9' // this is old right?
}
repositories {
mavenCentral()
}
dependencies {
/* uncomment for cross-platform jar: */
runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:win"
runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:linux"
runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:mac"
}
javafx {
version = "16"
modules = [ 'javafx.controls' ]
}
mainClassName = 'main.class.with.Code'
jar {
manifest {
attributes 'Main-Class': 'main.class.with.Launcher'
}
from {
// this is what causes the module duplicate error I think (at least it did in my other tries)
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
I have a Simple Gradle based Java project, After gradle build jar has been created under build/libs folder. When i try to run in cmd using java -jar discord-notification-bot-1.0-SNAPSHOT.jar in the below path
F:\github projects\discord-notification-bot\build\libs>
I'm getting below Error
Exception in thread "main" java.lang.NoClassDefFoundError: org/javacord/api/DiscordApiBuilder
at Application.main(Application.java:8)
Caused by: java.lang.ClassNotFoundException: org.javacord.api.DiscordApiBuilder
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
build.gradle
plugins {
id 'java'
}
group 'org.test'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.javacord:javacord:3.0.6'
}
jar {
manifest {
attributes(
'Main-Class': 'Application'
)
}
}
under src/Application.java
import org.javacord.api.DiscordApi;
import org.javacord.api.DiscordApiBuilder;
public class Application {
public static void main(String[] args) {
String key = System.getenv().get("key");
DiscordApi api = new DiscordApiBuilder().setToken(key).login().join();
System.out.println("you can invite the bot by using following url "+api.createBotInvite());
}
}
It seems javacord library is not getting reflected while i run via cmd.
Note: in MANIFEST.MF I have main application correctly.
But dependency is not getting reflected while running via cmd.
So, What should I do for that?
The gradle java plugin will not add classpath information to the generated JARs by default. You could add this information similar to the way you added the main class but you're probably better off using the gradle application plugin.
With the application plugin you'll get an archive file as output that bundles all dependencies and some bat/sh files as well for execution. A simple gradle file with the application plugin might look like this:
plugins {
// Apply the application plugin to add support for building a CLI application in Java.
id 'application'
}
repositories {
// Use JCenter for resolving dependencies.
jcenter()
}
dependencies {
// This dependency is used by the application.
implementation 'com.google.guava:guava:29.0-jre'
}
application {
// Define the main class for the application.
mainClass = 'gradle.application.App'
}
As mentioned in the comments another solution might be to create a shadow/fat/uber-jar using the com.github.johnrengelman.shadow plugin. Which will result in this basic gradle file:
plugins {
id 'java'
// Apply the shadow plugin to add support for building a shadow-jar
id "com.github.johnrengelman.shadow" version "6.1.0"
}
repositories {
// Use JCenter for resolving dependencies.
jcenter()
}
dependencies {
// This dependency is used by the application.
implementation 'com.google.guava:guava:29.0-jre'
}
jar {
manifest {
attributes(
'Main-Class': 'Application'
)
}
}
With the shadow-plugin you get an additional task shadowJar that will create a JAR with all dependencies included. While this sounds very handy, it comes with some drawbacks e.g. when using the shadow-jar as dependency itself, which might result in the need of additional configuration. In your case however, this might be the best option.
My gradle build file is
plugins {
// Apply the java plugin to add support for Java
id 'java'
// Apply the application plugin to add support for building a CLI application
id 'application'
}
apply plugin: 'java'
jar {
from configurations.runtime
manifest {
attributes(
'Created-By':'Gmack',
'Main-Class':'myapprunner.App',
'Class-Path':'mydaos-1.0.jar'
)
}
}
allprojects{
repositories {
jcenter()
}
}
subprojects {
version = '1.0'
apply plugin: 'java'
}
dependencies {
// This dependency is used by the application.
implementation 'com.google.guava:guava:27.1-jre'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
// Compile Project for dependency
compile project(':mydaos')
}
application {
// Define the main class for the application
mainClassName = 'myapprunner.App'
}
When I run the app using java -jar myapprunner.jar
I get a ClassNotFoundException
Caused by: java.lang.ClassNotFoundException: com.mydaos.Library
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 1 more
I can confirm that the jar has been packed. Not sure why this is not picking things up.
Any help would be appreciated.
Thanks,
Plugin java is being applied twice and com.mydaos.Library is likely being pulled in from compile project(':mydaos') (or 'Class-Path':'mydaos-1.0.jar'). Would assume the project does not build or the class path is wrong.
Dependency classes (projects/external jars) aren't packed inside your jar by default.
You are using the application plugin which bundles your classes, your dependencies and an execution script in a zip so you should use that. The plugin also adds a "run" task to your project to run your main class via gradle for development purposes. See the application plugin docs for more info
If you want to pack your dependencies inside your jar (known as an uber jar) see here. I suggest you stop using the application plugin if you do this
'Class-Path':'mydaos-1.0.jar'
This assumes that mydaos-1.0.jar is in the same folder you are running java -jar ... from which is likely not the case
I am doing the simple HelloWorld example from https://spring.io/guides/gs/gradle/.
I had to do some changes (I'm using Gradle 5.2.1 on Ubuntu 18) to the build.gradle. I used gradlew wrapper. I managed to get tasks like 'build' and 'run' working. Everything is generated correctly, it seems. But running the app without gradle using the generated build/scripts/<appscript> does not work. Running the jar with
java -jar build/libs/hello-1.0.jar
works. But
./build/scripts/sayhello
Does not work and produces an error:
erno#moongate:~/Projects/java/sayhello$ ./build/scripts/sayhello
Error: Could not find or load main class hello.HelloWorld
Caused by: java.lang.ClassNotFoundException: hello.HelloWorld
Project file structure is as suggested:
sayhello/
build.gradle
gradlew
src/
main/
java/
hello/
Greeter.java
HelloWorld.java
I had to add the manifest and the mainclass attribute to the build configuration file as it seems that the gradle init --type java-application does not do it. Meaning that even trying to run the gradle generated base project does not work.
My build.gradle is like this:
plugins {
id 'java'
id 'application'
}
mainClassName = 'hello.HelloWorld'
repositories {
mavenCentral()
jcenter()
}
dependencies {
compile "joda-time:joda-time:2.10"
testCompile "junit:junit:4.12"
}
jar {
manifest {
attributes(
'Main-Class': 'hello.HelloWorld'
)
}
baseName = 'hello'
version = '1.0'
}
The problem with the startScripts task is that it generates a very basic script. It does not make sure dependent jars are in the right places - it expects this to be done by you. Also it assumes that you will be running the script from a directory it refers to as the $APP_HOME and this folder needs to contain a lib folder which contains all the jars your app needs.
My very hacky solution is to generate an even more basic unix script instead of relying on the default one.
startScripts {
dependsOn jar
doFirst {
unixStartScriptGenerator = configure(new CustomUnixStartScript()) {
classpath = configurations.runtimeClasspath + jar.outputs.files
}
}
}
class CustomUnixStartScript implements ScriptGenerator {
#InputFiles
FileCollection classpath
#Override
void generateScript (JavaAppStartScriptGenerationDetails details, Writer destination) {
destination << """java -classpath $classpath.asPath ${details.mainClassName}"""
}
}
You can extend this as you see fit.
I've made a project in maven and spring boot. After build it via maven it worked perfect.
After all I decided to swap my project into gradle. And now, after:
gradle build
The following exception is comming.Error:
Error: Could not find or load main class
Here are things I checked before I asked this question:
made sure that I have main method (which i obviously have, maven did thing great)
checked path to main class in manifest and in jar task in gradle
found out that compiled class is in specified jar in specified path
Made a jar task in gradle that looks like this:
jar {
manifest {
attributes 'Main-Class': 'pl.sygnity.schedulein.App'
}
}
I have no idea what i can do more about it.
Could you help me?
Edit.
It's important i wish to use my program as jar so:
java -jar xx.jar
Edit2.
gradle run
makes my App start. So it looks like as if gradle build is not working somehow...
You need to define the main class in the build.gradle file. (You may have more than one, and you need to choose which one to use)
I like to do it with Gradle - the application plugin
apply plugin: 'application'
mainClassName = "<Your main class>"
Then you can run gradle install to build the program with an executor.
You need to modify your gradle manifest.
jar {
manifest {
attributes <...>
'Main-Class': 'main.myMainClass'
}
}
Otherwise you can change the path of your source fields like this.
sourceSets.main.java.srcDirs = ['MAINFOLDER'] // 'src'
So i find out that these steps made my jar working well.
Removed
apply plugin: 'maven'
Added
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
Bit weird but maybe someone will be struggling with same kind of problem. Thanks for help.