tags:

views:

4322

answers:

8

I have runtime dependencies on some external jars that I would like to "rejar" into a single jar. These external dependencies are stored in a external_jars directory, and I'd like to be able to not have to list each one out (e.g., to not need to change my build scripts if my dependencies change). Any thoughts?

Google gave me a good answer on how to do this if you don't mind listing out each jar you want as a dependency:

http://markmail.org/message/zijbwm46maxzzoo5

Roughly, I want something along the lines of the following, which would combine all jars in lib into out.jar (with some sane overwrite rules).

jar -combine -out out.jar -in lib/*.jar

+10  A: 

You could check out jarjar:

http://code.google.com/p/jarjar/

Staale
three minutes to perfect answer = <3 stackoverflow
Jacob
doh! I looked into this. It has a lot of advanced functionality that it turns out I don't need. What it is missing (at least from docs on the site) is an easy way to do something like:jar -combine -out out.jar -in lib/*.jarwhich is what I need
Jacob
jar jar jar it works
Mario Ortegón
+1  A: 

Where ever you need to include those jars simple use wildcard path like external_jars/.

Why you want to put all the jars into one jar file?

Bhushan
+1  A: 

Try extracting your JAR's to a marshalling directory first:

<target name="combine-jars">
    <mkdir dir="${marshall.dir}"/>
    <unzip dest="${marshall.dir}">
        <fileset dir="${external.jar.dir}">
            <include name="**/*.jar"/>
        </fileset>
    </unzip>
    <jar destfile="${combined.jar}" basedir="${marshall.dir"}>
    <delete dir="${marshall.dir}"/>
</target>

Where ${marshall.dir} is a temporary directory, ${external.jar.dir} is where you keep the JAR's, and ${combined.jar} is the target JAR.

David Grant
The previous examples will include the other jars -as jar!- in the jar file. This one, on the other hand , will first deflate all the jars to *.class files , and then create one jar from all the class files.
yossale
A: 

Have you considered using Maven or some other system which manages your dependencies automatically? Then you would not need to specify where each library is located, what their names are, and what transitive dependencies your direct dependencies have. You would just state in one place what the dependency and its version are, and the system would take care of downloading the libraries, configuring the classpath and building the project.

Esko Luontola
+14  A: 

Just use zipgroupfileset with the Ant Zip task

<zip destfile="out.jar">
    <zipgroupfileset dir="lib" includes="*.jar"/>
</zip>

This will flatten all included jar libraries' content.

Vladimir
Sorry to hijack someone else's question. I did this but now I can get my application to run. It can't find some of the classes. Do I still need to sepcifiy the classpath like java -cp xxx -jar yyy.jar?
uriDium
+5  A: 

Vladimir's answer is a correct one, but I feel that what he suggests implies repacking all jars in a one big out.jar, which is then feeded to Ant Jar task as a single <zipfileset> or something like that. This two-step approach is unnecessary. I'm not sure whether this is connected with Ant version, but I have Ant 1.7.1, and its <jar> task understands <zipgroupfileset>, which allows to feed all contents of third party jars' directly.

<jar destfile="MyApplication.jar">
  <zipgroupfileset dir="lib" includes="*.jar" /> 
  <!-- other options -->
  <manifest>
    <attribute name="Main-Class" value="Main.MainClass" />
  </manifest>
</jar>
nightingale
A: 

Well, I am not so much in to programming - but something simpler worked for me...if the question meant - combining jar files in to one. Ofcourse, this is manual, dirty solution. I just untarred all the tars...and then..created a new tar file, by adding all the directories formed by untarring- in to the new tar file. it worked.

Sowmya
A: 

Maven or other build tools can't "manage" the resolution of multiple versions of class files. In fact, Maven causes these problems in the first place, through transitive inclusion of all downstream jar files that are not explicitly required by a project.

Suppose somewhere in the transitive closure of a project (all libraries and modules required by the project, and all it's dependent projects, recursively) there are two versions of a class file. How could Maven possibly know which one is the 'correct' one? which one was intended by the programmer?

It can't because this information was lost when explicit dependencies were thrown away in favor of transitive ones (to save XML typing).

hans anderson