There are manifold ways to manage 3rd party library dependencies within a build, ranging from simply checking them into your SCM system to Maven’s innovative on demand downloading of versioned libraries at build time. Each strategy has its own pros and cons. For example, keeping 3rd party libraries in a lib directory hanging of the root directory of a project is fine so long as that’s the only project within an SCM system– if you have multiple projects that all have lib directories and each has the same copy of various dependencies, you end up with copies of binaries across the system, which always seemed somewhat inelegant to me.
Of course, Maven’s auto-downloading of dependencies requires that you use Maven as the core build system (actually, the Maven team recently released a set of Ant tags that simulate dependency management), which is a problem if you have already invested in Ant. All’s not lost, however, as Ant users have the option of using Ivy, which is an excellent dependency management framework that works much like Maven.
Getting up and running with Ivy is quite easy too– it takes, at a minimum, 4.2 steps (and as you’ll see, you can get by with 3.1). Central to Ivy’s behavior is the notion of dependencies, which you define in an XML file. In this file you explicitly state the dependency’s name and version. This is key too– not only do you specify that your build requires JUnit compile (and run), for example, but that you are explicitly bound to version 3.8.1 (as opposed to 4.0).
As an example, here is a dependency file (named ivy.xml), which defines a project’s required libraries (which either are required for compilation or are runtime dependencies). By the way, Ivy is sophisticated enough to allow you to delineate specific types of dependencies– either runtime, compile, etc.
<ivy-module version="1.0">
<info organisation="acme" module="os19xp" />
<dependencies>
<dependency name="saxpath" rev="1.0-FCS" />
<dependency name="jaxen" rev="1.0-FCS-full" />
<dependency name="xom" rev="1.1" />
<dependency name="junit" rev="3.8.1" />
<dependency name="jdepend" rev="2.7" />
<dependency name="xmlunit" rev="1.0" />
<dependency name="groovy" rev="all-1.0" />
<dependency name="xerces" rev="2.3.0" />
<dependency name="xml-apis" rev="2.0.2" />
</dependencies>
</ivy-module>
As you can see, this file makes no reference of where these files exist and where they’ll be stored– it just defines required dependencies for a particular project. By default, Ivy will scan Ibiblio for these jar files using the same exact pattern that Maven 1 utilized (name/jars/jarname-version.jar)
Secondly, if you’d like to use a custom repository from which project dependencies are downloaded (for example, if you don’t want to rely on Ibiblio and would rather have an internal web server serving up files), you can define a configuration file. This file is commonly called ivyconfig.xml and allows you to, among other things, define a custom dependency repository.
<ivysettings>
<conf defaultResolver="chained" />
<resolvers>
<chain name="chained">
<url name="xrepo">
<artifact
pattern="http://www.acme.com/
repo/[artifact]/jars/[artifact]-[revision].[ext]" />
</url>
<ibiblio name="ibiblio" />
</chain>
</resolvers>
</ivysettings>
As you can see, in the file above, an additional repository is defined (along with a directory layout and mapping scheme), plus, Ibiblio is defined as the second repository should the first repository fail to yield a download. You’ll also notice that this file supports keywords (such as artifact, revision, and ext) by which custom patterns can be created. Plus, Ivy supports additional resolvers (such as file systems) if you’d rather not use http.
Step two, as you can see, is also optional, should you rather not want to define a custom repository; however, relying on Ibiblio may not be entirely prudent should you require explicit control over your project’s dependencies.
Once these files have been defined, incorporating Ivy’s functionality into Ant is a breeze– in fact, it takes two steps (or just one if you don’t require a configuration file) plus two minor steps. The first minor step is to add Ivy’s jars into Ant’s classpath (which means placing them in your ANT_HOME/lib directly), second, you must add a specific namespace to your Ant build file’s project element as follows:
<?xml version="1.0" encoding="UTF-8"?>
<project default="jar" name="acme-xs" basedir="."
xmlns:ivy="antlib:fr.jayasoft.ivy.ant">
...
</project>
Next, you need to create a new target (or update an existing target) that invokes Ivy’s behavior. If you want to use a custom configuration file, then you’ll need to use the configure task and point it to the requisite file like so:
<ivy:configure file="./ivyconfig.xml" />
Lastly, you need to force Ivy to retrieve the dependencies you specified in step one via the retrieve tag.
<ivy:retrieve />
Upon invoking the retrieve task, Ivy will check a local cache (which you can define) for the required libraries– if they don’t exist, it’ll download them. As a side note, if you’d like those jar files to reside in a local directory of the project, provide a ivy.lib.dir property, and Ivy will copy the files specified in the ivy.xml file into this directory.
For example, this snippet of XML defines a classpath in Ant with the jars downloaded via Ivy:
<property name="ivy.lib.dir" value="${libdir}" />
<path id="build.classpath">
<fileset dir="${libdir}">
<include name="**/*.jar"/>
</fileset>
</path>
As you can see, getting Ivy up and running requires 4.2 easy steps:
- Create an ivy.xml file with your required dependencies
- Create a configuration file pointing to a custom repository (optional)
- Place Ivy’s libraries in Ant’s classpath
- Add an Ivy namespace
- Call the ivy:configure task (optional, see #2)
- Call the ivy:retrieve task
If you’re using Ant and are looking for an easy way to declaratively specify your project’s dependencies, then have a look at Ivy– it couldn’t be easier to set up. Plus, once you start digging, you’ll see that this is quite a sophisticated management system (capable of transitive dependencies, for example).

June 26th, 2007 at 4:30 am
Thanks for this detailed step by step tutorial on Ivy!
Two minor recommendations for people new to Ivy that may be useful:
First I recommend using the “org” attribute when declaring a dependency. Indeed Ivy allows to avoid this attribute, but in this case it considers the dependency as being from the same organization as the module in which the dependency is declared. So in your example it’s as if you declared:
which is not really true, and may become a problem later if you start using other repositories.
Second I’d also recommend using a different pattern for the private repository (even if what you suggest works well). If you don’t need to leverage an existing repository (in which you don’t control the layout), we recommend using a pattern similar to maven 2:
[organisation]/[module]/[revision]/[artifact]-[revision].[ext]
The advantage is that it’s more scalable, and that you will be able to use some repository browsing features properly (like repository aware code completion in eclipse using IvyDE, or repository wide reports).
Hope this may help some Ivy newbies.
Xavier (Ivy project creator)
June 28th, 2007 at 9:56 pm
[…] Test Early ยป Ivy in 4.2 steps (tags: readlater ivy java) […]