Paagalpan
Paagalpan

Reputation: 1311

java.lang.ClassNotFoundException: org.jsoup.nodes.Document using Maven

I'm using maven to manage my project.

This is my main file:

package com.sample;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

/**
 * Hello world!
 *
 */
public class App {
    public static void main(String[] args )
    {
        try
        {

        /*  String html = "<html><head><title>First parse</title></head>"
                      + "<body><p>Parsed HTML into a doc.</p></body></html>";
                    Document doc = Jsoup.parse(html);*/
            Document doc = Jsoup.connect("http://www.javatpoint.com").get();  
            String title = doc.title();  
            System.out.println("title is: " + title);  
        }
        catch (Exception e)
        {
            System.out.println(e);
        }
    }
}

This is my pom.xml:

<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.sample</groupId>
    <artifactId>sample-pc</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>sample-pc</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.8.3</version>
                    <scope>compile</scope>

        </dependency>

    </dependencies>

        <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.sample.App</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

When I run the following commands:

mvn clean package
java -jar target/sample-pc-1.0-SNAPSHOT.jar 

I get the following errors:

Error: A JNI error has occurred, please check your installation and try again Exception in thread "main" java.lang.NoClassDefFoundError: org/jsoup/nodes/Document at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) at java.lang.Class.privateGetMethodRecursive(Class.java:3048) at java.lang.Class.getMethod0(Class.java:3018) at java.lang.Class.getMethod(Class.java:1784) at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526) Caused by: java.lang.ClassNotFoundException: org.jsoup.nodes.Document at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.

However, if I directly run the app from eclipse, it runs without any errors. I am not sure why I cant run it from the command line.

Thanks

Upvotes: 2

Views: 7225

Answers (4)

mipo256
mipo256

Reputation: 3140

Maven jar plugin is created on the package phase, and the jar created by this plugin is, by default, not executable, though you have specified the class that contains main method in the generated MANIFEST.MF file:

<archive>
   <manifest>
   <mainClass>com.sample.App</mainClass>
   </manifest>
</archive>

so you was able to execute it, but this JAR that you have assembled only contains the compiled source code file (.class files generated from your source .java files) and the resources (typically located in src/main/resource folder, though this location can be overrided, extended e.t.c.), that's all.

So, this jar is not a fat JAR (you can create one with maven shade plugin, see official usage example here).

Also there is no Class-Path entry specified in the MANIFEST.MF within the JAR (you can specify the Class-Path entry in the maven jar plugin configuration, see here official example, also take a look into maven-dependency-plugin, also widely used in this cases) - so, JVM is throwing NoClassDefFoundError, because at runtime it is not able to find some classes, and this happens because JVM has no idea where to search for them

Ponder on it - classes of your dependencies are not present in the JAR itself, because it is not a fat Jar you are assembling, neither there is a classpath specified in your manifest.

So, I think the easiest solution would be to include the maven-shade-plugin into your build and assemble an uber jar. Include the following plugin into your build:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.3.0</version>
    <executions>
       <execution>
          <phase>package</phase>
          <goals>
            <goal>shade</goal>
          </goals>
       </execution>
    </executions>
</plugin>

Hope it helped, have a nice day.

Upvotes: 0

N K
N K

Reputation: 401

As an aside, I'm using IntelliJ IDEA with Maven support, and my setup is very similar to yours except for the scope: compile element in the dependency declaration. Looks like the IDE takes care of these specific requirements.

Unless you are specifically looking to understand Maven, you could consider using such an IDE to handle the minutiae for you.

Upvotes: 1

Avihoo Mamka
Avihoo Mamka

Reputation: 4786

Your JAR does not include your dependencies after it has been packaged.

Add this code to your pom.xml under the plugins section:

    <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <descriptor>assembly.xml</descriptor>
        </configuration>
    </plugin>

And add the file assembly.xml to your resources directory:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
    <!-- TODO: a jarjar format would be better -->
    <id>jar-with-dependencies</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>runtime</scope>
        </dependencySet>
    </dependencySets>
</assembly>

And then you can run mvn clean clean install or mvn package

Upvotes: 4

bmargulies
bmargulies

Reputation: 99993

Specifying a dependency to Maven makes it available for compiling -- not for running your code afterwards. Eclipse reads your POM and also sees the dependency.

Read up on the appassembler-maven-plugin or about making a MANIFEST.MF with a Class-Path to solve your problem.

Upvotes: 2

Related Questions