5

I am trying to run a java project from the command line in linux :

$ java -jar target/my-app.jar -csv test.csv

and got this error

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/cli/ParseException
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2531)
    at java.lang.Class.getMethod0(Class.java:2774)
    at java.lang.Class.getMethod(Class.java:1663)
    at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:494)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:486)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.cli.ParseException

I'm using maven-3, here my build maven configuration :

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                    <sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>${appClass}</mainClass>
                            <classpathPrefix>lib/</classpathPrefix>
                            <useUniqueVersions>false</useUniqueVersions>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

And my commons-cli dependency declaration

        <!-- CLI -->
        <dependency>
            <groupId>commons-cli</groupId>
            <artifactId>commons-cli</artifactId>
            <version>1.2</version>
        </dependency>

If I remove code & dependencies into my class I get no more error.

Thank you !

biology.info
  • 3,500
  • 2
  • 28
  • 39
  • 1
    duplicate of questions like http://stackoverflow.com/questions/574594/how-can-i-create-an-executable-jar-with-dependencies-using-maven . From all solutions I prefer using maven-shade-plugin instead – Robert Scholte Sep 01 '15 at 12:47
  • You're right, but i think that accepted answer is no good – biology.info Sep 01 '15 at 12:53
  • With maven-shade-plugin we got a full jar that contains all dependencies. You think it's better than maven-dependency-plugin approach that generate all dependencies in a lib folder ? – biology.info Sep 01 '15 at 13:31
  • It just depends on how you want to distribute it and how you expect that users will execute it. maven-shade-plugin ends op with the easiest approach, but it will be harder to determine the dependencies. – Robert Scholte Sep 01 '15 at 14:32

4 Answers4

6

You are using maven but you are running the application from command line so you need to provide all the required jars to your application:

Approach 1: You can provide into your classpath like below:

$ java -jar -cp "list-of-jars" target/my-app.jar -csv test.csv

If you are on Windows the path will be semi colon separated and on Linux it will colon separated. You can use wild cards also like /*.jar to include all the jars(java6+).

Approach 2: You can use one fat/uber/one jar to combine all the jars into on jar run it like you want.

Below is using one-jar:

Using Maven: you need to update the plugins section pom.xml:

<plugin>
        <groupId>org.dstovall</groupId>
        <artifactId>onejar-maven-plugin</artifactId>
        <version>1.4.4</version>
        <executions>
          <execution>
            <goals>
                <goal>one-jar</goal>
            </goals>
          </execution>
        </executions>
    </plugin>

And update pluginRepositories section in pom.xml

<pluginRepository>
        <id>onejar-maven-plugin.googlecode.com</id>
        <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
</pluginRepository>

When you will execute the mvn package you will get yourappname-one-jar.jar and you can run it java -jar yourappname-one-jar.jar

Approach 3: To use the maven shade plugin (as Robert suggested):

Add this into the plugins section of pom.xml:

<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.4.1</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <mainClass>org.sonatype.haven.HavenCli</mainClass>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>

Upon execution on mvn package the uber jar will be generated.

Garry
  • 4,493
  • 3
  • 28
  • 48
  • I do not agree with you, see my solution – biology.info Sep 01 '15 at 12:55
  • @biology.info .. there are lot of option along with mentioned above like maven-assembly plugin. Anything works for you is great. – Garry Sep 01 '15 at 13:00
  • Garry > thx you for your reply, i did not agree with your first approach, but your post is now very useful! – biology.info Sep 01 '15 at 13:03
  • @biology.info .. your welcome, but I think I was right in finding the cause of your issue ;) – Garry Sep 01 '15 at 13:07
  • I tested the third approach to compare > the difference is that in one case we get a jar compiled with all dependencies and in the other case the dependencies are stored in a separate folder – biology.info Sep 01 '15 at 13:24
  • @biology.info .. thanks for testing and sharing the results. Yes, I think for your case maven-dependency plugin it will be stored in separate folder. – Garry Sep 01 '15 at 13:33
0

Using maven-dependency-plugin is a solution.

 <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.8</version>
    <executions>
        <execution>
             <id>copy-dependencies</id>
             <phase>package</phase>
             <goals>
                 <goal>copy-dependencies</goal>
             </goals>
             <configuration>
                 <outputDirectory>${project.build.directory}/lib</outputDirectory>
             </configuration>
        </execution>
     </executions>
</plugin>
biology.info
  • 3,500
  • 2
  • 28
  • 39
0

Use maven assembly plugin in your pom.xml. this will bundle all your dependencies in a single jar.

<plugin> 
<artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                       <mainClass>com.app.appmain</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
            </configuration>
        </plugin>
 <dependencies>
   <dependency>
        <groupId>commons-cli</groupId>
        <artifactId>commons-cli</artifactId>
        <version>1.3</version>
    </dependency>
   </dependencies>

To build: mvn clean compile assembly:single

Pari Rajaram
  • 422
  • 3
  • 7
-2

The -jar parameter is incompatible with -classpath or abreviatted -cp.

So when you launch your java process using a jar file you must provide a valid Manifest.mf file which declares a correct classpath.

This is the manifest example from java documentation:

Manifest-Version: 1.0
Class-Path: MyUtils.jar
Created-By: 1.7.0_06 (Oracle Corporation)

Then you may put the .jar file inside the definitive .jar file wherever you want (then you may add the path to it). Or just leave it outside, but respect the path as if it where inside the .jar file.

amk
  • 112
  • 1
  • 5