65

I have a Maven project which generates a jar file and copies all dependencies to target/lib folder. I want to execute this project on client's machine (windows). So, I copied myproject.jar to C:\xyz folder and all dependencies to C:\xyz\lib folder. How do I execute this project from client's command prompt? I tried to use java -cp lib\*.jar -jar myproject.jar from C:\xyz folder but it throws following error.

Exception in thread "main" java.lang.NoClassDefFoundError: lib\commons-codec-1/3/jar
Caused by: java.lang.ClassNotFoundException: lib\commons-codec-1.3.jar
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    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)
Could not find the main class: lib\commons-codec-1.3.jar.  Program will exit.

I think if I specify all dependencies in classpath (like java -cp lib\dep1.jar;dep2.jar), it will get rid of the problem but I don't want to do this as I have 40 libraries already and it might grow in future releases. Is there a better way to do this?

Jagger
  • 10,350
  • 9
  • 51
  • 93
Praneeth
  • 1,457
  • 5
  • 23
  • 36

9 Answers9

80

You cannot use both -jar and -cp on the command line - see the java documentation that says that if you use -jar:

the JAR file is the source of all user classes, and other user class path settings are ignored.

You could do something like this:

java -cp lib\*.jar;. myproject.MainClass

Notice the ;. in the -cp argument, to work around a Java command-line bug. Also, please note that this is the Windows version of the command. The path separator on Unix is :.

Sualeh Fatehi
  • 4,700
  • 2
  • 24
  • 28
  • 1
    from what I read in the documentation, the * represents one or more jar files. So you need to say -cp lib\*; You should not use it in the normal sense (one or more characters) – Brian Jul 30 '14 at 14:26
  • 1
    Indeed, the *.jar didn't work for me (running on raspberry pi) – bvdb May 16 '16 at 16:02
  • when tools that are supposed to make life easier for you actually cause more troubles... – Ahmadov Jul 22 '16 at 10:48
  • I just want to add that this does not work currently PowerShell, but works find in CommandPrompt... – Amnestic Jun 12 '17 at 14:06
  • 2
    It's a real shame both `-cp` and `-jar` are not available together. I have a CLI program that requires the user to supply a JDBC library to use it properly, and packaging it as an executable JAR file presents a challenge, here. – Christopher Schultz Jun 10 '18 at 18:16
66

Using java 1.7, on UNIX -

java -cp myjar.jar:lib/*:. mypackage.MyClass

On Windows you need to use ';' instead of ':' -

java -cp myjar.jar;lib/*;. mypackage.MyClass
jamp
  • 2,159
  • 1
  • 17
  • 28
  • pfew, I've been looking for this for 30 minutes now, trying to run an application on raspberry pi. Turns out I just needed to replace the `;` separator with `:`. Thanks :) – bvdb May 16 '16 at 15:44
  • Thank you. This worked for me. The windows version. – Coder17 Nov 19 '19 at 09:07
15

Let maven generate a batch file to start your application. This is the simplest way to this.

You can use the appassembler-maven-plugin for such purposes.

khmarbaise
  • 92,914
  • 28
  • 189
  • 235
  • When you use -jar, -cp is ignored. On the other hand, '-cp lib/*.jar' is the same as '-cp lib/dep1.jar;lib/dep2.jar...', I think from java1.5 – Michael Chen Dec 18 '13 at 19:01
12

Regardless of the OS the below command should work:

java -cp "MyJar.jar;lib/*" com.mainClass

Always use quotes and please take attention that lib/*.jar will not work.

AS Mackay
  • 2,831
  • 9
  • 19
  • 25
Hari
  • 121
  • 1
  • 3
3

You can use maven-assembly-plugin, Here is the example from the official site: https://maven.apache.org/plugins/maven-assembly-plugin/usage.html

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.5.1</version>
        <configuration>
            <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
            <archive>
                <manifest>
                    <mainClass>your main class</mainClass>
                </manifest>
            </archive>
        </configuration>
        <executions>
            <execution>
                <id>make-assembly</id> <!-- this is used for inheritance merges -->
                <phase>package</phase> <!-- bind to the packaging phase -->
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
andrewchan2022
  • 4,953
  • 45
  • 48
2

a possible solution could be

create a batch file

there do a loop on lib directory for all files inside it and set each file unside lib on classpath

then after that run the jar

source for loop in batch file for info on loops

Mukul Goel
  • 8,387
  • 6
  • 37
  • 77
1

There are several options.

The easiest is likely the exec plugin.

You can also generate a jar containing all the dependencies using the assembly plugin.

Lastly, you can generate a file with the classpath in it using the dependency:classpath goal.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
1

I was running into the same issue but was able to package all dependencies into my jar file using the Maven Shade Plugin

fjxx
  • 945
  • 10
  • 20
-2

This will not work java -cp lib\*.jar -jar myproject.jar. You have to put it jar by jar.

So in case of commons-codec-1.3.jar.

java -cp lib/commons-codec-1.3.jar;lib/next_jar.jar and so on.

The other solution might be putting all your jars to ext directory of your JRE. This is ok if you are using a standalone JRE. If you are using the same JRE for running more than one application I do not recommend doing it.

Jagger
  • 10,350
  • 9
  • 51
  • 93
  • 2
    Wildcard classpaths are available in JDK 6+, the issue instead is that you can't specify both `-jar` and `-cp` at the same time. Putting your jars in your ext directory, IMO, is a pretty horrible idea. – Dave Newton Oct 22 '12 at 19:15
  • @DaveNewton Yeah and this question is about executing a `jar` with its dependencies. – Jagger Oct 22 '12 at 19:16
  • Yeah and you can do that with a wildcard classpath. Filling your ext directory affects *everything* you run, and is dangerous if you ever run *anything* else. It's a Maven project; use Maven. – Dave Newton Oct 22 '12 at 19:18
  • @DaveNewton And how would you want to do it? Put the wildcard and then fully qualified name of the class which contains the `main` method? The whole idea of having an executable `jar` file is to avoid putting fully qualified name while executing and instead having it in the manifest file. – Jagger Oct 22 '12 at 19:21
  • That, or by creating a jar with all dependencies, as I stated. And again, just throwing a single project's dependencies into a JRE shared across anything run with that JRE is nuts. – Dave Newton Oct 22 '12 at 19:25
  • @DaveNewton Therefore my comment that if it is not a standalone JRE this is a bit cumbersome. I will rephrase it. – Jagger Oct 22 '12 at 19:29
  • 1
    If by "cumbersome" you mean "will likely break everything else in the world", sure. – Dave Newton Oct 22 '12 at 19:31