I decided to take a stab at finding out how hard it would be to integrate Ivy with a GWT Ant build.

Generate Project

I started out by generating the GWT application with webAppCreator.

C:/Programs/gwt-2.0.0-ms1/webAppCreator com.mostlyblather.IvyGwt

Create Ivy Configuration

Next I created the ivy.xml file. After playing around with a couple of different configurations, I settled on this one. Any future libraries added to the project would be either assigned to “compile” or “runtime” configurations. The “compile” runtime would include things like 3rd party GWT libraries. The “runtime” configuration would be used for dependencies executed in the Servlet container.


ivy.xml file:


<ivy-module version="2.0">
<info organisation="com.mostlyblather" module="ivygwt"/>
<configurations>
<conf name="runtime" description="needed in servlet container"/>
<conf name="compile" description="needed for compilation (other GWT libraries)"/>
<conf name="sdk" description="GWT SDK (compile time, seperated for Eclipse GWT IDE Integration)"/>
</configurations>
<dependencies>
<dependency org="com.google.gwt" name="gwt-servlet" rev="2.0.0-ms1" conf="runtime->default"/>
<dependency org="com.google.gwt" name="gwt-user" rev="2.0.0-ms1" conf="sdk->default"/>
<dependency org="com.google.gwt" name="gwt-dev" rev="2.0.0-ms1" conf="sdk->default"/>
</dependencies>
</ivy-module>

Modify Ant Build

In order to use the Ivy resolved dependencies, several modifications to build.xml need to be made.

First an automatic ivy installation code section.


<property name="ivy.install.version" value="2.1.0" />
<condition property="ivy.home" value="${env.IVY_HOME}">
<isset property="env.IVY_HOME" />
</condition>
<property name="ivy.home" value="${user.home}/.ant" />
<property name="ivy.jar.dir" value="${ivy.home}/lib" />
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />

<target name="download-ivy" unless="offline">
<mkdir dir="${ivy.jar.dir}"/>
<!-- download Ivy from web site so that it can be used even without any special installation -->
<get src="http://repo2.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
dest="${ivy.jar.file}" usetimestamp="true"/>
</target>

<target name="init-ivy" depends="download-ivy">
<!-- try to load ivy here from ivy home, in case the user has not already dropped
it into ant's lib dir (note that the latter copy will always take precedence).
We will not fail as long as local lib dir exists (it may be empty) and
ivy is in at least one of ant's lib dir or the local lib dir. -->
<path id="ivy.lib.path">
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
</target>
Next, add ivy to the build.xml xml namespace.


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



Create a new target named “resolve” to actually fetch the needed jars.

  
<target name="resolve" depends="init-ivy" description="retrieve dependencies with ivy">
<ivy:retrieve pattern="${ivy.lib.dir}/[conf]/[artifact].[ext]"/>
</target>


Additionally create a “resolve” target dependency to the “libs” target.

    
<target name="libs" depends="resolve" description="Copy libs to WEB-INF/lib">


The property definition “gwt.sdk” is no longer required so it can be removed.

The “project.class.path” property has to be changed to pick up the new Ivy provided jars.

 
<path id="project.class.path">
<pathelement location="war/WEB-INF/classes"/>
<fileset dir="lib/compile" includes="**/*.jar"/>
<fileset dir="lib/sdk" includes="**/*.jar"/>
</path>


Target “libs” similarly needs to be updated. Notice that it is only picking up the “runtime” configuration.

 
<target name="libs" depends="resolve" description="Copy libs to WEB-INF/lib">
<mkdir dir="war/WEB-INF/lib" />
<copy todir="war/WEB-INF/lib" >
<fileset dir="lib/runtime" includes="**/*.jar"/>
</copy>
</target>


The “clean” target has some additional work to do now.

 
<target name="clean" description="Cleans this project">
<delete dir="war/WEB-INF/classes" failonerror="false" />
<delete dir="war/WEB-INF/lib" failonerror="false" />
<delete dir="war/ivygwt" failonerror="false" />
<delete dir="lib" failonerror="false" />
</target>


