Question

We started to develop a new web application project and decided to use Maven. This project will use some older internal ant based jar library, so I decided to use Nexus to create our internal repository. I deployed the library to Nexus and linked pom.xml to the new repository and set the dependency to newly created artefact. Maven builds war without problems, I can deploy it on server and launch. So far, everything is working fine.

But now, when I try to call some code of the library, I got a NoClassDefFoundError exception.

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

I googled little bit and added dependency manually to the missing library.

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.3.3</version>
</dependency>

But I got another various NoClassDefFoundError exceptions. All problem seems to be more complex.

I think I understand the problem: The jar library has it's own internal dependencies defined by ant, but they are not visible for maven so they are still missing. But I don't know, how to solve it.

If I am right, I was thinking of examining all those internal dependencies manually and add them to pom.xml. But it seems like dirty solution and I don't feel safe about it. I also don't want to add mess to my pom.xml, if I don't have to. Is there any cleaner way, how to do it? Can maven examine and resolve internal dependencies of non-mavenized jar library defined earlier by ant?

I am still learning with maven, so solution is maybe obvious. I still didn't find anything useful.


EDIT: Solution found and working. I created a new pom.xml with defined dependencies as suggested and (manually) uploaded to Nexus. Now transitive dependencies are correctly resolved and downloaded by maven. Here it is fyi. (There was in fact only one dependency to define.)

<?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>

I still got some ClassNotFoundException, but it is probably caused by some collision in libraries, this is different story.

Was it helpful?

Solution

The ideal way to do this is to rebuild your internal library with a pom of its own where you specify all its dependencies. Then you should point that pom.xml to your nexus repository and deploy it (as in mvn deploy). This way, the pom.xml will get published too in nexus and any application using the maven dependency will download too every dependency that your legacy library carries with it.

OTHER TIPS

In general, you should only be deploying your internal artifacts to your internal Nexus. 3rd party artifacts should be obtained via your internal Nexus that acts as a Proxy Repository to the public Nexus repositories. These days, you can normally find most 3rd party artifacts in a public repository somewhere.

When it comes to Maven, it uses what's called transitive dependencies, which in short means that if artifact A depends on artifact B and you create a new artifact that depends on A, you'll also depend on B.

For this to work it's important that artifact A is built with Maven because the dependencies are captured at build time. The alternative is that you manually deploy the pre-built artifact, in which case the dependency information has been lost and you'll have to define it yourself by creating a pom for the 3rd party artifact.

Assuming the dependencies are correct (you can list them with mvn dependency:list), when you build a WAR with Maven, all the compile and runtime dependencies will be included in the WEB-INF/lib directory.

A good solution for this problem is to create a pom.xml for the ant project that declares the dependencies correctly and use the aether ant tasks to deploy the jar from the Ant build to the Nexus instance.

Then you can use the Ant built Jar from Maven like any other dependency and it will even have the correct transitive dependencies managed automaticall.y

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top