tags:

views:

475

answers:

6

Ok so i wrote a program that makes use of a 3rd party open source library and i want to package it with my program in a single jar. I'm using netbeans 6.8 and everything I've tried java always spit back the error:

java.lang.NoClassDefFoundError: libraryname;

off topic:also i would like to know how to make an executable-jar(exe) through netbeans if it is possible. (ive seen programs that were written in java but were an .exe)

EDIT discovered a plugin for eclipse called FatJar which can do what i want, but i cant find something similar for netbeans, is there such thing?

+1  A: 

To include another jar in your jar, you might find jarjar useful.

Executable jars just have a class defined as 'Main', if I'm not mistaken. This may be useful.

Conrad Meyer
the information on how to use jarjar is not clear on how to accomplish this task. I also see that other users on google code are having problems with jarjars lack of example/documentation. Can you explain how to do this with jarjar?
Dacto
A: 

If there are no licencing issues then the most preffered way is to unjar the actual jar and rejar it with your class files in it, to a new jar.

You can simply use the jar cmd itself for this, no big deal!!

Suraj Chandran
how do i accomplish this? I know i can just extract the contents, but then im lost...
Dacto
I disagree. It is (maybe) simple for the developer, but it is an impediment to users who need to replace the third-party library with a different version. That is why a lot of open source licenses discourage / restrict / forbid this kind of embedding!!
Stephen C
Ok then im back to the original place :)
Dacto
@Dacto - I'm talking about the practice of unjaring the 3rd party jars and mixing their contents with your application classes. By contrast, simply embedding the 3rd party jars in your jar is more kosher.
Stephen C
Yea i know what you ment, I am oblivious to the embedding the 3rd party jar and still have my program function as it should.
Dacto
@stephen...that's why my answer started with "If there are no licencing issues..." :). For the other point, I think this is not the job of end user but the job of product integeration team, if they have one that is :)
Suraj Chandran
A: 

I realize that this doesn't achieve exactly what you want, but I'll describe the customary method of distributing a standalone application. If it does meet your needs, you'll find that it's better supported by tools and more readily understood by users, because it follows established conventions.

Put your code in a jar (I'll call it app.jar) along with a META-INF/MANIFEST.MF file with entries like this:

Main-Class: com.y.app.AppMain
Class-path: third-party.jar blort.jar foo.jar

Then, you can throw all of the jars into a directory and run AppMain like this:

java -jar app.jar

If you want, you can put the third-party libraries in a single directory like lib and refer to them in the Class-path attribute using a path relative to the main jar: lib/third-party.jar That helps keep your distribution tidy.

erickson
yes, this is the structure that i currently have, i would like to embed the library into my main jar
Dacto
A: 

If there's not any concern of repackaging 3rd party jars into your final big jar, then this should be the easiest method.

bryantsai
+2  A: 

My generic answer to your off-topic question is a (rather lengthy) article: Convert Java to EXE - Why, When, When Not and How. It has lots of links to free and commercial tools, but I have never seen a Netbeans plugin with such functionality, sorry.

Dmitry Leskov
Hmm thanks, this answers my off-topic :) thank you!
Dacto
+2  A: 

I'll start off with the obligatory disclaimer: Java executable JARs do not work this way. An executable JAR has a main class defined in the JAR's MANIFEST.MF file, and the MANIFEST also allows the definition of a class path to include libraries that the code in the executable JAR will need. The class path definition in the MANIFEST must enumerate every JAR or folder to put on the class path, relative paths are relative to the location of the executable JAR - not to paths contained inside the executable JAR. Executable JARs are launched with the "-jar" argument to the java executable, and both the java "-cp" flag and the CLASSPATH environment variable are ignored. As for why executable JARs were designed this way, you should be aware of the primary disadvantage of loading classes from JARs contained within JARs, even though the rest of this reply will focus on doing just that.

NOTE: I lost the original sun forum topic that explained it fully, but essentially it is because entries in the top level JAR can be read in a random access manner, but the entire embedded JAR must be read before any entries can be accessed, because the top level JAR might have compressed its entries.

I have used One-Jar successfully in the past, but the structure of the final resulting jar may not be what you expect. Essentially the One-Jar classes are the only non-JARd classes in the final jar; all other code (your code and any dependent library code) is included in the resulting as JAR as JAR files. Your application is JARed as a regular JAR file named "main.jar" in the final JAR's "main" folder. Any libraries your code needs is placed, as JAR files, in the final JAR's "lib" folder. And last but not least the final JAR's MANIFEST.MF file tells One-Jar what your main class is. Execution is a dead simple "java -jar final.jar [args your app uses]". I don't know how to take the next step of converting to an OS-native EXE regarding your off-topic question, but it would probably be best to use a different packaging mechanism than One-Jar anyway. I'm not sure how to go about this with NetBeans, my advice there is to use a build tool to package the final jar. Fortunately One-Jar provides instructions on generating the final jar with Ant, and that should be easily integratable into NetBeans.

I believe the Eclipse FatJar plugin creates a One-Jar executable JAR, so if that plugin seems to do what you want, then One-Jar is the way to do it. Personally, I used a Maven assembly.

There is a caveat - any signed libraries that require (or desire) to take advantage of Java's signed JAR verification may not work this way - Java Cryptographic Extension (JCE) implementations like BouncyCastle are a notable example. I think the reason is that the signature verification runs against the final JAR, not the signed library. Fortunately One-Jar allows the end user to add additional libraries to the classpath, something that is explicitly precluded when running an executable JAR; to workaround this you might be better off delivering the problematic JARs with the final JAR and an OS dependent launch script (.bat, .sh, etc).

beltorak
One-jar is indeed the best way I've seen to pursue this ill-advised course ;) +1
erickson