Here is the final build.xml

 
<?xml version="1.0" encoding="utf-8" ?>
<project name="IvyGwt" xmlns:ivy="antlib:org.apache.ivy.ant" default="build" basedir=".">

<path id="project.class.path">
<pathelement location="war/WEB-INF/classes"/>
<fileset dir="lib/compile" includes="**/*.jar"/>
<fileset dir="lib/sdk" includes="**/*.jar"/>
</path>

<property name="ivy.install.version" value="2.1.0" />
<condition property="ivy.home" value="${env.IVY_HOME}">
<isset property="env.IVY_HOME" />
</condition>
<property name="ivy.home" value="${user.home}/.ant" />
<property name="ivy.jar.dir" value="${ivy.home}/lib" />
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />

<target name="download-ivy" unless="offline">
<mkdir dir="${ivy.jar.dir}"/>
<!-- download Ivy from web site so that it can be used even without any special installation -->
<get src="http://repo2.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
dest="${ivy.jar.file}" usetimestamp="true"/>
</target>

<target name="init-ivy" depends="download-ivy">
<!-- try to load ivy here from ivy home, in case the user has not already dropped
it into ant's lib dir (note that the latter copy will always take precedence).
We will not fail as long as local lib dir exists (it may be empty) and
ivy is in at least one of ant's lib dir or the local lib dir. -->
<path id="ivy.lib.path">
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
</target>

<target name="resolve" depends="init-ivy" description="retrieve dependencies with ivy">
<mkdir dir="lib/runtime" />
<mkdir dir="lib/compile" />
<mkdir dir="lib/sdk" />
<ivy:retrieve pattern="${ivy.lib.dir}/[conf]/[artifact].[ext]"/>
</target>

<target name="libs" depends="resolve" description="Copy libs to WEB-INF/lib">
<mkdir dir="war/WEB-INF/lib" />
<copy todir="war/WEB-INF/lib" >
<fileset dir="lib/runtime" includes="**/*.jar"/>
</copy>
</target>

<target name="javac" depends="libs" description="Compile java source">
<mkdir dir="war/WEB-INF/classes"/>
<javac srcdir="src" includes="**" encoding="utf-8"
destdir="war/WEB-INF/classes"
source="1.5" target="1.5" nowarn="true"
debug="true" debuglevel="lines,vars,source">
<classpath refid="project.class.path"/>
</javac>
<copy todir="war/WEB-INF/classes">
<fileset dir="src" excludes="**/*.java"/>
</copy>
</target>

<target name="gwtc" depends="javac" description="GWT compile to JavaScript">
<java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler">
<classpath>
<pathelement location="src"/>
<path refid="project.class.path"/>
</classpath>
<!-- add jvmarg -Xss16M or similar if you see a StackOverflowError -->
<jvmarg value="-Xmx256M"/>
<!-- Additional arguments like -style PRETTY or -logLevel DEBUG -->
<arg value="com.mostlyblather.IvyGwt"/>
</java>
</target>

<target name="hosted" depends="javac" description="Run hosted mode">
<java failonerror="true" fork="true" classname="com.google.gwt.dev.HostedMode">
<classpath>
<pathelement location="src"/>
<path refid="project.class.path"/>
</classpath>
<jvmarg value="-Xmx256M"/>
<arg value="-startupUrl"/>
<arg value="IvyGwt.html"/>
<!-- Additional arguments like -style PRETTY or -logLevel DEBUG -->
<arg value="com.mostlyblather.IvyGwt"/>
</java>
</target>

<target name="build" depends="gwtc" description="Build this project" />

<target name="war" depends="build" description="Create a war file">
<zip destfile="IvyGwt.war" basedir="war"/>
</target>

<target name="clean" description="Cleans this project">
<delete dir="war/WEB-INF/classes" failonerror="false" />
<delete dir="war/WEB-INF/lib" failonerror="false" />
<delete dir="war/ivygwt" failonerror="false" />
<delete dir="lib" failonerror="false" />
</target>

</project>