How to use ivy to build a war with out copying jar

2019-03-11 10:08发布

问题:

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:

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.



回答2:

If you're using Ant 1.8, you can use the technique described here: http://www.beilers.com/2010/06/ivy-dependency-management-lessons-learned-and-ant-1-8-mapped-resources/

EXAMPLE:

<war destfile="${war.full.path}" webxml="WebContent/WEB-INF/web.xml" manifest="${manifest.path}">
    <fileset dir="WebContent">
     </fileset>
    <classes dir="${build.dir}"/>

    <mappedresources>
      <restrict>
        <path refid="classpath.CORE"/>
        <type type="file"/>
      </restrict>
      <chainedmapper>
        <flattenmapper/>
        <globmapper from="*" to="WEB-INF/lib/*"/>
      </chainedmapper>
    </mappedresources>

    <zipfileset dir="src" prefix="WEB-INF/classes">
         <include name="**/resources/**/*.properties" />
         <include name="**/resources/**/*.xml" />
    </zipfileset>
</war>


标签: ant ivy