我们开始开发一个新的web应用程序项目,并决定使用Maven。这个项目将使用一些旧的内部基于蚂蚁的jar库,所以我决定使用Nexus来创建我们的内部存储库。我将库部署到Nexus,并将pom.xml链接到新的存储库,并将依赖项设置为新建的artifact。Maven构建战争没有问题,我可以在服务器上部署它并启动。到目前为止,一切都很顺利。
但现在,当我尝试调用库的某些代码时,我得到了一个NoClassDefFoundError异常。
java.lang.NoClassDefFoundError: HTTPClient/HTTPConnection
at com.logica.imfplus.authentication.client.HttpConnection.connect(HttpConnection.java:217)
at com.logica.imfplus.authentication.client.HttpConnection.<init>(HttpConnection.java:135)
at com.logica.imfplus.authentication.client.LoginController.getResponse(LoginController.java:402)
at com.logica.imfplus.authentication.client.LoginController.login(LoginController.java:169)
at com.logica.imfplus.authentication.client.AuthClientAPI.internalLogin(AuthClientAPI.java:416)
at ...
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.ClassNotFoundException: HTTPClient.HTTPConnection
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1718)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1569)
... 38 more
我在谷歌上搜索了一点,并手动将依赖项添加到缺失的库中。
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.3</version>
</dependency>
但我得到了另一个不同的NoClassDefFoundError异常。所有的问题似乎都更加复杂。
我想我理解这个问题:jar库有自己的内部依赖项,由ant定义,但它们对maven不可见,所以它们仍然缺失。但我不知道,如何解决它。
如果我是对的,我曾考虑手动检查所有这些内部依赖项,并将它们添加到pom.xml中。但这似乎是一个肮脏的解决方案,我对此感到不安全。如果不必要的话,我也不想在pom.xml添加混乱。有没有更干净的方法,如何做到这一点?maven可以检查和解决蚂蚁之前定义的非mavenized jar库的内部依赖关系吗?
我仍在和maven一起学习,所以解决方案可能是显而易见的。我仍然没有发现任何有用的东西。
编辑:解决方案已找到并正在运行。我按照建议创建了一个新的pom.xml,并(手动)上传到Nexus。现在,maven正确地解析并下载了可传递的依赖关系。给你。(事实上,只有一个依赖项需要定义。)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.logica.imfplus.authentication</groupId>
<artifactId>authenticationClient</artifactId>
<packaging>jar</packaging>
<version>1.3.1.0_8</version>
<name>IMFplus authenticationClient</name>
<dependencies>
<dependency>
<groupId>net.sf.grinder</groupId>
<artifactId>grinder-httpclient</artifactId>
<version>3.9.1</version>
</dependency>
</dependencies>
</project>
我仍然得到一些ClassNotFoundException,但它可能是由库中的一些冲突引起的,这是另一回事。
实现这一点的理想方法是使用自己的pom重新构建内部库,在pom中指定其所有依赖项。然后,您应该将pom.xml指向您的nexus存储库并部署它(如mvn deploy
中所示)。这样,pom.xml也将在nexus中发布,任何使用maven依赖项的应用程序也将下载遗留库附带的所有依赖项
通常,您应该只将内部工件部署到内部Nexus。第三方工件应通过您的内部Nexus获得,该Nexus充当公共Nexus存储库的代理存储库。如今,您通常可以在某个公共存储库中找到大多数第三方工件。
当谈到Maven时,它使用了所谓的传递依赖关系,简而言之,这意味着如果工件A依赖于工件B,并且你创建了一个依赖于A的新工件,那么你也将依赖于B。
为了实现这一点,使用Maven构建工件A非常重要,因为依赖关系是在构建时捕获的。另一种选择是手动部署预构建的工件,在这种情况下,依赖性信息已经丢失,您必须通过为第三方工件创建pom来自己定义它。
假设依赖项是正确的(您可以使用mvn-dependency:list列出它们),当您使用Maven构建WAR时,所有编译和运行时依赖项都将包含在WEB-INF/lib目录中。
这个问题的一个好的解决方案是为ant项目创建一个pom.xml,它正确地声明了依赖关系,并使用其他ant任务将jar从ant构建部署到Nexus实例。
然后,您可以像使用任何其他依赖项一样使用Maven中Ant构建的Jar,它甚至可以自动管理正确的可传递依赖项。y