Project dependencies


This example is an illustration of dependency between two projects.

The depender project declares that it uses the dependee one. We will illustrate two things:
  • public libraries declared by standalone project will automatically be retrieved by the dependant project
  • the depender project will retrieve the "latest" version of the dependee project

projects used

dependee

The dependee project is very simple. It depends on the apache library commons-lang and contains only one class: standalone.Main which provides two services:
  • return the version of the project
  • capitalize a string using org.apache.commons.lang.WordUtils.capitalizeFully
Here is the content of the project:
  • build.xml: the ant build file for the project
  • ivy.xml: the project ivy file
  • src\standalone\Main.java: the only class of the project
Take a look at the ivy.xml file:
<ivy-module version="1.0">
<info organisation="org.apache" module="dependee"/>
<dependencies>
<dependency org="commons-lang" name="commons-lang" rev="2.0"/>
</dependencies>
</ivy-module>
The ivy dependency file declares only one dependency on apache commons-lang library.

depender

The project depender is very simple too. It declares only one dependency on the latest version of the dependee project and it contains only one class depending.Main which make 2 things:
  • getting the version of the standalone project throw a call to standalone.Main.getVersion()
  • transform a string throw a call to standalone.Main.capitalizeWords(str)
Take a look at the ivy.xml file:
<ivy-module version="1.0">
<info organisation="org.apache" module="depender"/>
<dependencies>
<dependency name="dependee" rev="latest.integration" />
</dependencies>
</ivy-module>

settings

The ivy settings is made in the settings directory which contains 2 files:
  • ivysettings.properties: a property file
  • ivysettings.xml: the file containing the settings
Let's have a look at the ivysettings.xml file:
<ivysettings>
<properties file="${ivy.settings.dir}/ivysettings.properties"/>
<settings defaultCache="${ivy.settings.dir}/ivy-cache" defaultResolver="libraries"/>
<resolvers>
<filesystem name="projects">
<artifact pattern="${repository.dir}/[artifact]-[revision].[ext]" />
<ivy pattern="${repository.dir}/[module]-[revision].xml" />
</filesystem>
<ibiblio name="libraries" m2compatible="true" usepoms="false" />
</resolvers>
<modules>
<module organisation="org.apache" name="dependee" resolver="projects"/>
</modules>
</ivysettings>
The file contains four main tags: properties, settings, resolvers and modules.

properties

This tag only load some properties for the ivy process in the same manner as ant would do it.

settings

This tag is in charge of initializing some parameters for ivy process. The directory that ivy will use to cache artifacts will be in a sub directory called ivy-cache of the directory containing the ivysettings.xml file itself.
The second parameter, tells ivy to use a resolver called "libraries" as its default resolver. More information can be found in the settings reference documentation.

resolvers

This tag defines the resolvers to use. Here we have two resolvers defined: "projects" and "libraries".
The filesystem resolver called "projects" is able to resolve the internal dependencies by locating them on the local filesystem.
The ibiblio resolver called "libraries" is able to find dependencies on maven 2 repository, but doesn't use maven poms.

modules

The modules tag allows to configure which resolver should be used for which module. Here the settings only tells to use the "projects" resolver for all modules having for organisation "org.apache" and for module name "dependee". This actually corresponds to only one module, but a regular expression could be used, or many other kind of expressions (like glob expressions).

