I'm struggling to run a simple program that uses Apache POI to create an Excel document. This is also my first time with a Maven project, so that might have something to do with it:
My pom.xml looks like this:
<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.mycompany.app</groupId>
<artifactId>calendar</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>calendar</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.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.10-FINAL</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.10-FINAL</version>
</dependency>
</dependencies>
</project>
From what I can tell, my dependencies are alright.
This is my java code, I skipped over import statements but they are all there, no errors in this code from what I can tell:
public class App
{
private static final String FILE_NAME = "/tmp/MyFirstExcel.xlsx";
public static void main( String[] args ) throws IOException
{
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("Datatypes in Java");
Object[][] datatypes = {
{"Datatype", "Type", "Size(in bytes)"},
{"int", "Primitive", 2},
{"float", "Primitive", 4},
{"double", "Primitive", 8},
{"char", "Primitive", 1},
{"String", "Non-Primitive", "No fixed size"}
};
int rowNum = 0;
System.out.println("Creating excel");
for(Object[] datatype : datatypes) {
Row row = sheet.createRow(rowNum++);
int colNum = 0;
for(Object field : datatype) {
Cell cell = row.createCell(colNum++);
if(field instanceof String) {
cell.setCellValue((String) field);
}
else if(field instanceof Integer) {
cell.setCellValue((Integer) field);
}
}
}
try {
FileOutputStream outputStream = new FileOutputStream(FILE_NAME);
workbook.write(outputStream);
//workbook.close()
} catch (FileNotFoundException e) {
System.out.println("Couldn't find file to write out to");
} catch (IOException e) {
System.out.println("IO Exception in printing");
}
}
}
I have workbook.close() commented out since this caused an error (deprecated method?).
With the above code in my source folder, I can run mvn package which builds successfully and generates the .jar file calendar-1.0-SNAPSHOT.jar in the target folder.
I am attempting to run this file using
java -cp target/calendar-1.0-SNAPSHOT.jar com.mycompany.app.App
...and I get the following error message
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/poi/ss/usermodel/Workbook
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.privateGetMethodRecursive(Unknown Source)
at java.lang.Class.getMethod0(Unknown Source)
at java.lang.Class.getMethod(Unknown Source)
at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Caused by: java.lang.ClassNotFoundException: org.apache.poi.ss.usermodel.Workbook
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 7 more
If this question requires any more information let me know. I'm at a loss here.
You need to create a fat/uber jar with Maven Assembly Plugin. Which means create a Jar together with its dependency Jars into a single executable Jar file. When you run it then it would have all the dependencies available.
Add following plugin inside your POM
<build>
<plugins>
<!-- Maven Assembly Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<!-- get all project dependencies -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- MainClass in mainfest make a executable jar -->
<archive>
<manifest>
<mainClass>com.your.path.to.main.App</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Run following:
mvn package
Two jar files will be created in the target folder.
calendar-1.0-SNAPSHOT.jar – Only your project classes
calendar-1.0-SNAPSHOT-with-dependencies.jar – Project and dependency classes in a single jar.
You can run it follwoing;
java -cp target/calendar-1.0-SNAPSHOT-with-dependencies.jarcom.mycompany.app.App
You can review the contents of calendar-1.0-SNAPSHOT-with-dependencies.jar
jar tf target/calendar-1.0-SNAPSHOT-with-dependencies.jar
You are packaging your maven artifact as a jar and by default a jar packaged by the maven jar plugin doesn't include the dependency jars with the built artifact.
Whereas the missing class at runtime.
If you want to include dependency jars of your application inside your jar, you should use the maven assembly plugin and specify jar-with-dependencies for the descriptorRef parameter.
You could bind the assembly singlegoal execution to the package phase so that the mvn package execution that you are using actually creates automatically the expected jar.
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>YourMainClassPrefixedByItsPackage</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
The problem is that at compile time POI libraries are available but not at run time. The reason why they are available is that they are in Maven Dependency. Also I don't see any build wrapper in your pom file. You will need to add a build wrapper to build jar file that you can run outside of your IDE.
Now coming back to your problem, either you need to add POI jar in your CLASSPATH environment variable so that java run-time can access it or build a fat jar including dependencies.
You can use this template to add a build wrapper in pom file to build jar with dependencies.
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Maven package task just packs compiled classes of your project into a single jar file. All 3rd party libraries are not included, that's why you're getting error - POI class is not found.
You should build a runnable jar file that includes all dependencies. Please, refer to this question - you should use some additional maven plugins to achieve that
Related
I'm trying to get the basic HelloWorld JNA example working while using Maven to build a .jar. I'm starting with this directory structure:
.
+-- pom.xml
+-- src
+-- main
+-- java
+-- HelloWorld.java
HelloWorld.java contains the code from the JNA getting started page:
package com.sun.jna.examples;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
/** Simple example of JNA interface mapping and usage. */
public class HelloWorld {
// This is the standard, stable way of mapping, which supports extensive
// customization and mapping of Java to native types.
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)
Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
CLibrary.class);
void printf(String format, Object... args);
}
public static void main(String[] args) {
CLibrary.INSTANCE.printf("Hello, World\n");
for (int i=0;i < args.length;i++) {
CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
}
}
}
My pom.xml file contains the following:
<project>
<groupId>edu.berkeley</groupId>
<artifactId>hello-world</artifactId>
<modelVersion>4.0.0</modelVersion>
<name>Hello World</name>
<packaging>jar</packaging>
<version>1.0</version>
<properties>
<jna.version>4.5.0</jna.version>
</properties>
<dependencies>
<dependency> <!-- JNA dependency -->
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>${jna.version}</version>
</dependency>
<dependency> <!-- JNA platform dependency -->
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>${jna.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.sun.jna.examples.HelloWorld</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
I can build the target .jar without problem using mvn package, but when I try to run it I get the error mentioned in the title:
$ java -jar target/hello-world-1.0.jar
Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/jna/Library
...
I can see the JNA and JNA-platform .jar files in the maven local repository. The manifest file for the built .jar has the jna related files in its class path:
$ unzip -p target/hello-world-1.0.jar META-INF/MANIFEST.MF
Manifest-Version: 1.0
Built-By: root
Class-Path: jna-4.5.0.jar jna-platform-4.5.0.jar
Created-By: Apache Maven 3.0.4
Build-Jdk: 1.8.0_144
Main-Class: com.sun.jna.examples.HelloWorld
If I manually copy the JNA .jars to the target folder, the application runs, but these .jars get removed when I do mvn clean. I assume copying those .jars to the target directory is not correct since they are removed with a clean. What should I be doing instead to get this application to run?
EDIT:
From the link shared by Roman, I found that I need to use either the maven-assembly plugin or the maven-shade plugin. I ended up going with the maven-shade plugin and added the following to my pom.xml file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<artifactSet>
<includes>
<include>net.java.dev.jna:jna</include>
<include>net.java.dev.jna:jna-platform</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
I'm using the include option so that only the white-listed dependencies (JNA) are included in order to keep the build time and .jar file size are to a minimum.
I am trying to use the new Apache Commons Text new random string generator, but I can't find any usage on the Internet on how to properly import it. Maven builds successfully, but when I try to run my jar file from the command line with the following command
java -cp target/my-app-1.0.jar com.mycompany.app.App
…I get the below error:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/text/RandomStringGenerator$Builder
at com.mycompany.app.App.main(App.java:8)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.text.RandomStringGenerator$Builder
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
I also have this warning during the build:
The POM for org.apache.commons:commons-text:jar:1.1 is invalid, transitive dependencies (if any) will not be available, enable debug logging for more detail
Here is the Maven debug version:
[WARNING] The POM for org.apache.commons:commons-text:jar:1.1 is invalid, transitive dependencies (if any) will not be available: 1 problem was encountered while building the effective model
[FATAL] Non-parseable POM C:\Users\me\.m2\repository\org\apache\commons\commons-text\1.1\commons-text-1.1.pom: only whitespace content allowed before start tag and not a (position: START_DOCUMENT seen a... #1:1) # line 1, column 1
Here is my App.java code:
package com.mycompany.app;
import org.apache.commons.text.RandomStringGenerator;
public class App {
public static void main(String[] args) {
// Generates a 20 code point string, using only the letters a-z
RandomStringGenerator generator = new RandomStringGenerator.Builder()
.withinRange('a', 'z').build();
String randomLetters = generator.generate(20);
System.out.println( randomLetters );
}
}
Here 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.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<name>my-app</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
If you want to run you application from a jar, you will need an exploded jar. The default class loader will not find the apache jar from your jar.
You can use the shade plugin to create an exploded jar. Add something like below to your pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>com.mycompany.app.App</Main-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Then, you can run with the following:
java -jar target/my-app-1.0.jar
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
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
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.
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.
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.
My first use of Maven and I'm stuck with dependencies.
I created a Maven project with Eclipse and added dependencies, and it was working without problems.
But when I try to run it via command line:
$ mvn package # successfully completes
$ java -cp target/bil138_4-0.0.1-SNAPSHOT.jar tr.edu.hacettepe.cs.b21127113.bil138_4.App # NoClassDefFoundError for dependencies
It downloads dependencies, successfully builds, but when I try to run it, I get NoClassDefFoundError:
Exception in thread "main" java.lang.NoClassDefFoundError: org/codehaus/jackson/JsonParseException
at tr.edu.hacettepe.cs.b21127113.bil138_4.db.DatabaseManager.<init>(DatabaseManager.java:16)
at tr.edu.hacettepe.cs.b21127113.bil138_4.db.DatabaseManager.<init>(DatabaseManager.java:22)
at tr.edu.hacettepe.cs.b21127113.bil138_4.App.main(App.java:10)
Caused by: java.lang.ClassNotFoundException: org.codehaus.jackson.JsonParseException
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
... 3 more
My pom.xml is like this:
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>tr.edu.hacettepe.cs.b21127113</groupId>
<artifactId>bil138_4</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>bil138_4</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.6</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Can anyone help me?
By default, Maven doesn't bundle dependencies in the JAR file it builds, and you're not providing them on the classpath when you're trying to execute your JAR file at the command-line. This is why the Java VM can't find the library class files when trying to execute your code.
You could manually specify the libraries on the classpath with the -cp parameter, but that quickly becomes tiresome.
A better solution is to "shade" the library code into your output JAR file. There is a Maven plugin called the maven-shade-plugin to do this. You need to register it in your POM, and it will automatically build an "uber-JAR" containing your classes and the classes for your library code too when you run mvn package.
To simply bundle all required libraries, add the following to your POM:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
Once this is done, you can rerun the commands you used above:
$ mvn package
$ java -cp target/bil138_4-0.0.1-SNAPSHOT.jar tr.edu.hacettepe.cs.b21127113.bil138_4.App
If you want to do further configuration of the shade plugin in terms of what JARs should be included, specifying a Main-Class for an executable JAR file, and so on, see the "Examples" section on the maven-shade-plugin site.
when I try to run it, I get NoClassDefFoundError
Run it how? You're probably trying to run it with eclipse without having correctly imported your maven classpath. See the m2eclipse plugin for integrating maven with eclipse for that.
To verify that your maven config is correct, you could run your app with the exec plugin using:
mvn exec:java -D exec.mainClass=<your main class>
Update: First, regarding your error when running exec:java, your main class is tr.edu.hacettepe.cs.b21127113.bil138_4.App. When talking about class names, they're (almost) always dot-separated. The simple class name is just the last part: App in your case. The fully-qualified name is the full package plus the simple class name, and that's what you give to maven or java when you want to run something. What you were trying to use was a file system path to a source file. That's an entirely different beast. A class name generally translates directly to a class file that's found in the class path, as compared to a source file in the file system. In your specific case, the class file in question would probably be at target/classes/tr/edu/hacettepe/cs/b21127113/bil138_4/App.class because maven compiles to target/classes, and java traditionally creates a directory for each level of packaging.
Your original problem is simply that you haven't put the Jackson jars on your class path. When you run a java program from the command line, you have to set the class path to let it know where it can load classes from. You've added your own jar, but not the other required ones. Your comment makes me think you don't understand how to manually build a class path. In short, the class path can have two things: directories containing class files and jars containing class files. Directories containing jars won't work. For more details on building a class path, see "Setting the class path" and the java and javac tool documentation.
Your class path would need to be at least, and without the line feeds:
target/bil138_4-0.0.1-SNAPSHOT.jar:
/home/utdemir/.m2/repository/org/codehaus/jackson/jackson-core-asl/1.9.6/jackson-core-asl-1.9.6.jar:
/home/utdemir/.m2/repository/org/codehaus/jackson/jackson-mapper-asl/1.9.6/jackson-mapper-asl-1.9.6.jar
Note that the separator on Windows is a semicolon (;).
I apologize for not noticing it sooner. The problem was sitting there in your original post, but I missed it.
You have to make classpath in pom file for your dependency. Therefore you have to copy all the dependencies into one place.
Check my blog.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>$fullqualified path to your main Class</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
This is due to Morphia jar not being part of your output war/jar. Eclipse or local build includes them as part of classpath, but remote builds or auto/scheduled build don't consider them part of classpath.
You can include dependent jars using plugin.
Add below snippet into your pom's plugins section
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
For some reason, the lib is present while compiling, but missing while running.
My situation is, two versions of one lib conflict.
For example, A depends on B and C, while B depends on D:1.0, C depends on D:1.1, maven may
just import D:1.0. If A uses one class which is in D:1.1 but not in D:1.0, a NoClassDefFoundError will be throwed.
If you are in this situation too, you need to resolve the dependency conflict.
I was able to work around it by running mvn install:install-file with -Dpackaging=class. Then adding entry to POM as described here:
Choosing to Project -> Clean should resolve this
I'm having problems resolving sub-dependencies from a third-party package. I'm a bit of a Maven beginner. Basically it goes like this:
git clone git://github.com/unidata/thredds.git
cd thredds
mvn install
Everything works great and stuff is installed into ~/.m2. Now, I wrote my own code that uses the package that I just installed:
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<packaging>jar</packaging>
<version>0.1</version>
<name>Test Package</name>
<dependencies>
<dependency>
<groupId>edu.ucar</groupId>
<artifactId>netcdf</artifactId>
<version>4.3.8-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
Ok, this also works great when I run mvn package. The netcdf artifact is found. Now, when I try to run my code, I start down a long ClassNotFoundException path, having to keep adding all of netcdf's dependencies to my classpath.
Am I doing something wrong, or should the thredds package and all its dependencies automatically be picked up?
edit: the thredds package has many sub-modules one of which is netcdf. My code only depends on the netcdf jar.
edit: the snapshot version is installed
$ ls -l ~/.m2/repository/edu/ucar/netcdf/4.3.8-SNAPSHOT/
total 4272
-rw-rw-r-- 1 nwatkins nwatkins 700 2012-03-29 23:23 maven-metadata-local.xml
-rw-rw-r-- 1 nwatkins nwatkins 182 2012-03-29 23:23 _maven.repositories
-rw-rw-r-- 1 nwatkins nwatkins 4357494 2012-03-29 23:23 netcdf-4.3.8-SNAPSHOT.jar
-rw-rw-r-- 1 nwatkins nwatkins 7840 2012-03-29 22:28 netcdf-4.3.8-SNAPSHOT.pom
edit: to run the code which is in a single file Test.java
$ java -cp target/test-0.1.jar Test
edit: first error message
$ java -cp target/test-0.1.jar Test
Exception in thread "main" java.lang.NoClassDefFoundError: ucar/ma2/InvalidRangeException
Caused by: java.lang.ClassNotFoundException: ucar.ma2.InvalidRangeException
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
edit: then I just try to manually add the dependency jar to the class path
$ java -cp ../thredds/cdm/target/netcdf-4.3.8-SNAPSHOT.jar:target/test-0.1.jar Test
xception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
at ucar.nc2.NetcdfFile.<clinit>(NetcdfFile.java:97)
at Test.main(Test.java:37)
Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
... 2 more
The slf4j package is also in ~/.m2. I stopped trying to add things to the classpath after this as it seemed like the wrong approach.
at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
Two solutions here (the cause of the problem has been explained in several answers):
1.Use maven exec plugin to launch your app:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<classpathScope>runtime</classpathScope>
<executable>java</executable>
<commandlineArgs>-classpath %classpath Test</commandlineArgs>
</configuration>
</plugin>
2.You can also package your jar with all its dependencies, using maven assembly plugin. To do that, you need to add the following to your plugins of your build:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>build-package</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Then you can use the output jar created by maven assembly in your classpath arg
It sounds like you are trying to run your project from the target folder, and it is not seeing the transitive dependencies. You will need to use the maven dependencies plugin to have those dependencies copied over along with your jar file.
See also:
http://maven.apache.org/plugins/maven-dependency-plugin/copy-dependencies-mojo.html
You can then define the dependencies on these jars either manually, or via a generated manifest file:
http://maven.apache.org/shared/maven-archiver/index.html
The maven project that you've created only packages your classes into test-0.1.jar.
If you use a simple java command to run your application, you MUST provide all other jars that your project depends on to the -classpath ( or -cp ) switch ( or through CLASSPATH environment variable ).
There are alternative packaging configurations that can copy all required dependencies into a single jar, if that is what you want.
Here is the example, which is a verbatim copy from here -> http://www.sonatype.com/books/mvnref-book/reference/assemblies-sect-basics.html. I recommend that you read that whole chapter ( heck the whole book ) for better understanding.
<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>org.sonatype.mavenbook.assemblies</groupId>
<artifactId>executable-jar</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Assemblies Executable Jar Example</name>
<url>http://sonatype.com/book</url>
<dependencies>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-2</version>
<executions>
<execution>
<id>create-executable-jar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>
jar-with-dependencies
</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>org.sonatype.mavenbook.App</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
If you want to have all the dependencies in classpath, when running your jar, you can use the maven-exec-plugin to run the program from withing maven, and have all the dependencies automatically added to your classpath.
You are missing the dependency for:
org/slf4j/LoggerFactory
which means in other words you need to add a dependency to your project:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
Assuming you are using log4j ?
And furthermore based on the missing class: ucar.ma2.InvalidRangeException it looks you need an other supplemental dependency except (May be take a look into the documentation if exists).
<dependency>
<groupId>edu.ucar</groupId>
<artifactId>netcdf</artifactId>
<version>4.3.8-SNAPSHOT</version>
</dependency>