views:

481

answers:

2

Is it possible to create a JAR file that requires external dependencies without including those dependencies in the JAR file?

My google-fu has failed to give me an answer; everything that I have found shows how to include them in the JAR file, but not what to put in the manifest file to say "I haven't got them, look in the user's classpath". I would assume that the dependencies are properly installed and configured on the user's classpath.

In my case, my dependencies are Apache Commons CLI and Math.


Edit: Inside my JAR file, I have Main.class.

My manifest file looks like:

Manifest-Version: 1.0
Created-By: 1.6.0 (Sun Microsystems Inc.)
Main-Class: Main

My CLASSPATH looks like

.;C:\Program Files\Java\jre1.6.0_06\lib\ext\QTJava.zip;C:\java_lib\commons-cli-1.2.jar;C:\java_lib\commons-math-2.0\commons-math-2.0.jar

If I include the dependencies in the JAR in /lib and add the line Class-Path: lib/commons-math-2.0.jar lib/commons-cli-1.2.jar to the manifest, then it does work.

I've tried adding Class-Path: commons-math-2.0.jar commons-cli-1.2.jar to the manifest without including the files in the JAR just to see if that would work, but it didn't.

+3  A: 

It certainly is possible. One way to think about it is that every time you create a jar, you are depending on the classes in the jre, and it is not necessary to include them in your jar. The jre will automatically look for them in the classpath. If they are not found you will see a NoClassDefFoundError.

akf
+1. Like akf says, you shouldn't have to do anything, as long as the user's classpath is correct. Putting entries in the manifest is just a way to add to the classpath.
Tim Yates
I can see that I shouldn't have to do anything, it's just that I can't get it to work! Oh well, in this particular case, it's only an additional ~130 kB, so I can live with including the libraries in the JAR...
masher
and you are identifying your dependencies on the java commandline in the classpath?
akf
I've tried `java -classpath c:\java_lib\commons-cli-1.2.jar;c:\java_lib\commons-math-2.0.jar -jar myjar.jar` as well as `java -jar myjar.jar` (due to the jars being in my CLASSPATH), and both end in a `NoClassDefinition` error.If I run the program before JARing it all up, it properly...
masher
+1  A: 

Use the Class-Path entry in the META-INF/MANIFEST.MF to tell where to look for dependencies relatively to your JAR. For example:

Class-Path: servlet.jar ../foo/bar.jar acme/beans.jar
Pascal Thivent
but I don't know where they are, except that they exist in the classpath of the user's computer.
masher
@masher Bundle everything in a zip so you have control of the location. Else, this is just not for you. Better just ask the user to set his class path manually in that case.
Pascal Thivent
@masher: If you don't know where they are you shouldn't list them at all but document that the user needs to put them in the classpath next to your jar.
Fredrik
@Fredrik @Pascal: I'm going to bundle them. Considering that I (the developer) can't get it to work, I can't expect my users to do it for me.
masher
@masher This makes sense IMHO and the manifest "trick" will definitely work then (and this is a nice transparent solution).
Pascal Thivent
@masher: I totally agree. It was just that the first comment sort of indicated that you didn't bundle them as you don't know about their locations (btw, did you consider a fatjar?).
Fredrik
@Fredrik I've had a quick look at that, and also at jarjar and one-jar. In this case, they would be overkill. But definitely on the cards if I get something more substantial.
masher