Reputation: 1311
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
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
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
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
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