Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Including Java library built with Gradle throws NoClassDefFoundError

I am writing a Java library and I would like to build the library with Gradle and then test it from a local test project.

I would prefer using Gradle 3.3 for my objective. The library should be built for Java5 and higher.

So far my build.gradle looks like this:

plugins {
  id 'jvm-component'
  id 'java-lang'
}

repositories {
  mavenCentral()
}

model {
  components {
    main(JvmLibrarySpec) {
      sources {
        java {
          dependencies {
            module 'commons-codec:commons-codec:1.10'
            module 'org.apache.httpcomponents:httpcore:4.4.6'
            module 'org.apache.httpcomponents:httpclient:4.5.3'
          }
        }
      }

      api {
        exports 'io.simplepush'
      }

      targetPlatform 'java5'
    }
  }
}

The source code of the library is located in src/main/java/io/simplepush/Notification.java and depends on the dependencies stated in the build.gradle file.

Building the library with ./gradlew build works fine and generates build/jars/main/jar/main.jar.

However when I run a test project from IntelliJ (after including main.jar into the test project), I get the following runtime error:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/HttpEntity.

It seems like the test project does not know about the runtime dependencies needed by my library.

I am not sure on what is the correct way to tell the test project about the dependencies of my library. I do not want a fat jar which includes all dependencies.
Listing all dependencies in the test project itself is also not an option.
Preferably I want the library itself to tell the test project about which dependencies it needs.

like image 653
tymm Avatar asked Feb 14 '17 19:02

tymm


1 Answers

The library jar which you have created does not contain any dependency information which the IDE/Gradle can then resolve to be able to compile/run the test project. I see that you are using the maven central repository so what you need to do is to publish your library to your local maven repository and in the test project just add a dependency information (no just plain jar file).

So in both library and test project build.gradle add a maven local repository config.

repositories {
   mavenLocal()
   mavenCentral()
}

And now you need to publish the library to local repository. As you are using the gradle 3.3 you can use the Maven Publishing.

So in the library build.gradle add a maven publishing information.

publishing {
    publications {
        maven(MavenPublication) {
            groupId 'io.simplepush'
            artifactId 'project1-sample'
            version '1.1'

            from components.java
        }
    }
}

Gradle “maven-publish” plugin makes this easy to publish to local repository automatically creating a PublishToMavenLocal task. So you can just run

gradle publishToMavenLocal

Which will publish your library with all the dependency information into local maven repository.

And then you just need to add a library information to you test projects build.gradle

dependencies {
        // other dependencies .....
        module 'io.simplepush:project1-sample:1.1'
}
like image 186
Babl Avatar answered Oct 06 '22 01:10

Babl