New to gradle - am I missing something with the classpath?

not-a-bug

(John) #1

I am new to Gradle, just trying a simple example to see if I can figure out what is going on. I have a Mouse class in a Jar. I have a class that creates an instance of mouse like so:

public class Animals {
    public static void main(String args[]){
        Mouse mouse = new Mouse("Mickey");

        mouse.squeak();
    }
}

Very simple. Here is my build.gradle file:

apply plugin: 'java'
sourceSets{
    main{
        java {
            srcDirs=['src']
        }
    }
}

/*repositories {
	flatDir{
		dirs 'lib'
	} 
}*/

dependencies {
    compile files("lib\\Mouse.class")
}

When I run gradle build on the command line, it seems to work, but as soon as I try to run the main program, it says “NoClassDefFoundError: Mouse”. Do I need to include something else in the build.gradle file to make this run? It seems like it is expecting to find the Mouse jar in the classpath, but I thought part of using Gradle was to avoid having to do that. What options do I have to fix this?


(davidmichaelkarr) #2

Just to address the limited scope of your question, the issue is that Gradle is compiling your source files and producing class files, but this is just the building step. If you try to run your class outside of Gradle, it won’t use the artifacts the build produced unless you point Java to use them.


(John) #3

Hi David, thanks for the info. I changed my build.gradle file by adding the jar code as seen in the Java Quickstart docs, thinking that the dependencies would be added to the jar. That didn’t work. (It did build the jar though)

jar {
    manifest {
        attributes('Main-Class': 'Animals')
    }
}

Then I tried adding the uploadArchives to my build.gradle file thinking that the dependencies might be put there. This also didn’t work. I tried with both dirs "libs" and dirs ".\\libs", thinking it would put my Mouse dependency there.

uploadArchives {
    repositories {
        flatDir {
            dirs ".\\libs"
        }
    }
}

All of these build, but none seem to use the Mouse Jar. Do you have any ideas on what to try next? It seems like I am missing something obvious.


(Chris Doré) #4

You want to declare a dependency on the module (jar) containing the Mouse class.

So, if mice.jar is in the lib directory, try:

repositories {
    flatDir {
        dir 'lib'
    }
}
dependencies {
    compile ':mice'
}

Some more information on the flat directory artifact repository type https://docs.gradle.org/current/javadoc/org/gradle/api/artifacts/repositories/FlatDirectoryArtifactRepository.html


(John) #5

Hi Chris, that is promising.
When I use that structure, executing gradle dependencies seems to find the .jar file. However, once it is built, I navigate to the folder with the generated .class file, and it still gives me the NoClassDefFound error when I try to run it. Running the generated jar file also gives me the same error.

Do you have any other ideas? It seems like it knows where the mice.jar file is, the generated .class or .jar files just can’t seem to find it. I have not modified my classpath of course-I thought I could get around that with gradle.


(Chris Doré) #6

What command are you running, are you supplying mice.jar on the classpath during the execution?

Also, you might find the application plugin useful. It adds a run task to Gradle, which will execute with the required runtime classpath.


(John) #7

I run gradle build first. Then, I navigate to the folder it generates (it is /build/classes/java/main/Animals.cass).
Then I run java Animals. I do not supply mice.jar on the classpath, I haven’t touched the classpath at all. Normally, I would put the mice.jar on the classpath, but I thought gradle would build dependencies together with a project, allowing me to not worry about the classpath. Is that not correct?

My goal with learning gradle is to stop copying jars and dependencies all over the place and then having the classpath point to them. It sounds like a gradle.build file can help with this, I’m just not understanding how to do it in my examples.

Also, in my experimenting with Gradle, if I use IntelliJ Idea to set up a “gradle project”, I no longer have to specify a folder of jars if my gradle.build file has them as a dependency. Maybe this is why I thought gradle took away the need to declare jars in the classpath.


(Chris Doré) #8

OK, I see. No, Gradle, by default, does not remove the need for you work with classpaths at runtime.

One example of a solution is the application plugin I suggested. In addition to the run task, it also adds the creation of some distributions (for example, a zip). That zip contains the application jar, all of the required library jars, as well as a script which executes the required java command.

Another solution could be the creation of a “fat” or “shadow” jar. Some plugins from a quick Google search:


(John) #9

Thanks for your help! It is much appreciated.


(Benjamin Muschko) #10

Hi John,

This guide should help clear up some questions: https://guides.gradle.org/building-java-applications/.

Cheers,

Ben