Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java代码为外部库中的类抛出NoClassDefFoundError_Java_Maven_Gradle - Fatal编程技术网

Java代码为外部库中的类抛出NoClassDefFoundError

Java代码为外部库中的类抛出NoClassDefFoundError,java,maven,gradle,Java,Maven,Gradle,我有一个maven项目,其中包括一个jar,我使用gradle作为pom依赖项创建了这个jar。 在包含的Jar代码中,我引用了log4j logmanager。 当我尝试访问外部jar中的方法时,它会在外部jar中的类所引用的logmanager上抛出java.lang.NoClassDefFoundError 外部jar的build.gradle是: plugins { id 'java' } group 'com.somecompany.somethingelse' versio

我有一个maven项目,其中包括一个jar,我使用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 Assembly构建了这个罐子

我使用mvn install:install文件将这个jar本地安装到.m2中,然后在消费应用程序的pom中对它有依赖关系

我真的不确定这里发生了什么

外部Jar类代码 Jar消费类代码 您可能需要添加此选项

编译组:“org.apache.logging.log4j”,名称:“log4j-1.2-api”,版本:“2.2”
也是 这个想法就是你们并没有足够的依赖性来满足你们的需求。这种情况经常发生在伐木工人身上

参考:

一般来说,日志库有2个JAR的原因(如您展示的示例中所示)是为了让库只针对库的API JAR进行编译,然后在运行时使用日志库的实际实现(在您的示例中是
log4j core
)显示在消费应用程序的类路径上的某个位置

考虑到上述内容,您必须分离库和应用程序之间的依赖关系,即在库的
build.gradle
中,您应该有以下内容:

dependencies {

    implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.13.0'
    // Note: you do not need the 'actual' implementation of Log4j in your library
    // at all!  It should compile very well with just the API, you'll then have
    // to put an 'implementation' dependency on log4j-core in your consuming
    // application's build.gradle (or pom.xml for that matter)

}
然后,在应用程序的pom.xml中,您必须添加以下内容:

    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.13.0</version>
    </dependency>

org.apache.logging.log4j

另一方面,我建议让您的库不依赖于Log4j的API,而是依赖于一个API,因为这样消费应用程序就可以选择使用哪个日志库实现。如以下所述:

图书馆和其他嵌入式组件应该考虑SLF4J。 因为库负担不起 他们对最终用户日志框架的选择


注意:无论您选择做什么,都不要在Gradle构建脚本中使用
compile
依赖项配置,因为它在不久前已被弃用,并且可能无法与Gradle的未来版本一起使用。大致相当于
compile
的配置是
api

当您使用
mvn install:install file
时,您正在安装jar文件并使用普通Maven为其创建默认pom。如果不执行任何其他操作,pom将不包含任何可传递依赖项。毕竟,Maven只看到一个jar文件,对周围的Gradle脚本一无所知。这就是为什么它在运行时失败,因为库(“外部”)pom中缺少Log4J依赖项

您应该做的是使用为库创建适当的pom。为此,请添加:

plugins {
    id 'maven-publish'
}

publishing {
    publications {
        myLibrary(MavenPublication) {
            from components.java
        }
    }
}
然后,您可以使用
gradle publishToMavenLocal
将jar文件上载到本地.m2存储库,其中包含完整的pom

另外,在编译类路径上不需要
log4j core
的部分中,这是正确的-这只是一种糟糕的做法。相反,您应该删除它并使消费项目将其作为显式依赖项添加,或者将配置从
implementation
更改为
runtimeOnly
。这两种方法都很好,这取决于您希望将Log4j与库耦合的程度


我还认为在库中使用log4j2api是非常好的,即使它可以在使用许多不同日志实现的项目中使用。毕竟,将log4j2api绑定到SLF4J和将log4j2api绑定到SLF4J一样容易。这两个都是很受欢迎且非常好的选择。

您可以发布一个简单的Java代码示例,该示例与您已经提供的Gradle构建脚本一起,将演示您遇到的问题吗?您是指消费应用程序中的Java代码?实际上,两者都应该更好(库和消费应用程序)。还请显示消费应用程序的Gradle构建脚本。顺便说一句,每次修改库时,您不需要在本地Maven repo中手动安装库,因为您可以使用Gradle:added code的复合构建特性。此外,消费应用程序是一个maven项目,而不是gradle项目。我使用简单的mvn clean Install构建它,这听起来非常违反直觉。正在使用的jar应该是自给自足的,并且使用它的代码应该是不可知的。如果消费代码本身不想记录任何东西,为什么它应该包括与log4j相关的库呢?您的库应该只包括编译所需的依赖库。您的库本身不会运行,因此它实际上不需要任何实际的实现依赖项,更不用说它应该将这些依赖项强加给消费应用程序。考虑一下我刚才谈到的SLF4J案。它也有API和JAR,但是猜猜看,它有几个不同的实现JAR。如果您在库中选择了一个特定的JAR,则消费应用程序需要努力选择不同的内容。消费应用程序对日志记录一无所知。由于一些项目限制,我无法使用slf4j。但不管怎样,我不知道你为什么建议在消费应用程序中进行任何更改,以代替外部jar的任何日志记录需求。这完全违背了使用第三方外部jar的目的。我也遇到过其他外部jar的问题,比如fasterxml.jackson。我即将创建一个uber jar,现在到此为止,即使您的应用程序不直接使用任何日志类,它仍然需要提供日志配置。因此,最终,您的应用程序并不像您想象的那样对所选库不可知。如果上述任何一点都不能说服你,以及
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.13.0</version>
    </dependency>
plugins {
    id 'maven-publish'
}

publishing {
    publications {
        myLibrary(MavenPublication) {
            from components.java
        }
    }
}