1

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?

RenceAbi
  • 522
  • 2
  • 11
  • 26
  • Does this answer your question? [Why am I getting a NoClassDefFoundError in Java?](https://stackoverflow.com/questions/34413/why-am-i-getting-a-noclassdeffounderror-in-java) – leopal Nov 04 '20 at 12:41
  • No. I understood the issue. But I dont know how to fix this! – RenceAbi Nov 04 '20 at 12:44

1 Answers1

0

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.

dpr
  • 10,591
  • 3
  • 41
  • 71
  • So Considering gradle plugin, How can i add dependency library to jar? – RenceAbi Nov 04 '20 at 12:54
  • @RenceAbi what do you mean by this? The application plugin will create a bundle with all dependencies included automatically. An alternative might be to create a shadow-jar (also called fat- or uber-jar) - that is a single jar file with all dependencies bundled into this single jar. There is a plugin for this as well https://imperceptiblethoughts.com/shadow/ – dpr Nov 04 '20 at 12:58
  • @RenceAbi is there anything left to add to make the answer at least upvote worthy? – dpr Nov 05 '20 at 10:19