tags:

views:

2529

answers:

5

I am trying to rearchitect my build technique for creating Java jar files which depend on common 3rd party jar files. (GlazedLists, Apache Commons, etc.)

I had been chucking them all into {Java JRE dir}/lib/ext so they would automatically be seen by the JRE, but that led to problems like not remembering that I need to distribute certain jar files, so I'd like to learn to be more explicit.

So I moved them all into c:\appl\java\common\, added them to the Eclipse build path, aand defined this in my ant file:

I have my Class-Path manifest header set to "." in my jar task but that doesn't seem to work even if I put the relevant jar files into the same directory as my application jar file. I can add them all manually one-by-one to the Class-Path header, but I'm wondering, is there an easier way to get the Class-Path header setup properly?

A: 

Classpath directories do not, by default, include Jar files for security reasons. Someone could place a jar file in there, and it could be loaded up, overriding your code, without your knowledge. I do know that there was discussion about adding another flag or ending token to allow Jar files to be added to the classpath, but, if my memory serves, that is slated for version 7. However, I could be wrong on the last part.

aperkins
A: 

The Class-Path manifest header for jar files requires you to explicitly list the jar files you want to include. Listing a directory in the classpath means java will look for .class files in that directory, not jarfiles.

+2  A: 

What you want is a mapper. Flattenmapper is probably the easiest, but essentially you need to create a path element which specifies your classpath, then use a pathconvert on it to turn it into a string that can be included in your manifest.

Edit: you can use include rules to build the path element, so everything in a directory ending with jar would be **/*.jar

Tim Bender
A: 

Since you're in Ant, you probably don't want to switch, but Maven is pretty good at identifying all your dependencies, and has several facilities for copying or combining your lib jars together for distribution purposes. For my purposes I have a Maven plugin that creates a run script during build, which in turn sets the classpath for me so I don't need to worry about it.

toluju
Ivy is a pretty ant-compatible way to do dependency management.
Jeff Walker
+4  A: 

This is all you need:

 <path id="build-classpath">
  <fileset dir="${dist}/lib">
   <include name="*.jar"/>
  </fileset>
 </path>
 <manifestclasspath property="lib.list" jarfile="${dist}/lib/myprog.jar">
  <classpath refid="build-classpath"/>
 </manifestclasspath>
     <jar jarfile="${dist}/lib/myprog.jar" basedir="${build}" includes="com/my/prog/**" >
  <manifest>
   <attribute name="Main-Class" value="com.my.prog.MyProg"/>
   <attribute name="Class-Path" value="${lib.list}"/>
  </manifest>
 </jar>

As you can probably see, it assumes you've compiled your Java classes and output them to ${build}. It also assumes you've copied your jarfiles to ${dist}/lib.

rob
ahhhh... that's what I was looking for. Excellent!
Jason S
Hmmm. Correction: it doesn't work for a fresh build, because the ${dist}/lib dir may not exist yet. Is there a way to delay the execution of the <path> task?
Jason S
DOH! never mind, I had put the <path> and <manifestclasspath> in the root section of my ant file, just fixed it by putting it into the jar task. thanks again!!!!!
Jason S
No problem; glad I could help!
rob