tags:

views:

250

answers:

1

My goal is have my ant build script build a war file and include the jars that ivy knows this project depends on. The best code I could come up with at the moment is the following

<mkdir dir="dist/lib"/>
<ivy:retrieve pattern="dist/lib/[artifact].[ext]" sync="true"/>
<war destfile="dist/${ivy.module}.war" basedir="build" includes="**/*.class"
    webxml="${war.webxml}">
    <fileset dir="${war.web}"/>
    <lib dir="dist/lib"/>
</war>

The problem with this code is it copies the jars twice. Once in to my dist/lib directory and again in to the war when it's created. It works but I can't shake the feeling there is a better way.

What I would like to do is something more like the following

<ivy:cachepath pathid="locpathref.classpath"/>
<war destfile="dist/${ivy.module}.war" basedir="build" includes="**/*.class"
    webxml="${war.webxml}">
    <fileset dir="${war.web}"/>
    <lib refid="locpathref.classpath"/>
</war>

The problem is that the lib tag does not take in a refid of any kind. Any ideas or am I stuck with an extra set of file copies?

+1  A: 

The problem here is that the lib tag is a custom fileset that targets it's files into the war archive's lib sub directory. It might be possible to write a custom war task but I don't think it's worth the effort.

If want to improve the manner in which ivy manages your war's dependencies might I suggest using configurations?

Create a configuration describing the run-time dependencies:

    <ivy-module version="2.0">
    <info organisation="apache" module="hello-ivy"/>
    <configurations>
        <conf name="build" description="Libraries needed to for compilation"/>
        <conf name="war" extends="build" description="Libraries that should be included in the war file" />
    </configurations>
    <dependencies>
        <dependency org="commons-lang" name="commons-lang" rev="2.0" conf="build->*,!sources,!javadoc"/>
        <dependency org="commons-cli" name="commons-cli" rev="1.0" conf="build->*,!sources,!javadoc"/>
    </dependencies>
</ivy-module>

Afterwards you retrieve them into a dedicated directory (using a pattern) which can be simply included using the war task's lib tag:

    <ivy:retrieve pattern="${lib.dir}/[conf]/[artifact].[ext]"/>

    <war destfile="${war.file}" webxml="${resources.dir}/web.xml">
        <fileset dir="${resources.dir}" excludes="web.xml"/>
        <lib dir="${lib.dir}/war"/>
    </war>

The advantage of this approach is that you use the ivy conf attribute of each project dependency to ultimately decide if the jar gets included within the war file or not. The build file no longer cares.

In conclusion I understand that the point of your post was concern for multiple copies of your jar files... Using my suggested approach will further multiple your copies, but I would submit that this is not an issue provided you have a clean target to remove them afterwards.

Mark O'Connor
I agree that this is a better solution then what I am doing but it still does not remove the extra file copy as I would like. The more I look at this the more I think that, as you said, the only real way to fix is by creating a custom war task or even a new custom lib task for the war task. In a perfect world this new task could would day become part of Ivy or Ant.
AmaDaden
The solution you want is to use the ivy cachefileset task instead of cachepath. Then the refid parameter to the warfile's lib tag will work as expected
Mark O'Connor