包含使用Gradle构建的Java库会抛出NoClassDefFoundError

tym*_*ymm 9 java dependencies jvm noclassdeffounderror gradle

我正在编写一个Java库,我想用Gradle构建库,然后从本地测试项目中测试它.

我更喜欢使用Gradle 3.3作为我的目标.该库应该是为Java5及更高版本构建的.

到目前为止,我build.gradle看起来像这样:

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'
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

库的源代码位于src/main/java/io/simplepush/Notification.java并依赖于build.gradle文件中声明的依赖项.

构建具有良好./gradlew build工作原理的库并生成build/jars/main/jar/main.jar.

但是当我从IntelliJ运行一个测试项目(包括main.jar在测试项目中之后)时,我得到以下运行时错误:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/HttpEntity.

看起来测试项目不知道我的库所需的运行时依赖性.

我不确定告诉测试项目关于我的库的依赖关系的正确方法是什么.我不想要一个包含所有依赖项的胖jar.
列出测试项目本身中的所有依赖项也不是一个选项.
我希望库本身能够告诉测试项目它需要哪些依赖项.

Bab*_*abl 6

您创建的库jar不包含IDE/Gradle随后可以解析的任何依赖性信息,以便能够编译/运行测试项目.我看到你正在使用maven中央存储库,所以你需要做的是将你的库发布到你的本地maven存储库,在测试项目中只需添加一个依赖信息(不仅仅是普通的jar文件).

因此,在库和测试项目中build.gradle添加maven本地存储库配置.

repositories {
   mavenLocal()
   mavenCentral()
}
Run Code Online (Sandbox Code Playgroud)

现在您需要将库发布到本地存储库.当您使用gradle 3.3时,您可以使用Maven Publishing.

所以在库中build.gradle添加maven发布信息.

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

            from components.java
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Gradle"maven-publish"插件可以轻松地发布到本地存储库,自动创建PublishToMavenLocal任务.所以你可以跑

gradle publishToMavenLocal

这会将包含所有依赖关系信息的库发布到本地maven存储库中.

然后,您只需要向测试项目添加库信息 build.gradle

dependencies {
        // other dependencies .....
        module 'io.simplepush:project1-sample:1.1'
}
Run Code Online (Sandbox Code Playgroud)


tym*_*ymm 2

我通过改变几件事解决了这个问题。
感谢@Babl为我指明了正确的方向。
我的新图书馆build.gradle看起来像这样:

plugins {
  id 'java'
  id 'maven-publish'
}

sourceCompatibility = 1.5

repositories {
  mavenLocal()
  mavenCentral()
}

dependencies {
  compile 'commons-codec:commons-codec:1.10'
  compile 'org.apache.httpcomponents:httpcore:4.4.6'
  compile 'org.apache.httpcomponents:httpclient:4.5.3'
}

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

      from components.java
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

现在我可以使用 .push 将库推送到本地 Maven 存储库./gradlew publishToMavenLocal

build.gradle测试项目的使用该插件application并定义一个主类(Hello在我的例子中)。然后我可以运行./gradlew installDist生成一个可执行文件(请参阅应用程序插件文档),该文件将所有依赖项放入类路径中并运行得很好。

group 'com.test'
version '1.0-SNAPSHOT'

apply plugin: 'java'
apply plugin: 'application'

repositories {
  mavenLocal()
  mavenCentral()
}

dependencies {
  compile 'io.simplepush:project1-sample:1.1'
}

mainClassName = "Hello"
Run Code Online (Sandbox Code Playgroud)