Gradle not compiling dependency jars in lib folder

I am new to gradle and learning now. I am trying to build a runnable jar using gradle(My builded jar should be run from command prompt). I just started with a simple HelloWorld project with a dependency and try to build it using gradle. I am not using maven. So I added the dependency jar to the lib folder inside project folder. Below are the details.

Gradle Version: 3.1 Eclipse Version: Neon

HelloWorld.java

package com.padhu.test;
import org.joda.time.LocalTime;

public class HelloWorld {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        LocalTime currentTime = new LocalTime();
        System.out.println("The current local time is: " + currentTime);

        System.out.println("Hello World");

    }

}

build_path_snap

build.gradle file:

apply plugin: 'java'
apply plugin: 'application'
mainClassName = 'com.padhu.test.HelloWorld'

repositories {

   flatDir {
      dirs 'lib'
   }
}

dependencies {


    compile files(fileTree(dir: 'lib', includes: ['*.jar']))

    }

jar {
  manifest {
    attributes(

      'Main-Class': 'com.padhu.test.HelloWorld'
    )
  }
}

I can successfully execute gradle build in my cmd and jar file is getting generated. But inside jar file, I can see only HelloWorld folder structure, but couldnt see the dependency files. So I am not able to run the jar from command prompt since I am getting NoClassDefFoundError: org/joda/time/LocalTime…

I tried fixing the issue myself by searching and reading blogs…but I am not able to run the jar successfully.

Kindly help me.

You are building an executable JAR, but you’re not building a “fat” JAR. You’ll either need to explicitly create one, use a plugin that does so, or run the JAR with the additional classpath information.

You’re currently applying the application plugin and configuring it on lines 2 and 3. This will create a distribution (not just a single JAR) with start scripts you can run from the command line. However, if you want just the “fat” JAR, you can remove these two lines.

Manually configuring the JAR is pretty simple. You would just add one line to your jar { ... } block:

jar {
    manifest {
        attributes 'Main-Class': 'com.padhu.test.HelloWorld'
    }
    from configurations.runtime.collect { zipTree(it) }
}

This would be good enough for what you have, but if you eventually add dependencies that are folders rather than JARs, you could follow the example in this blog post to handle that scenario as well. Note that the blog post uses compile rather than runtime. Either should work for you in your example, but runtime is technically more accurate.

If you just want to apply a plugin that will take care of it, Shadow would be a possibility.

Also, as a side note, your repositories / dependencies blocks are redundant. If you are declaring a file system dependency, you don’t need a flat dir repository. If you’re using a flat dir repository, you can declare your actual dependencies instead.

dependencies {
    compile files(fileTree(dir: 'lib', includes: ['*.jar']))
}

-OR-

repositories {
    flatDir { dirs 'lib' }
}

dependencies {
    compile 'joda-time:joda-time:2.1'
}

Personally, I’d use the second one to be explicit about dependencies. This also has the added benefit that you could change from the flatDir to a maven repository at any time and your dependencies would be correct for both cases.

2 Likes

Thanks for the detailed information. Your solution worked.

compile is deprecated in new gradle version. What is the new approach? I tried with implementation, but jar won’t compile implementation libraries.