包括使用 Gradle 构建的 Java 库会抛出 NoClassDefFoundError
Including Java library built with Gradle throws NoClassDefFoundError
我正在编写一个 Java 库,我想用 Gradle 构建该库,然后从本地测试项目对其进行测试。
我更愿意为我的 objective 使用 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'
}
}
}
库的源代码位于 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 不包含任何依赖信息,IDE/Gradle 然后可以解析这些信息以便能够 compile/run 测试项目。我看到您正在使用 maven 中央存储库,所以您需要做的是将您的库发布到本地 maven 存储库,并在测试项目中添加依赖信息(不仅仅是普通的 jar 文件)。
所以在库和测试项目中 build.gradle
添加一个 maven 本地存储库配置。
repositories {
mavenLocal()
mavenCentral()
}
现在您需要将库发布到本地存储库。当您使用 gradle 3.3 时,您可以使用 Maven Publishing.
于是在库中build.gradle
添加一个maven发布信息
publishing {
publications {
maven(MavenPublication) {
groupId 'io.simplepush'
artifactId 'project1-sample'
version '1.1'
from components.java
}
}
}
Gradle “maven-publish” 插件可以轻松发布到本地存储库,自动创建 PublishToMavenLocal 任务。
所以你可以 运行
gradle publishToMavenLocal
这会将您的库和所有依赖信息发布到本地 maven 存储库中。
然后你只需要在你的测试项目中添加一个库信息即可build.gradle
dependencies {
// other dependencies .....
module 'io.simplepush:project1-sample:1.1'
}
这指定要检查哪些存储库以从中获取依赖项
repositories {
mavenCentral()
}
因此,dependecies{}
中的任何内容都将从上面的内容中获取。
如果测试项目未与库项目耦合,(@RaGe 示例)新测试项目需要知道从何处获取依赖项 - 您需要使用首选方法发布它。
之后,您的新测试项目需要在 build.gradle dependencies{}
中指定具有首选配置(编译...运行时等)的库
之后根据 IDE 您需要刷新类路径并从指定的之前存储库下载依赖项,库依赖项中指定的传递依赖项(在本例中)将从测试项目中获取 repositories{}
图书馆build.gradle
repositories {
mavenCentral()
}
dependencies {
module 'commons-codec:commons-codec:1.10'
module 'org.apache.httpcomponents:httpcore:4.4.6'
module 'org.apache.httpcomponents:httpclient:4.5.3'
}
测试项目build.gradle
repositories {
mavenCentral() repository to fetch transitives
mavenLocal() or any other repo that you published the library to
}
dependencies {
pref-conf librarygroup:name:version
}
您可以在 gradle 中为 gradle idea
或 gradle eclipseClasspath
任务使用 idea 或 eclipse 插件,以使用新添加的依赖项刷新它。
使用此解决方案,您应该不需要在库中打包传递依赖项,
PS。在你说你想要可执行的 jar 之后,我只是感到困惑。
我通过改变几件事解决了它。
感谢 @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
}
}
}
现在我可以使用 ./gradlew publishToMavenLocal
将库推送到本地 maven 存储库。
测试项目的build.gradle
使用了application
插件,定义了一个mainclass(在我的例子中是Hello
)。然后我可以 运行 ./gradlew installDist
生成一个可执行文件(参见 Application plugin docs),它将所有依赖项放在 class 路径和 运行 中就好了。
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"
我正在编写一个 Java 库,我想用 Gradle 构建该库,然后从本地测试项目对其进行测试。
我更愿意为我的 objective 使用 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'
}
}
}
库的源代码位于 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 不包含任何依赖信息,IDE/Gradle 然后可以解析这些信息以便能够 compile/run 测试项目。我看到您正在使用 maven 中央存储库,所以您需要做的是将您的库发布到本地 maven 存储库,并在测试项目中添加依赖信息(不仅仅是普通的 jar 文件)。
所以在库和测试项目中 build.gradle
添加一个 maven 本地存储库配置。
repositories {
mavenLocal()
mavenCentral()
}
现在您需要将库发布到本地存储库。当您使用 gradle 3.3 时,您可以使用 Maven Publishing.
于是在库中build.gradle
添加一个maven发布信息
publishing {
publications {
maven(MavenPublication) {
groupId 'io.simplepush'
artifactId 'project1-sample'
version '1.1'
from components.java
}
}
}
Gradle “maven-publish” 插件可以轻松发布到本地存储库,自动创建 PublishToMavenLocal 任务。 所以你可以 运行
gradle publishToMavenLocal
这会将您的库和所有依赖信息发布到本地 maven 存储库中。
然后你只需要在你的测试项目中添加一个库信息即可build.gradle
dependencies {
// other dependencies .....
module 'io.simplepush:project1-sample:1.1'
}
这指定要检查哪些存储库以从中获取依赖项
repositories {
mavenCentral()
}
因此,dependecies{}
中的任何内容都将从上面的内容中获取。
如果测试项目未与库项目耦合,(@RaGe 示例)新测试项目需要知道从何处获取依赖项 - 您需要使用首选方法发布它。
之后,您的新测试项目需要在 build.gradle dependencies{}
之后根据 IDE 您需要刷新类路径并从指定的之前存储库下载依赖项,库依赖项中指定的传递依赖项(在本例中)将从测试项目中获取 repositories{}
图书馆build.gradle
repositories {
mavenCentral()
}
dependencies {
module 'commons-codec:commons-codec:1.10'
module 'org.apache.httpcomponents:httpcore:4.4.6'
module 'org.apache.httpcomponents:httpclient:4.5.3'
}
测试项目build.gradle
repositories {
mavenCentral() repository to fetch transitives
mavenLocal() or any other repo that you published the library to
}
dependencies {
pref-conf librarygroup:name:version
}
您可以在 gradle 中为 gradle idea
或 gradle eclipseClasspath
任务使用 idea 或 eclipse 插件,以使用新添加的依赖项刷新它。
使用此解决方案,您应该不需要在库中打包传递依赖项,
PS。在你说你想要可执行的 jar 之后,我只是感到困惑。
我通过改变几件事解决了它。
感谢 @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
}
}
}
现在我可以使用 ./gradlew publishToMavenLocal
将库推送到本地 maven 存储库。
测试项目的build.gradle
使用了application
插件,定义了一个mainclass(在我的例子中是Hello
)。然后我可以 运行 ./gradlew installDist
生成一个可执行文件(参见 Application plugin docs),它将所有依赖项放在 class 路径和 运行 中就好了。
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"