views:

399

answers:

1

Hi,

I'm trying to compile a runnable jar-file for a project that makes use of hibernate. I'm trying to construct an ant build.xml file to streamline my build process, but I'm having troubles with the inclusion of the hibernate3.jar inside the final jar-file.

If I run the ant script I manage to include all my library jars, and they are put in the final jar-file's root. When I run the jar-file I get a

java.lang.NoClassDefFoundError: org/hibernate/Session 

error. If I make use of the built-in export to jar in Eclipse, it works only if I choose "extract required libraries into jar". But that bloats the jar, and includes too much of my project (i.e. unit tests).

Below is my generated manifest:

Manifest-Version: 1.0
Main-Class: main.ServerImpl
Class-Path: ./ antlr-2.7.6.jar commons-collections-3.1.jar dom4j-1.6.1.jar
hibernate3.jar javassist-3.9.0.GA.jar jta-1.1.jar slf4j-api-1.5.11.jar 
slf4j-simple-1.5.11.jar mysql-connector-java-5.1.12-bin.jar rmiio-2.0.2.jar 
commons-logging-1.1.1.jar

And the part of the build.xml looks like this:

<target name="dist" depends="compile" description="Generates the Distribution Jar(s)">
    <mkdir dir="${dist.dir}" />
    <jar destfile="${dist.dir}/${dist.file.name}.jar" basedir="${build.prod.dir}" filesetmanifest="mergewithoutmain">
        <manifest>
            <attribute name="Main-Class" value="${main.class}" />
            <attribute name="Class-Path" value="./ ${manifest.classpath} " />
            <attribute name="Implementation-Title" value="${app.name}" />
            <attribute name="Implementation-Version" value="${app.version}" />
            <attribute name="Implementation-Vendor" value="${app.vendor}" />
        </manifest>
        <zipfileset refid="hibernatefiles" />
        <zipfileset refid="slf4jfiles" />
        <zipfileset refid="mysqlfiles" />
        <zipfileset refid="commonsloggingfiles" />
        <zipfileset refid="rmiiofiles" />
    </jar>
</target>

The refids' for the zipfilesets point to the directories in a library directory lib in the root of the project. The manifest.classpath-variable takes the classpath of all those library jar-files, and flattens them with pathconvert and mapper.

I've also tried to set the manifest classpath to ".", "./" and only the library jar, but to no difference at all. I'm hoping there's a simple remedy to my problems...

+1  A: 

Since you can't specify jar-inside-jar in your classpath, this way won't work. You need either to jar only your code and then zip your jar with libs jars and launch script, like

#!/bin/sh
java -cp ./hibernate.jar:./mycode.jar... my.Main

(this what most people do), or you may unpack all your lib jars to the same dir which contains your compiled classes and then jar result dir back to single jar file (this what maven jar-with-dependencies packaging do).

Victor Sorokin
Thank you for the clarification. I went with the option to unpack all the lib jars into my build-dir and repack all classes together with the project-classes. I used zipfileset: <zipfileset src="lib.jar" includes="**/*.class" />, but is there an easier way to include several jar-files in a directory rather than having to call a zipfileset for each and every jar-file I want to include?
Patrick
you always can write sh script which will do something like 'jar xf *jar; jar cf my-app-with-libs.jar *'.Still, I would recommend 1st approach -- zip which will be auto-unpacked and launched by accompanying shell script. Using 2nd approach you must take care of classes with same FQCN from different libs, if any.
Victor Sorokin
Ok, thanks a lot for the help. I actually went with the option to point the manifest classpath to an accompanying lib subfolder where I copied all necessary jar-files, and it works great now.
Patrick