我们开始开发一个新的Web应用程序项目并决定使用Maven。这个项目将使用一些较旧的基于内部ant的jar库,所以我决定使用Nexus来创建我们的内部存储库。我将库部署到Nexus并将pom.xml链接到新存储库,并将依赖项设置为新创建的工件。 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
我用Google搜索了一点,并手动将依赖项添加到了丢失的库中。
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.3</version>
</dependency>
但是我得到了另一个不同的NoClassDefFoundError异常。所有问题似乎都更复杂。
我认为我理解这个问题:jar库有自己定义的内部依赖关系,但它们对于maven是不可见的,因此它们仍然缺失。但我不知道如何解决它。
如果我是对的,我正在考虑手动检查所有这些内部依赖项并将它们添加到pom.xml中。但这似乎是一个肮脏的解决方案,我不会感到安全。如果我不必,我也不想在我的pom.xml中加入混乱。有没有更干净的方法,怎么做? maven可以检查并解决之前由ant?
定义的非mavenized jar库的内部依赖关系我仍在学习maven,所以解决方案可能很明显。我仍然没有找到任何有用的东西。
编辑: 解决方案找到并工作。我根据建议创建了一个新的pom.xml,并定义了(手动)上传到Nexus的依赖项。现在,maven可以正确地解析和下载传递依赖性。这是fyi。 (实际上只有一个依赖项可以定义。)
<?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,但它可能是由库中的一些碰撞引起的,这是不同的故事。
答案 0 :(得分:2)
执行此操作的理想方法是使用自己的pom重建内部库,并指定其所有依赖项。然后,您应该将pom.xml指向您的nexus存储库并进行部署(如mvn deploy
中所述)。这样,pom.xml也将在nexus中发布,任何使用maven依赖的应用程序都会下载旧版库随附的所有依赖项。
答案 1 :(得分:2)
通常,您应该只将内部工件部署到内部Nexus。第三方工件应通过您的内部Nexus获取,该内部Nexus充当公共Nexus存储库的Proxy Repository。现在,您通常可以在某个公共存储库中找到大多数第三方工件。
当谈到Maven时,它会使用名为transitive dependencies的内容,简而言之,如果工件A依赖于工件B并且您创建了一个依赖于A的新工件,那么您可以使用它。 ll也取决于B.
为此,使用Maven构建工件A非常重要,因为在构建时捕获了依赖项。另一种方法是你manually deploy the pre-built artifact,在这种情况下,依赖信息已经丢失,你必须通过为第三方工件创建一个pom来自己定义它。
假设依赖项是正确的(您可以使用mvn dependency:list列出它们),当您使用Maven构建WAR时,所有编译和运行时依赖项都将包含在WEB-INF / lib目录中。
答案 2 :(得分:2)
解决此问题的一个好方法是为ant项目创建一个pom.xml,它正确地声明了依赖项,并使用aether ant tasks将jar从Ant构建部署到Nexus实例。
然后你可以像使用任何其他依赖项一样使用Maven中的Ant构建的Jar,它甚至可以管理automaticall.y
的正确传递依赖性。