mauryat
mauryat

Reputation: 1646

How to run a jar which contains dependency libraries within it?

I have a Maven generated jar which contains all the dependency jars within it in a directory called lib.

app-0.0.1-SNAPSHOT.jar
|_ lib/
|_ app.properties
|_ app/
|_ spring/

However, when I run it from the command line using:

java -jar app-0.0.1-SNAPSHOT.jar

it complains that it can't find slf4j (which in fact is included in the directory lib). Basically, it is not able to recognize the lib directory.

This jar has been created using the maven-dependency-plugin and the maven-jar-plugin as per this solution. As the solution suggests, a custom classloading code to load the jars is necessary. I'm wondering what this class loading code should look like.

Manifest.mf

Manifest-Version: 1.0
Built-By: me
Build-Jdk: 1.6.0_26
Class-Path: lib/camel-core-2.6.0.jar lib/commons-logging-api-1.1.jar ...
Created-By: Apache Maven 3.1.1
Main-Class: app.Main
Archiver-Version: Plexus Archiver

Upvotes: 0

Views: 561

Answers (1)

Ryan J
Ryan J

Reputation: 8323

It might be easier to show this in an answer, rather than extensive commenting...

You have two options for accomplishing what you want:

  1. Create a single jar file that packages all dependencies within
  2. Create a standalone jar that only contains the resources and classes of the artifact, but no dependencies. The dependent jars are placed in some directory, alongside the jar.

To do #1, you can use the maven-assembly-plugin to build a jar file, with all dependencies, using the following in your POM:

<plugin>
     <artifactId>maven-assembly-plugin</artifactId>
     <configuration>
          <descriptorRefs>
               <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
               <manifest>
                    <mainClass>${main.class}</mainClass>
               </manifest>
          </archive>
     </configuration>
     <executions>
          <execution>
               <phase>package</phase>
               <goals>
                    <goal>single</goal>
               </goals>
          </execution>
     </executions>
</plugin>

The manifest packed in this jar looks like this:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: <username>
Build-Jdk: 1.7.0_60
Main-Class: your.main.Class

With this solution, there's no need to have a bunch of jars on your classpath because they are already in the jar, in their proper package location (in .class format)

If you go with #2, the solution should provide you something like this (assuming you have all dependencies in a directory called lib in your target directory

your.artifact.jar
lib
  |-- dependent jars...

And your manifest for your jar would have:

Manifest-Version: 1.0
Built-By: me
Build-Jdk: 1.6.0_26
Class-Path: lib/camel-core-2.6.0.jar lib/commons-logging-api-1.1.jar ...
Created-By: Apache Maven 3.1.1
Main-Class: app.Main
Archiver-Version: Plexus Archiver

Note that the lib directory is not packed in your jar, but alongside it (ie, you distribute them together, yourself)

Upvotes: 1

Related Questions