88

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?

utdemir
  • 26,532
  • 10
  • 62
  • 81
  • I had the same problem, I had forgotten the package com.myapp.mypack.myclass in my main class. Adding it solved mine. – Ash Nov 20 '19 at 04:30

7 Answers7

150

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.

Matt Ryall
  • 9,977
  • 5
  • 24
  • 20
  • 6
    In case anyone runs into this answer, here is where you can get an actual version of the plugin, because 1.6 is pretty old now: http://mvnrepository.com/artifact/org.apache.maven.plugins/maven-shade-plugin – Scadge Aug 13 '15 at 10:05
  • 2
    Wouldn't the only difference be 3.1.1 (instead of 1.6)? Running "mvn package" seems to automatically download maven-shade – user3211306 Aug 01 '18 at 05:08
  • My team happens to use `org.apache.maven.plugins` and `maven-dependency-plugin` with `copy-dependencies`. – Andrew Kirna Oct 18 '18 at 21:10
  • 1
    @Scadge I've updated the plugin version to the latest (3.4.1) in the POM example above. Maven should download it automatically when you run your build; you don't need to go and get it manually. – Matt Ryall Nov 16 '22 at 04:01
23

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.

Ryan Stewart
  • 126,015
  • 21
  • 180
  • 199
  • Getting this error: http://pastebin.com/g2txkMY6. I can run it on eclipse with m2eclipse plugin, I developed the application on it. I can't just figure out how to run it via command line. And how to import my maven classpath? Edit: Tried with adding -classpath /home/utdemir/.m2/repository/ parameter to java command, still no luck. – utdemir May 13 '12 at 00:15
  • Thank you. Setting the classpath as you say solved the problem, marking the question as solved. But I have a few questions more: 1- Why don't I have to add Jackson to classpath for exec plugin? 2- Exec plugin needs my project to be compiled, so I should have run mvn compile or package, right? 3- This code is my assignment, does adding libraries into their classpaths is their responsibility, or I have to do something about it? – utdemir May 13 '12 at 12:40
  • 2
    1) Pretty much anything you run through maven, including the exec plugin, will automatically set up the class path for you based on your project's dependencies as specified in the pom. That's a major reason for maven's popularity. 2) Yes, you have to run at least `mvn compile` prior to running the exec plugin. 3) Finally, if I were handing in an assignment, I'd be sure that it were fully executable in whatever manner specified. If you have a question about how your project should be packaged or something for turning in, I'd suggest starting a new SO question. – Ryan Stewart May 13 '12 at 17:09
  • The plugin link is dead. – Cameron Hudson Sep 20 '19 at 19:56
7

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>
quangkid
  • 1,287
  • 1
  • 12
  • 31
madhawa
  • 184
  • 1
  • 8
3

For some reason, the lib is present while compiling, but missing while running.

One possible reason 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.

How to resolve depends conflict

exclude the lib which you don't need in pom file

<dependency>
    <groupId>xx</groupId>
    <artifactId>B</artifactId>
    <version>xx</version>
    <exclusions>
        <exclusion>
            <groupId>xx</groupId>
            <artifactId>D</artifactId>
        </exclusion>
    </exclusions>
</dependency>
  • 3
    For this answer to help the questioner, it would probably have been helpful if you had explained how to resolve the type of conflicts referred to. – Dragonthoughts Dec 06 '19 at 07:54
2

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>
Satya
  • 429
  • 3
  • 8
-2

I was able to work around it by running mvn install:install-file with -Dpackaging=class. Then adding entry to POM as described here:

Philip Rego
  • 552
  • 4
  • 20
  • 35
-5

Choosing to Project -> Clean should resolve this

user2009677
  • 436
  • 4
  • 9