Multiple Resolvers

This example is an illustration of how modules can be retrieved by multiple resolvers. Using multiple resolvers can be useful in many contexts, here are some examples:
  • separate integration builds from releases
  • use a public repository for third party modules and a private one for internal modules
  • use a repository for storing modules which are not accurate in an unmanaged public repository
  • use a local repository to expose builds made on one developer's station
In Ivy, the use of multiple resolvers is supported by one compound resolver called a chain resolver.

In our example, we will simply show how to use two resolvers, one on a local repository and one using maven2 repository.

project description

the project: chained-resolvers

The project is very simple and contains only one simple class: example.Hello.

It depends on two libraries: Apache commons-lang and a little test library (sources are included in jar file). The test library is used by the project to uppercase a string, and commons-lang is used to capitalize the same string.

Here is the content of the project:
  • build.xml: the ant build file for the project
  • ivy.xml: the ivy project file
  • src\example\ the only class of the project
Let's have a look at the ivy.xml file:
<ivy-module version="1.0">
<info organisation="org.apache" module="chained-resolvers"/>
<dependency org="commons-lang" name="commons-lang" rev="2.0"/>
<dependency name="test" rev="1.0"/>
As we expect, the ivy file declares to be dependent on the two libraries that the project use: commons-lang and test. Note that we don't specify the organisation for the dependency test, in this case Ivy assumes the same org as the declaring module, ie org.apache in this case.

the ivy settings

The ivy settings is made in the settings directory it contains only one file: ivysettings.xml.
<settings defaultResolver="chain-example"/>
<chain name="chain-example">
<filesystem name="libraries">
<artifact pattern="${ivy.settings.dir}/repository/[artifact]-[revision].[ext]" />
<ibiblio name="ibiblio" m2compatible="true" />

the settings tag

This tag initializes ivy with some parameters. Here only one is used, the name of the resolver to use by default.

the resolvers tag

Under this tag, we can find the description of the resolvers that ivy will use. In our example, we have only one resolver, called "chain-example", which is quite special as it defines a list (a chain) of resolvers.
The resolvers put in the chain are :
  • libraries : it is a file resolver. This one is configured to look for artifacts in the "repository" sub directory of the directory that contains the ivysettings.xml file.
  • ibiblio : this resolver is a special one. It looks in the ibiblio maven repository to retrieve the libraries.
That's it, we have configured a chain of resolvers!


step 1: preparation

Open a DOS or shell window, and go to the "chained-resolvers" directory.

step 2: clean directory tree

On the prompt type: ant
This will clean up the entire project directory tree and ivy cache. You can do it each time you want to clean up this example.
In almost all examples, we provide a clean target as default target. Since most examples use the same Ivy cache, you will clean the whole Ivy cache each time you call this target.

Cleaning Ivy cache is something you can do with no fear (except performance): it's only a cache, everything can be (and should be) obtained again from repositories. For those coming from maven 2 land, this may sounds strange, but remember that in Ivy, the cache is not a local repository, things are kept cleanly isolated.

step 3: run the project

Go to chainedresolvers-project directory. And simply run ant.
Buildfile: src\example\chained-resolvers\chainedresolvers-project\build.xml resolve: [ivy:retrieve] :: Ivy 2.0.0-beta1-local-20071104204849 - 20071104204849 :: :: [ivy:retrieve] :: loading settings :: file = C:\dev\data\opensource_workspace\ivy\src\example\chained-resolvers\config\ivysettings.xml [ivy:retrieve] :: resolving dependencies :: [ org.apache | chained-resolvers | working@BEN-ScokartG ] [ivy:retrieve] confs: [default] [ivy:retrieve] found [ commons-lang | commons-lang | 2.0 ] in ibiblio [ivy:retrieve] found [ org.apache | test | 1.0 ] in libraries [ivy:retrieve] downloading ... [ivy:retrieve] ............................................................. [ivy:retrieve] ......................................................... (165kB) [ivy:retrieve] .. (0kB) [ivy:retrieve] [SUCCESSFUL ] [ commons-lang | commons-lang | 2.0 ]/commons-lang.jar[jar] (5928ms) [ivy:retrieve] downloading C:\dev\data\opensource_workspace\ivy\src\example\chained-resolvers\config\repository\test-1.0.jar ... [ivy:retrieve] .. (1kB) [ivy:retrieve] [SUCCESSFUL ] [ org.apache | test | 1.0 ]/test.jar[jar] (10ms) [ivy:retrieve] :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 2 | 2 | 0 | 0 || 2 | 2 | --------------------------------------------------------------------- [ivy:retrieve] :: retrieving :: [ org.apache | chained-resolvers ] [ivy:retrieve] confs: [default] [ivy:retrieve] 2 artifacts copied, 0 already retrieved run: [mkdir] Created dir: C:\dev\data\opensource_workspace\ivy\src\example\chained-resolvers\chainedresolvers-project\build [javac] Compiling 1 source file to C:\dev\data\opensource_workspace\ivy\src\example\chained-resolvers\chainedresolvers-project\build [java] standard message :example world ! [java] capitalized by org.apache.commons.lang.WordUtils : Example World ! [java] upperCased by test.StringUtils : EXAMPLE WORLD ! BUILD SUCCESSFUL Total time: 12 seconds
We can see in the log of the resolve task, that the two dependencies have been retrieved (2 artifacts) and copied to the ivy cache directory (2 downloaded).

The run target succeed in using both commons-lang.jar comming from ibiblio repository and test.jar coming from the local repository.

Going further

This very simple example helps to see how to make a basic setting of two resolvers in a chain. The chain resolver's reference documentation is available for those who would like to know all the features offered by this resolver.

The most interesting things to know that you can try out from this basic example are:
  • a chain is not limited to two nested resolvers, you can use the number you want
  • by setting returnFirst="true", you can have a chain which stops as soon as it has found a result for a given module
  • by setting dual="true", the full chain will be used both for module descriptors and artifacts, while with dual="false", the resolver in the chain which found the module descriptor (if any) is also used for artifacts