Apache Ivy Resolve


April 4, 2014 Maithilish

Chapter 3. Apache Ivy Resolve

Resolve task, resolve dependencies described in ivy.xml and places the resolved dependencies in the Apache Ivy cache.
Let’s go through a sample project to understand this important concept. First, create a directory tree for package in.ex.ivy in the work dir
mkdir -p src/in/ex/ivy
Add following class file to src/in/ex/ivy.
Example.java

package in.ex.ivy;

import org.apache.commons.lang.StringUtils;

public class Example {
      public static void main(String[] args) {
            String string = StringUtils.upperCase("Ivy Beginner Guide");
            System.out.println(string);
      }
}

Example class depends on Apache Commons module commons-lang and let’s delegate the Dependency management to Apache Ivy.
Add a file named ivy.xml to the work dir.
ivy.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<ivy-module version="2.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
 <info organisation="in.ex" module="ivy-example" status="integration">
 </info>
 <dependencies>
  <dependency org="commons-lang" name="commons-lang" rev="2.6" />
 </dependencies>
</ivy-module>

Ivy reads this file and manage the dependencies. It provides info about the sample project and its dependencies and has 3 sections
  1. ivy-module : this is a standard root element with version,schema etc.
  2. info : this section is information about the project.
    • organisation : organisation or company.
    • module : name of the project
    • status : release status – milestone, integration or release.
  3. dependencies : one or more dependencies for this project.
    • dependency :
      • org : organisation which provides the module
      • name : module name
      • rev : revision or version of the module
To sum up, in ivy.xml we are indicating that our project is dependent on commons-lang revision 2.6.
To run the Apache Ivy in command line mode, we depend on Apache Ant. Add Ant build file build.xml to the work dir.
build.xml

<project name="ivy example" default="resolve" xmlns:ivy="antlib:org.apache.ivy.ant">
 <target name="resolve" description="resolve dependencies with ivy">
  <ivy:resolve />
 </target>
</project>

In the project element we add Ivy namespace, so that Apache Ivy Ant Tasks are visible to Ant during the build. Resolve task is defined through <ivy:resolve /> within target element. When Ant encounters this element, it calls Apache Ivy Resolve task which resolves the dependencies described in ivy.xml and places the resolved dependencies in its cache.
That completes the Apache Ivy and Ant configuration. Next, run Ant from work directory.

ant

Apache Ivy gets into the job of resolving the dependencies we mentioned in ivy.xml. If you are connected to the Internet, Ivy fetches the commons-lang 2.6 from a public repository in Internet and places them in the cache.

Ivy Resolve Task

Figure 3.1. Resolve output


Console output shows the status of Resolve.
  • conf – ivy is using default configuration
  • module – as indicated by number and dwnlded columns, one module is resolved and downloaded.
  • artifacts – as indicated by the columns under artifacts, module contains 3 artifacts, i.e. jar, source and javadoc and Ivy has downloaded those three artifacts.
In this example, we have not specified the location where Ivy has to look for the modules. But how come Ivy is able to complete the task. In the absence of specific settings, Apache Ivy falls back on default settings that comes bundled with it. For a repository location, it uses a concept known as Resolver and default public resolver points to http://repo1.maven.org/maven2. This default setting enabled Ivy to resolve and fetch the module.
In case a module itself has other dependencies, then Ivy will fetch all required dependencies. These are known as transitive dependencies. For example, log4j depends on other modules like javax.mail, junit, jermanio.spec and oro etc., Dependency line <dependency org=”log4j” name=”log4j” rev=”1.2.16″/> will download log4j plus four dependent modules. By adding transitive=”false” to dependency line, we can force the Ivy not to download the other transitive dependencies. Dependency line <dependency org=”log4j” name=”log4j” rev=”1.2.16″ transitive=”false” /> downloads just log4j.
Ivy dependency line

The dependency line <dependency org=”commons-lang” name=”commons-lang” rev=”2.6″ /> in ivy.xml requires some explanation. First is how to construct this line. When module developers publish the modules to public repositories they define these values and from these repositories we can easily get the details. As an example, let’s find out the dependency line for the module, commons-lang, from the repository.

Go to MVN Repository at http://mvnrepository.com/ and search for commons-lang which yields all matching commons module. From the list, select commons-lang which displays the commons-lang versions available in the repository.

Ivy Resolve Task - Dependency element

Figure 3.2. Module versions


Click on 2.5 or whatever version you are interested. Repositories hosts modules for Ivy and also other build systems like maven, grape etc. Select Ivy tab and there you will have the exact dependency line for Apache Ivy. Cut and paste this line to ivy.xml

Ivy Resolve Task - dependency element

Figure 3.3. Ivy Dependency element


Another thing about this particular dependency line is that the org is mentioned as commons-lang whereas it should have been apache.org. For some reasons, while publishing the module to the repository, developer (or build guy) has mentioned it as commons-lang instead of apache.org and so it is continuing like that. Instead of guessing, it is always easy to do a search in maven repository and copy the dependency line as provided there.

Clean the Work Dir

Before trying out the next example, delete all files from work dir, except src dir, to avoid errors and confusion. We require src dir which contains the example class to run some examples and so, don’t delete that.
Apache Ivy Cache

On first run, <ivy:resolve> fetches the artifacts from the public repository and place them in the cache. During subsequent calls to <ivy:resolve> either from this project or any other project, Ivy finds the module in cache and will not download it from public repository. Through the cache, Ivy speeds up the time required for resolve and also saves bandwidth usage. By default, Apache Ivy cache is at $HOME/.ivy2. Beyond that, we need not bother much about the internals of the cache.

With the <ivy:resolve>, we are able to resolve the dependencies and place them in the cache and the next chapter covers tasks to expose the resolved artifacts to the project.