# Project dependencies

This tutorial will show you how to use Ivy when one of your projects depends on another.
For our example, we will have two projects, depender and dependee, where the depender project uses/requires the dependee project. This example will help illustrate two things about Ivy:

- that dependencies defined by parent projects (dependee) will automatically be retrieved for use by child projects (depender)
- that child projects can 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 file declares only one dependency, that being the apache commons-lang library.

## depender

The depender project is very simple as well. It declares only one dependency on the latest version of the dependee project, and it contains only one class, `depending.Main`, which does 2 things:

- gets the version of the standalone project by calling `standalone.Main.getVersion()`
- transforms a string by calling `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 are defined in two files located in the settings directory:

- `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 defaultResolver="libraries" />
    	<caches defaultCacheDir="${ivy.settings.dir}/ivy-cache" />
    	<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 loads some properties for the Ivy process, just like Ant does.

## settings

This tag initializes some parameters for the Ivy process. In this case, 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 named "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 the maven 2 repository, but doesn't use maven poms.

## modules

The modules tag allows you to configure which resolver should be used for which module. Here the setting tells Ivy to use the "projects" resolver for all modules having an organisation of `org.apache` and module name of `dependee`. This actually corresponds to only one module, but a regular expression could be used, or many other types of expressions (like glob expressions).
All other modules (i.e. all modules but org.apache#dependee), will use the default resolver ("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 this each time you want to clean up this example.

## step 3: publication of dependee project

Go to `dependee` directory and publish the project

    [ivy@apache:/ivy/dependence/dependee]$ ant publish
    Buildfile: /ivy/dependence/dependee/build.xml

    resolve:
    [ivy:retrieve] :: Apache Ivy 2.4.0 - 20141213170938 :: http://ant.apache.org/ivy/ ::
    [ivy:retrieve] :: loading settings :: file = /ivy/dependence/settings/ivysettings.xml
    [ivy:retrieve] :: resolving dependencies :: org.apache#dependee;working@apache
    [ivy:retrieve] 	confs: [default]
    [ivy:retrieve] 	found commons-lang#commons-lang;2.0 in libraries
    [ivy:retrieve] downloading https://repo1.maven.org/maven2/commons-lang/commons-lang/2.0/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 (3338ms)
    [ivy:retrieve] :: resolution report :: resolve 1111ms :: artifacts dl 3340ms
    	---------------------------------------------------------------------
    	|                  |            modules            ||   artifacts   |
    	|       conf       | number| search|dwnlded|evicted|| number|dwnlded|
    	---------------------------------------------------------------------
    	|      default     |   1   |   1   |   0   |   0   ||   1   |   1   |
    	---------------------------------------------------------------------
    [ivy:retrieve] :: retrieving :: org.apache#dependee
    [ivy:retrieve] 	confs: [default]
    [ivy:retrieve] 	1 artifacts copied, 0 already retrieved (165kB/5ms)

    compile:
        [mkdir] Created dir: /ivy/dependence/dependee/build/classes
        [javac] Compiling 1 source file to /ivy/dependence/dependee/build/classes

    jar:
    [propertyfile] Creating new property file: /ivy/dependence/dependee/build/classes/version.properties
          [jar] Building jar: /ivy/dependence/dependee/build/dependee.jar

    publish:
    [ivy:publish] :: delivering :: org.apache#dependee;working@apache :: 1 :: release :: Sat Dec 13 17:10:38 CET 2014
    [ivy:publish] 	delivering ivy file to /ivy/dependence/dependee/build/ivy.xml
    [ivy:publish] :: publishing :: org.apache#dependee
    [ivy:publish] 	published dependee to /ivy/dependence/settings/repository/dependee-1.jar
    [ivy:publish] 	published ivy to /ivy/dependence/settings/repository/dependee-1.xml
         [echo] project dependee released with version 1

    BUILD SUCCESSFUL
    Total time: 5 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

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 its 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 its resolved ivy file to the repository.
Both are just copies of the files found in the current project, or more precisely, those in the `build` directory. This is because the artifactspattern has been set to `${build.dir}/[artifact].[ext]`, so the dependee artifact is found at `build/dependee.jar` and the 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`

    [ivy@apache:/ivy/dependence/depender]$ ant
    Buildfile: /ivy/dependence/depender/build.xml

    clean:

    resolve:
    [ivy:retrieve] :: Apache Ivy 2.4.0 - 20141213170938 :: http://ant.apache.org/ivy/ ::
    [ivy:retrieve] :: loading settings :: file = /ivy/dependence/settings/ivysettings.xml
    [ivy:retrieve] :: resolving dependencies :: org.apache#depender;working@apache
    [ivy:retrieve] 	confs: [default]
    [ivy:retrieve] 	found org.apache#dependee;1 in projects
    [ivy:retrieve] 	[1] org.apache#dependee;latest.integration
    [ivy:retrieve] 	found commons-lang#commons-lang;2.0 in libraries
    [ivy:retrieve] downloading /ivy/dependence/settings/repository/dependee-1.jar ...
    [ivy:retrieve] .. (1kB)
    [ivy:retrieve] .. (0kB)
    [ivy:retrieve] 	[SUCCESSFUL ] org.apache#dependee;1!dependee.jar (3ms)
    [ivy:retrieve] :: resolution report :: resolve 87ms :: artifacts dl 6ms
    	---------------------------------------------------------------------
    	|                  |            modules            ||   artifacts   |
    	|       conf       | number| search|dwnlded|evicted|| number|dwnlded|
    	---------------------------------------------------------------------
    	|      default     |   2   |   1   |   1   |   0   ||   2   |   1   |
    	---------------------------------------------------------------------
    [ivy:retrieve] :: retrieving :: org.apache#depender
    [ivy:retrieve] 	confs: [default]
    [ivy:retrieve] 	2 artifacts copied, 0 already retrieved (167kB/6ms)

    compile:
        [mkdir] Created dir: /ivy/dependence/depender/build/classes
        [javac] Compiling 1 source file to /ivy/dependence/depender/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: 0 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 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 version 1 artifact of the project "dependee"
- the call to `standalone.Main.capitalizeWords(str)` succeed, which means that the required library was in the classpath. If you look at the `lib` directory, you will see that the library `commons-lang-2.0.jar` was also retrieved. This library was declared as a dependency of the "dependee" project, so Ivy retrieves it (transitively) along with the dependee artifact.

## step 5: new version of dependee project

Like we did before in step 3, publish the dependee project again. This will result in a new version of the project being published.

    [ivy@apache:/ivy/dependence/dependee]$ ant publish
    Buildfile: /ivy/dependence/dependee/build.xml

    resolve:
    [ivy:retrieve] :: Apache Ivy 2.4.0 - 20141213170938 :: http://ant.apache.org/ivy/ ::
    [ivy:retrieve] :: loading settings :: file = /ivy/dependence/settings/ivysettings.xml
    [ivy:retrieve] :: resolving dependencies :: org.apache#dependee;working@apache
    [ivy:retrieve] 	confs: [default]
    [ivy:retrieve] 	found commons-lang#commons-lang;2.0 in libraries
    [ivy:retrieve] :: resolution report :: resolve 56ms :: artifacts dl 2ms
    	---------------------------------------------------------------------
    	|                  |            modules            ||   artifacts   |
    	|       conf       | number| search|dwnlded|evicted|| number|dwnlded|
    	---------------------------------------------------------------------
    	|      default     |   1   |   0   |   0   |   0   ||   1   |   0   |
    	---------------------------------------------------------------------
    [ivy:retrieve] :: retrieving :: org.apache#dependee
    [ivy:retrieve] 	confs: [default]
    [ivy:retrieve] 	0 artifacts copied, 1 already retrieved (0kB/3ms)

    compile:

    jar:
    [propertyfile] Updating property file: /ivy/dependence/dependee/build/classes/version.properties

    publish:
       [delete] Deleting: /ivy/dependence/dependee/build/ivy.xml
    [ivy:publish] :: delivering :: org.apache#dependee;working@apache :: 2 :: release :: Sat Dec 13 17:10:39 CET 2014
    [ivy:publish] 	delivering ivy file to /ivy/dependence/dependee/build/ivy.xml
    [ivy:publish] :: publishing :: org.apache#dependee
    [ivy:publish] 	published dependee to /ivy/dependence/settings/repository/dependee-2.jar
    [ivy:publish] 	published ivy to /ivy/dependence/settings/repository/dependee-2.xml
         [echo] project dependee released with version 2

    BUILD SUCCESSFUL
    Total time: 0 seconds

Now if you look in your repository folder, you will find 2 versions 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, so other projects can refer to either version.

## step 6: get the new version in depender project

What should we expect if we run the depender project again? It should:

- retrieve version 2 as the latest.integration version of the dependee project
- display version 2 of dependee project

Let's try it!!

    [ivy@apache:/ivy/dependence/depender]$ ant
    Buildfile: /ivy/dependence/depender/build.xml

    clean:

    resolve:
    [ivy:retrieve] :: Apache Ivy 2.4.0 - 20141213170938 :: http://ant.apache.org/ivy/ ::
    [ivy:retrieve] :: loading settings :: file = /ivy/dependence/settings/ivysettings.xml
    [ivy:retrieve] :: resolving dependencies :: org.apache#depender;working@apache
    [ivy:retrieve] 	confs: [default]
    [ivy:retrieve] 	found org.apache#dependee;2 in projects
    [ivy:retrieve] 	[2] org.apache#dependee;latest.integration
    [ivy:retrieve] 	found commons-lang#commons-lang;2.0 in libraries
    [ivy:retrieve] downloading /ivy/dependence/settings/repository/dependee-2.jar ...
    [ivy:retrieve] .. (1kB)
    [ivy:retrieve] .. (0kB)
    [ivy:retrieve] 	[SUCCESSFUL ] org.apache#dependee;2!dependee.jar (4ms)
    [ivy:retrieve] :: resolution report :: resolve 92ms :: artifacts dl 7ms
    	---------------------------------------------------------------------
    	|                  |            modules            ||   artifacts   |
    	|       conf       | number| search|dwnlded|evicted|| number|dwnlded|
    	---------------------------------------------------------------------
    	|      default     |   2   |   1   |   1   |   0   ||   2   |   1   |
    	---------------------------------------------------------------------
    [ivy:retrieve] :: retrieving :: org.apache#depender
    [ivy:retrieve] 	confs: [default]
    [ivy:retrieve] 	2 artifacts copied, 0 already retrieved (167kB/4ms)

    compile:
        [mkdir] Created dir: /ivy/dependence/depender/build/classes
        [javac] Compiling 1 source file to /ivy/dependence/depender/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: 0 seconds

OK, we got what we expected as the `run` target shows that we are using version 2 of the main class of the dependee project. If we take a look at the resolve target results, we see that one artifact has been downloaded to the ivy cache. In fact, this file is the same version 2 of the dependee project that is in the repository, but now all future retrievals will pull it from your ivy-cache directory.