For other modules (i.e. all modules but org.apache#dependee), since there is no special settings, the default resolver will be used: "libraries".

walkthrough

step 1: preparation

Open a DOS or shell window, and go to the "src/example/dependence" directory.

step 2: clean directory tree

On the prompt type: ant
This will clean up the entire project directory tree. You can do it each time you want to clean up this example.

step 3: publication of dependee project

Go to dependee directory and publish the project
I:\dependee>ant publish
Buildfile: src\example\dependence\standalone\build.xml resolve: [ivy:retrieve] :: Ivy 2.0.0-beta1-local-20071104204849 - 20071104204849 :: http://ant.apache.org/ivy/ :: [ivy:retrieve] :: loading settings :: file = C:\dev\data\opensource_workspace\ivy\src\example\dependence\config\ivysettings.xml [ivy:retrieve] :: resolving dependencies :: [ org.apache | standalone | working@BEN-ScokartG ] [ivy:retrieve] confs: [default] [ivy:retrieve] found [ commons-lang | commons-lang | 2.0 ] in libraries [ivy:retrieve] downloading http://www.ibiblio.org/maven/commons-lang/jars/commons-lang-2.0.jar ... [ivy:retrieve] ................................................................ [ivy:retrieve] ...................................................... (165kB) [ivy:retrieve] .. (0kB) [ivy:retrieve] [SUCCESSFUL ] [ commons-lang | commons-lang | 2.0 ]/commons-lang.jar[jar] (5388ms) [ivy:retrieve] :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 1 | 1 | 0 | 0 || 1 | 1 | --------------------------------------------------------------------- [ivy:retrieve] :: retrieving :: [ org.apache | standalone ] [ivy:retrieve] confs: [default] [ivy:retrieve] 1 artifacts copied, 0 already retrieved compile: [mkdir] Created dir: C:\dev\data\opensource_workspace\ivy\src\example\dependence\standalone\build\classes [javac] Compiling 1 source file to C:\dev\data\opensource_workspace\ivy\src\example\dependence\standalone\build\classes jar: [propertyfile] Creating new property file: C:\dev\data\opensource_workspace\ivy\src\example\dependence\standalone\build\classes\version.properties [jar] Building jar: C:\dev\data\opensource_workspace\ivy\src\example\dependence\standalone\build\standalone.jar publish: [ivy:publish] :: delivering :: [ org.apache | standalone | working@BEN-ScokartG ] :: 1 :: release :: Sun Nov 04 20:50:24 CET 2007 [ivy:publish] delivering ivy file to C:\dev\data\opensource_workspace\ivy\src\example\dependence\standalone/build/ivy.xml [ivy:publish] :: publishing :: [ org.apache | standalone ] [ivy:publish] published standalone to C:\dev\data\opensource_workspace\ivy\src\example\dependence\config/repository/standalone-1.jar [ivy:publish] published ivy to C:\dev\data\opensource_workspace\ivy\src\example\dependence\config/repository/standalone-1.xml [echo] project standalone released with version 1 BUILD SUCCESSFUL Total time: 11 seconds
What we see here:
  • the project depends on 1 library (1 artifact)
  • the library was not in the ivy cache and so was downloaded (1 downloaded)
  • the project has been released under version number 1
To give more details on the publish, as you can see the call to the publish task has resulted in two main things:
  • the delivery of a resolved ivy file to build/ivy.xml.
  • This has been done because by default the publish task not only publishes artifacts but also ivy file. So it has looked to the path where the ivy file to publish should be, using the artifactspattern: ${build.dir}/[artifact].[ext].
    For an ivy file, this resolves to build/ivy.xml. Because this file does not exist, it automatically makes a call to the deliver task which delivers a resolved ivy file to this destination.
  • the publication of artifact dependee and resolved ivy file to the repository.
  • Both are mere copy of files found in the current project, more precisely in the build dir. This is because the artifactspattern has been set to ${build.dir}/[artifact].[ext], so dependee artifact is found in build/dependee.jar and ivy file in build/ivy.xml. And because we have asked the publish task to publish them using the "projects" resolver, these files are copied to repository\dependee-1.jar and to repository\dependee-1.xml, respecting the artifact and ivy patterns of our settings (see above).

step 4: running the depender project

Go to directory depender and run ant
I:\depender>ant
Buildfile: src\example\dependence\depending\build.xml clean: resolve: [ivy:retrieve] :: Ivy 2.0.0-beta1-local-20071104204849 - 20071104204849 :: http://ant.apache.org/ivy/ :: [ivy:retrieve] :: loading settings :: file = C:\dev\data\opensource_workspace\ivy\src\example\dependence\config\ivysettings.xml [ivy:retrieve] :: resolving dependencies :: [ org.apache | depending | working@BEN-ScokartG ] [ivy:retrieve] confs: [default] [ivy:retrieve] found [ org.apache | standalone | 1 ] in projects [ivy:retrieve] [1] [ org.apache | standalone | latest.integration ] [ivy:retrieve] found [ commons-lang | commons-lang | 2.0 ] in libraries [ivy:retrieve] downloading C:\dev\data\opensource_workspace\ivy\src\example\dependence\config\repository\standalone-1.jar ... [ivy:retrieve] .. (1kB) [ivy:retrieve] .. (0kB) [ivy:retrieve] [SUCCESSFUL ] [ org.apache | standalone | 1 ]/standalone.jar[jar] (20ms) [ivy:retrieve] :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 2 | 1 | 0 | 0 || 2 | 1 | --------------------------------------------------------------------- [ivy:retrieve] :: retrieving :: [ org.apache | depending ] [ivy:retrieve] confs: [default] [ivy:retrieve] 2 artifacts copied, 0 already retrieved compile: [mkdir] Created dir: C:\dev\data\opensource_workspace\ivy\src\example\dependence\depending\build\classes [javac] Compiling 1 source file to C:\dev\data\opensource_workspace\ivy\src\example\dependence\depending\build\classes run: [java] you are using version 1 of class standalone.Main [java] standard message : i am depending.Main and standalone.Main will do the job for me [java] [standalone.Main] capitalizing string "i am depending.Main and standalone.Main will do the job for me" using org.apache.commons.lang.WordUtils [java] capitalized message : I Am Depending.main And Standalone.main Will Do The Job For Me BUILD SUCCESSFUL Total time: 3 seconds
What we see here:
  • the project depends on 2 libraries (2 artifacts)
  • one of the libraries was in the cache because there was only 1 download (1 downloaded)
  • ivy retrieved the version 1 of the project dependee. The call to standalone.Main.getVersion() has returned 1. If you look in the depender/lib directory, you should see dependee-1.jar which is the artifact version 1 of the project dependee
  • the call to standalone.Main.capitalizeWords(str) succeed, which means that the required library were in the classpath. If you look at the lib directory, you will see that the library commons-lang-2.0.jar was retrieved. This library was declared to be used by the project "dependee", so ivy get it too for the depender project.

step 5: new version of dependee project

Like we did before in step 3, publish again the dependee project. This will result as a new version of the project.
I:\dependee>ant publish
Buildfile: src\example\dependence\standalone\build.xml resolve: [ivy:retrieve] :: Ivy 2.0.0-beta1-local-20071104204849 - 20071104204849 :: http://ant.apache.org/ivy/ :: [ivy:retrieve] :: loading settings :: file = C:\dev\data\opensource_workspace\ivy\src\example\dependence\config\ivysettings.xml [ivy:retrieve] :: resolving dependencies :: [ org.apache | standalone | working@BEN-ScokartG ] [ivy:retrieve] confs: [default] [ivy:retrieve] found [ commons-lang | commons-lang | 2.0 ] in libraries [ivy:retrieve] :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 1 | 0 | 0 | 0 || 1 | 0 | --------------------------------------------------------------------- [ivy:retrieve] :: retrieving :: [ org.apache | standalone ] [ivy:retrieve] confs: [default] [ivy:retrieve] 0 artifacts copied, 1 already retrieved compile: jar: [propertyfile] Updating property file: C:\dev\data\opensource_workspace\ivy\src\example\dependence\standalone\build\classes\version.properties [jar] Building jar: C:\dev\data\opensource_workspace\ivy\src\example\dependence\standalone\build\standalone.jar publish: [delete] Deleting: C:\dev\data\opensource_workspace\ivy\src\example\dependence\standalone\build\ivy.xml [ivy:publish] :: delivering :: [ org.apache | standalone | working@BEN-ScokartG ] :: 2 :: release :: Sun Nov 04 20:50:33 CET 2007 [ivy:publish] delivering ivy file to C:\dev\data\opensource_workspace\ivy\src\example\dependence\standalone/build/ivy.xml [ivy:publish] :: publishing :: [ org.apache | standalone ] [ivy:publish] published standalone to C:\dev\data\opensource_workspace\ivy\src\example\dependence\config/repository/standalone-2.jar [ivy:publish] published ivy to C:\dev\data\opensource_workspace\ivy\src\example\dependence\config/repository/standalone-2.xml [echo] project standalone released with version 2 BUILD SUCCESSFUL Total time: 2 seconds
Now if you look in your repository folder, you will find 2 version published of the dependee project.
Let's look at it:
I:\dependee>dir ..\settings\repository /w

[.] [..] dependee-1.jar dependee-1.xml dependee-2.jar dependee-2.xml

I:\dependee>
Ok now our repository contains two versions of the project dependee, other projects can refer to both versions.

step 6: get the new version in depender project

What do we expect about running again the depender project? Two major things are expected:
  • retrieve the version 2 as the latest.integration version of the dependee project
  • running the test must display version 2 of dependee project
Let's go!!!
I:\depender>ant
Buildfile: src\example\dependence\depending\build.xml clean: [delete] Deleting 3 files from C:\dev\data\opensource_workspace\ivy\src\example\dependence\depending [delete] Deleted 4 directories from C:\dev\data\opensource_workspace\ivy\src\example\dependence\depending resolve: [ivy:retrieve] :: Ivy 2.0.0-beta1-local-20071104204849 - 20071104204849 :: http://ant.apache.org/ivy/ :: [ivy:retrieve] :: loading settings :: file = C:\dev\data\opensource_workspace\ivy\src\example\dependence\config\ivysettings.xml [ivy:retrieve] :: resolving dependencies :: [ org.apache | depending | working@BEN-ScokartG ] [ivy:retrieve] confs: [default] [ivy:retrieve] found [ org.apache | standalone | 2 ] in projects [ivy:retrieve] [2] [ org.apache | standalone | latest.integration ] [ivy:retrieve] found [ commons-lang | commons-lang | 2.0 ] in libraries [ivy:retrieve] downloading C:\dev\data\opensource_workspace\ivy\src\example\dependence\config\repository\standalone-2.jar ... [ivy:retrieve] .. (1kB) [ivy:retrieve] .. (0kB) [ivy:retrieve] [SUCCESSFUL ] [ org.apache | standalone | 2 ]/standalone.jar[jar] (100ms) [ivy:retrieve] :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 2 | 1 | 0 | 0 || 2 | 1 | --------------------------------------------------------------------- [ivy:retrieve] :: retrieving :: [ org.apache | depending ] [ivy:retrieve] confs: [default] [ivy:retrieve] 2 artifacts copied, 0 already retrieved compile: [mkdir] Created dir: C:\dev\data\opensource_workspace\ivy\src\example\dependence\depending\build\classes [javac] Compiling 1 source file to C:\dev\data\opensource_workspace\ivy\src\example\dependence\depending\build\classes run: [java] you are using version 2 of class standalone.Main [java] standard message : i am depending.Main and standalone.Main will do the job for me [java] [standalone.Main] capitalizing string "i am depending.Main and standalone.Main will do the job for me" using org.apache.commons.lang.WordUtils [java] capitalized message : I Am Depending.main And Standalone.main Will Do The Job For Me BUILD SUCCESSFUL Total time: 5 seconds
Ok we have the result expected as the run target shows that we are using the version 2 of the main class of dependee project. If we take a look at the resolve target results, we can see that one artifact has been downloaded to the ivy cache. In fact this file is the version 2 of the dependee project that was taken from the repository, you can now retrieve it in the ivy-cache directory.