The Source for Java Technology Collaboration
User: Password:



Felipe Gaucho

Felipe Gaucho's Blog

Deliver Your Java Application in One-JAR!

Posted by felipegaucho on November 23, 2005 at 11:10 AM | Comments (17)

These days I'm finishing another course about Java and JDBC - everything was ok during the course and I decided to deploy the complete sample application to my students through their mailing list. The project is a simple Swing/JDBC application accessing a few tables in the MySql.

When I created the deployable JAR I detected a surprising detail: I can´t distribute my application in a single JAR because there is a dependency with the MySql - and the driver couldn't be accessed inside the application JAR due to classpath details.

This is a strange feature of the JAR tool because it force the users to download several files or use an external unzip tool in order to unzip the files before running the aplication - very odd.

I know we can use WebStart with its fantastic features - but I´m trying to distribute a simple application, it seems much more elegant if I got it packed in a only file.

There is an interesting project that inspired this entry, called One-JAR and a nice explanation about it usage on this site.

I opened a thread in the Java Programming Forum and the answers motivated me to share this curious gap about the JAR tool.


Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • Hi,
    Personnaly i don't think it's a good idea to distribute application library in a single package...

    Explanation :
    Like a Win32 software, your java app use external library, in win32 this library are DLL...

    And why it's impossible to pack dll in your exe (using win32 exemple) ?

    Because library need to be shared !!! it's one of root concept of POO : to not reinvent the wheel... If one day users install an other java app using mysql driver, if everybody pack all library in a single file, the MySql driver going to be stored in multiple places...

    Library need to be shared, it's why you can't pack all jar in one...

    And for me it's a good feature !

    Posted by: alois on November 24, 2005 at 12:40 AM

  • yep,

    from the point of view of developers, shared stuff is a great idea - it save a lot of repetitive downloads and also allow me to update the dependencies without checking all installed applications in my machine. Maven is a good example of such facility.

    But think about the final users - the ones who know nothing about computers but are trying to run my application. It is rude to expect those people to unzip things or deal with more than one file in order to open an application.

    I don´t think as One-JAR as a better or worst feature of the JAR tool, I just think it could be provided as an option. Perhaps a flag in the jartool, such as jar -single ...

    Posted by: felipegaucho on November 24, 2005 at 06:00 AM

  • felip, y to include jar in your jar?unzip the jar and then add it's contents 2 yr jar.i think this way you can have what u want.

    Posted by: dare_devil on November 24, 2005 at 08:01 AM

  • If you use maven to build your application you can use the UberJar plugin.

    Posted by: asrgomes on November 25, 2005 at 03:31 AM

  • It would be nice to be able to package libraries inside the jar-executable for simple applicatons, but this would also worse the problem of having lots of copies of the same libraries (for example, Jakarta-commons) because each app installs its own copy.

    Posted by: flozano on November 25, 2005 at 05:22 AM

  • We had a similar issue on the XUI project (http://xui.sf.net) when we needed to use native code (a win32 DLL) for an application distributed by several means and not just webstart.

    The solution we took was to package as a single jar and then extract and load the DLL using a class built into the jar (http://cvs.sourceforge.net/viewcvs.py/xui/xui/src/net/xoetrope/os/LibraryLoader.java?view=markup). I guess this technique could be applied to loading jars with the help of an AdaptiveClassLoader (from Apache Tomcat).

    Posted by: luano on November 25, 2005 at 05:26 AM

  • I actually had exactly the same problem yesterday for the first time. I found a single class-single jar application on the net which I wanted to expand to take cmd-line arguments. Because I was rushed, I used the Apache Common CLI library and then realised that I couldn't have a single executable jar file anymore (which *is* really nice: why should I require a directory, batch files/shortcuts just to run a small util?). So, I following task to my ant/netbeans script. It ain't pretty but it effectively unzips the common-cli jar and adds those classes to the distribution .jar file. I'd looked at the OneJar stuff but it was overkill in this case.


    <!-- Include the commons library jar file -->
    <target name="-post-jar">
    <jar destfile="${dist.jar}" manifest="${manifest.file}" update="true">
    <zipfileset src="${file.reference.commons-cli-1.0.jar}" includes="**/*.class"/>
    </jar>
    </target>

    Posted by: hopeless on November 25, 2005 at 06:37 AM

  • Hello!

    You have posted an iteresting topic: the jar file has been the fried to the Java(TM) desktop developer since it's inception.

    Please: if you have a moment, read the stated goals of JSR 277: Java Module System to see if it is addressing your needs.

    I am extremely curious to know what you think of it and if you think it would solve your problems in the exact use case you posted.

    Best regards in any case,
    Steven Coco

    Posted by: steevcoco on November 25, 2005 at 07:46 AM

  • I usualy distribute my programs in an .EXE , but you are right, a single JAR is often needed, an EXE is platform dependent, and Java was intended to be platform independent. See your problem.

    Posted by: bebben on November 25, 2005 at 12:28 PM

  • This is an excellent point Felipe. I've often wondered if Sun was ever consideirng an mean to lump together all of your application componnets into a single deployable unit similar to Apple’s application bundles. That could make life much easier.

    Ryan-

    Posted by: damnhandy on November 25, 2005 at 06:23 PM

  • Yes, that's the way it is. I personally use Maven's UberJar plugin. That's oneGoodReason++ to use Maven.

    Posted by: purvainais on November 27, 2005 at 12:58 AM

  • I package an application inside a zip file, with a jar for my app and libraries.
    The Manifest of the jar has a Classpath that points to the needed 3rd party
    jars in a lib dir.

    Users(windows) unzip and double click the jar. I gave up asking real nice
    for them to invoke a .bat or .sh, because they would not.

    With all of the overhead and a pile of gifs/jpgs etc, it's 28 MB but
    the process works without fail! and without lots of support calls.

    Sure would have liked to do this with webstart but ....

    Posted by: seapwc on November 28, 2005 at 02:55 PM

  • no worries, just unzip/unjar the mysql drivers and include the com folder or the org folder in your jar file, problem solve.

    Posted by: jmgtan on November 28, 2005 at 04:47 PM

  • I have had trouble with the Maven Uberjar plugin - it is very interesting the way it works, but it has failed for me in the past. With a good friend fo mine we wrote a simple Maven goal to unroll all of the dependencies in the project and roll them into a single jar. With Maven, this was easy to do, and works with all of our Maven based projects.

    Posted by: svetzal on November 28, 2005 at 05:05 PM

  • Felipe:

    Have you noticed this: This blog entry has 2 URLs:

    http://weblogs.java.net/blog/felipegaucho/archive/2005/11/deliver_your_ja.html

    and this one:

    http://weblogs.java.net/blog/felipegaucho/archive/2005/11/deliver_your_ja_1.html

    Wierd!!!

    Posted by: steevcoco on November 29, 2005 at 08:23 AM

  • If you use OSGI you can include native libraries in a bundle. You get a plugin infrastructure and a services framework along with that though. Might be an overkill for many scenarios. However in a OSGI bundle you can define libraries per OS and thus package your app with lets say 3 different native libs. No need to worry about setting a java.library.path and you can get it all packaged into a single jar too quite easily. Drawback is that the native attribute of bundle manifests is not documented on the web too well, but if i can figure it out, anyone can.

    This is a valid alternative which works right away and there is free osgi implementations you can deliver with your app.

    Just a suggestion. Regards, Stepan

    Posted by: stepanrutz on December 05, 2005 at 12:43 PM

  • I think my solution is similar to how 'XUI project' does handles this situation. (In fact, I probably have copied my code from them.)
    The purpose of the code is to extract a DLL from the JAR file that is later loaded to be called via JNI:


    DummyClass app = new DummyClass();
    Class cls = app.getClass();
    ProtectionDomain pDomain = cls.getProtectionDomain();
    CodeSource cSource = pDomain.getCodeSource();
    URL loc = cSource.getLocation();
    //System.out.println( "Loc:\t" + loc.toString() );
    //System.out.println( "Starting pathUpdate." );
    //System.setProperty( "java.library.path", System.getProperty( "java.library.path" ) + ";"
    // + loc.toString().replaceAll( "JTest.jar", "" ).replaceAll( "file:/", "" ).replaceAll( "%20", " " ).replaceAll( "/", "\\" ) );
    //System.out.println( "pathUpdated." );
    try {
    File outFile = new File( loc.toString().replaceAll( "JTest.jar", "JDDEClient.dll" ).replaceAll( "file:", "" ).replaceAll( "%20", " " ) );
    if ( !outFile.exists() ) {
    outFile.deleteOnExit();
    File inFile = new File( loc.toString().replaceAll( "file:", "" ).replaceAll( "%20", " " ) );
    FileOutputStream out = new FileOutputStream( outFile );
    JarFile jar = new JarFile( inFile );
    InputStream dllFile = jar.getInputStream( jar.getEntry( "JDDEClient.dll" ) );
    int c;
    while ( ( c = dllFile.read() ) != -1 ) {
    out.write( c );
    }
    out.close();
    dllFile.close();
    }
    } catch ( IOException e ) {
    e.printStackTrace();
    }

    Posted by: dunkthegeek on January 24, 2006 at 11:29 AM





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds