Is there any Ant feature, that copies classpath dependencies to WEB-INF/lib?

≡放荡痞女 提交于 2019-12-12 05:52:06

问题


I can't affect the procedure of copying classpath dependencies to WEB-INF/lib category: there is no special ANT task that copies those jars (at least, i cant find any 'copy' task with related "WEB-INF/lib" string as PATH argument), but they appeared after project building. How to affect this procedure? Basically, i need to exclude JAXB jars to avoid dependency conflict. At the same time i need this jars at compile-time, so i can't remove them. Maybe, it is easier to erase those jars manually, using 'delete' task?


回答1:


What your struggling with is multiple classpath management. In a typical build there are at least 4 types of classpath:

  • compile: Classes that your code directly invokes
  • runtime: Classes that your code indirectly invokes via other classes
  • provided: Classes that you need to compile against, but whose implementation will be provided by the target platform
  • test: Additional classes (like junit) that are needed when you're testing code but which are not shipped with your final application

It was the Maven build tool which formally identified these common classpaths and provided a dependency management system for resolving and populating classpaths during the build process.

The bad news is that ANT pre-dates Maven and therefore leaves classpath management completely up to the programmer.... Typically this is done by putting jars into different directories or using complicated filesets within your build logic.

The good news is that there is an ANT plugin called ivy which performs Maven-like dependency management. It's worth learning, especially, if you program a lot with open source libraries (which increasingly use Maven now).

Example (without ivy)

The files which make up the individual classpaths must be managed at the top of the build. Obviously the files must be separately downloaded into the "lib" directory. As the number of files increases this approach becomes unwieldy.

<project name="demo" default="build">

    <!-- 
    ================
    File collections 
    ================
    -->
    <fileset dir="lib" id="compile.files">
        <include name="*.jar"/>
        <exclude name="slf4j-log4j12.jar"/>
        <exclude name="log4j.jar"/>
        <exclude name="junit.jar"/>
        <exclude name="hamcrest-core.jar"/>
    </fileset>

    <fileset dir="lib" id="runtime.files">
        <include name="*.jar"/>
        <exclude name="junit.jar"/>
        <exclude name="hamcrest-core.jar"/>
    </fileset>

    <fileset dir="lib" id="test.files">
        <include name="*.jar"/>
    </fileset>

    <!--
    ===============
    Compile targets
    ===============
    -->
    ..
    ..

    <target name="compile" depends="init,resolve, resources" description="Compile code">
        <mkdir dir="${classes.dir}"/>
        <javac srcdir="${src.dir}" destdir="${classes.dir}" includeantruntime="false" debug="true">
            <classpath>
                <fileset refid="compile.files"/>
            </classpath>
        </javac>
    </target>

    <!--
    ===============
    Distribution targets
    ===============
    -->
    ..
    ..

    <target name="package" depends="test" description="Create the WAR file">
        <copy todir="build/lib">
            <fileset refid="runtime.files"/>
        </copy>

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

Example (Using ivy)

Very high level introduction to ivy and it's tasks. See the "retrieve" ivy task below which delivers the functionality you're looking for.

build.xml

<project name="demo" default="build" xmlns:ivy="antlib:org.apache.ivy.ant">

    <!--
    ===========
    Build setup
    ===========
    -->
    <target name="bootstrap" description="Install ivy">
        <mkdir dir="${user.home}/.ant/lib"/>
        <get src="http://search.maven.org/remotecontent?filepath=org/apache/ivy/ivy/2.2.0/ivy-2.2.0.jar"
             dest="${user.home}/.ant/lib/ivy.jar"/>
    </target>

    <!--
    ============================
    Resolve project dependencies
    ============================
    -->
    <target name="resolve" description="Use ivy to resolve classpaths">
        <ivy:resolve/>

        <ivy:report todir='${ivy.reports.dir}' graph='false' xml='false'/>

        <ivy:cachepath pathid="compile.path" conf="compile"/>
        <ivy:cachepath pathid="runtime.path" conf="runtime"/>
        <ivy:cachepath pathid="test.path"    conf="test"/>
    </target>

    <!--
    ===============
    Compile targets
    ===============
    -->
    ..
    ..

    <target name="compile" depends="init,resolve, resources" description="Compile code">
        <mkdir dir="${classes.dir}"/>
        <javac srcdir="${src.dir}" destdir="${classes.dir}" includeantruntime="false" debug="true" classpathref="compile.path"/>
    </target>

    <!--
    ===============
    Distribution targets
    ===============
    -->
    ..
    ..

    <target name="package" depends="test" description="Create the WAR file">
        <ivy:retrieve pattern="${build.dir}/lib/[artifact].[ext]" conf="runtime"/>

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

Notes

  • The "bootstrap" target is designed to install ivy (It's not packaged with ANT core)
  • The "cachepath" task is used to create custom ANT paths
  • The "retrieve" task populates the WAR file's WEB-INF/lib directory with the jars needed at runtime (managed by ivy configuration)

ivy.xml

This file lists your project's dependencies. It uses configurations to logically group jars together and enables the ivy "cachpath" task to create matching classpaths within your build. Finally the 3rd party jars are downloaded and cached during the build process. This is very convenient and it means you can reduce the size of your project.

<ivy-module version="2.0">
    <info organisation="com.myspotontheweb" module="demo"/>

    <configurations>
        <conf name="compile" description="Required to compile application"/>
        <conf name="runtime" description="Additional run-time dependencies" extends="compile"/>
        <conf name="test"    description="Required for test only" extends="runtime"/>
    </configurations>

    <dependencies>
        <!-- compile dependencies -->
        <dependency org="org.slf4j" name="slf4j-api" rev="1.7.2" conf="compile->default"/>

        <!-- runtime dependencies -->
        <dependency org="org.slf4j" name="slf4j-log4j12" rev="1.7.2" conf="runtime->default"/>

        <!-- test dependencies -->
        <dependency org="junit" name="junit" rev="4.10" conf="test->default"/>
    </dependencies>

</ivy-module>


来源:https://stackoverflow.com/questions/14029777/is-there-any-ant-feature-that-copies-classpath-dependencies-to-web-inf-lib

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!