我有一个 Maven 项目,其中包含一个使用 gradle 作为 pom 依赖项创建的 jar。 在包含 Jar 的代码中,我引用了 log4j logmanager。 当我尝试访问外部 jar 中的方法时,它会在外部 jar 内的类所引用的 logmanager 上抛出 java.lang.NoClassDefFoundError 。
外部 jar 的 build.gradle 是:
plugins {
id 'java'
}
group 'com.somecompany.somethingelse'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.13.0'
implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.13.0'
}
我使用 gradle clean assemble 构建 jar
我使用 mvn install:install-file 将此 jar 本地安装到 .m2 中,然后在使用应用程序的 pom 中具有它的依赖项。
我不太确定这里发生了什么。
外部Jar类代码
package com.company.something;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public abstract class MyClass{
private static Logger logger = LogManager.getLogger();
public static String myMethod(String someInput){
logger.info("entered myMethod");
......some code goes here.....
}
}
Jar 消费类代码
import com.company.something.MyClass;
public class consumingClass{
public String consumingMethod(){
MyClass.myMethod("someinput");
return "something";
}
}
最佳答案
当您使用mvn install:install-file
时,您正在安装jar文件并使用普通Maven为其创建默认pom。如果您不执行任何其他操作,pom 将不会包含任何传递依赖项。毕竟,Maven 只看到一个 jar 文件,对周围的 Gradle 脚本一无所知。这就是为什么它在运行时失败,因为库(“外部”)pom 中缺少 Log4J 依赖项。
您应该做的是使用 Maven Publish Plugin for Gradle为您的库创建合适的 pom。通过添加以下内容来做到这一点:
plugins {
id 'maven-publish'
}
publishing {
publications {
myLibrary(MavenPublication) {
from components.java
}
}
}
然后,您可以使用 gradlepublishToMavenLocal
将包含完整 pom 的 jar 文件上传到本地 .m2 存储库。
此外,ysakhno's answer关于编译类路径上不需要 log4j-core
的部分是正确的 - 这只是不好的做法。相反,您应该删除它并使使用项目将其添加为显式依赖项,或将配置从implementation
更改为仅运行时
。两种方法都可以,具体取决于您希望 Log4j 与库的耦合程度。
我还认为在库中使用 Log4J2 API 是完全可以的,即使它可以在使用许多不同日志记录实现的项目中使用。毕竟,将 Log4J2 API 绑定(bind)到 SLF4J 和反之亦然一样容易。两者都很受欢迎,而且都是非常好的选择。
关于Java 代码对外部库中的类抛出 NoClassDefFoundError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60103216/