Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference jars inside a jar

I have a jar whose content looks as shown below,

enter image description here

Below is my manifest file

Manifest-Version: 1.0 Ant-Version: Apache Ant 1.8.3 Created-By: 1.7.0_06-b24 (Oracle Corporation) Main-Class: org.sai.com.DerbyDemo Class-Path: derby.jar derbyclient.jar derbynet.jar derbytools.jar 

When i try to run the jar, it has thrown a ClassNotFoundExcception meaning it isn't referencing the jars inside the outer jar.

In the Class-Path attribute, how can I reference jars (derby.jar, etc) inside the actual jar?

like image 819
srk Avatar asked Sep 10 '12 18:09

srk


People also ask

Can jar contain other JARs?

To load classes in JAR files within a JAR file into the class path, you must write custom code to load those classes. For example, if MyJar. jar contains another JAR file called MyUtils. jar, you cannot use the Class-Path header in MyJar.

What is an Uberjar?

An uber-JAR—also known as a fat JAR or JAR with dependencies—is a JAR file that contains not only a Java program, but embeds its dependencies as well. This means that the JAR functions as an “all-in-one” distribution of the software, without needing any other Java code.


2 Answers

You will need a custom class loader for this, have a look at One Jar.

One-JAR lets you package a Java application together with its dependency Jars into a single executable Jar file.

It has an ant task which can simplify the building of it as well.

REFERENCE (from background)

Most developers reasonably assume that putting a dependency Jar file into their own Jar file, and adding a Class-Path attribute to the META-INF/MANIFEST will do the trick:

 jarname.jar | /META-INF | |  MANIFEST.MF | |    Main-Class: com.mydomain.mypackage.Main | |    Class-Path: commons-logging.jar | /com/mydomain/mypackage | |  Main.class | commons-logging.jar 

Unfortunately this is does not work. The Java Launcher$AppClassLoader does not know how to load classes from a Jar inside a Jar with this kind of Class-Path. Trying to use jar:file:jarname.jar!/commons-logging.jar also leads down a dead-end. This approach will only work if you install (i.e. scatter) the supporting Jar files into the directory where the jarname.jar file is installed.

like image 161
epoch Avatar answered Oct 02 '22 12:10

epoch


You can't. From the official tutorial:

By using the Class-Path header in the manifest, you can avoid having to specify a long -classpath flag when invoking Java to run the your application.

Note: The Class-Path header points to classes or JAR files on the local network, not JAR files within the JAR file or classes accessible over internet protocols. To load classes in JAR files within a JAR file into the class path, you must write custom code to load those classes. For example, if MyJar.jar contains another JAR file called MyUtils.jar, you cannot use the Class-Path header in MyJar.jar's manifest to load classes in MyUtils.jar into the class path.

like image 36
JB Nizet Avatar answered Oct 02 '22 14:10

JB Nizet