To build private repository like local or shared repositories we have to copy the module’s files and artifacts from public repository to private repository and we have to use Apache Ivy Install task for this. It resolves a module and its dependencies from a repository and install them in another repository. Apache Ivy Install task copies module’s ivy file and artifacts from a source repository to a target repository.
Let’s see Apache Ivy Install task in action by building some private repositories.
6.1. Ivy Local Repository
Apache Ivy Local Repository
Local repository is a private repository where access is restricted to
the owner. By default, the local repository is
${ivy.default.ivy.user.dir}/local
. Built-in variable
${ivy.default.ivy.user.dir}
points to $HOME/.ivy2 and hence local
repository resides in $HOME/.ivy2/local
folder.
Add following file build file to work dir.
build.xml
<project name="localrepository" default="install" xmlns:ivy="antlib:org.apache.ivy.ant">
<target name="install" description="--> install modules to localreporsitory">
<ivy:install organisation="commons-lang" module="commons-lang"
revision="2.6" transitive="true" overwrite="false"
from="public" to="local" />
</target>
</project>
This <ivy:install> definition installs commons-lang 2.6 from public repository to local file system repository. Run Ant and Ivy Install task creates a new local directory in $HOME/.ivy2. Repository layout is shown in the next figure.
Figure 6.1. Local Repository layout
We have not provided any info about local, public resolver and pattern to Ivy, to install the files and artifacts in the local repository. From where Ivy gets details about the repository. We get a clue from the following lines of the build output.
[ivy:resolve] :: loading settings :: url = jar:file:/opt/ant/apache-ant-1.8.2/lib/ivy-.2.0.jar!
/org/apache/ivy/core/settings/ivysettings.xml
So, Apache Ivy uses a default setting file - ivysettings.xml packaged in
ivy-2.0.jar. To know what’s there in this file, extract ivy-2.0.jar
archive some temporary location, and you will find ivysettings.xml
in org/apache/ivy/core/settings
. Contents of this file is are
follows.
/org/apache/ivy/core/settings/ivysettings.xml
<ivysettings>
<settings defaultResolver="default" />
<include url="${ivy.default.settings.dir}/ivysettings-public.xml" />
<include url="${ivy.default.settings.dir}/ivysettings-shared.xml" />
<include url="${ivy.default.settings.dir}/ivysettings-local.xml" />
<include url="${ivy.default.settings.dir}/ivysettings-main-chain.xml" />
<include url="${ivy.default.settings.dir}/ivysettings-default-chain.xml" />
</ivysettings>
By default, Apache Ivy comes with shared, default, local,
public, main resolvers. Definition of each of this resolvers is
contained in separate settings file. In org/apache/ivy/core/settings
folder you find these five settings files. Let’s go through the contents
of ivysettings-public.xml
and ivysettings-local.xml.
/org/apache/ivy/core/settings/ivysettings-public.xml
<ivysettings>
<resolvers>
<ibiblio name="public" m2compatible="true" />
</resolvers>
</ivysettings>
For public repository, Ivy uses built-in resolver <ibiblio>.
/org/apache/ivy/core/settings/ivysettings-local.xml
<ivysettings>
<property name="ivy.local.default.root"
value="${ivy.default.ivy.user.dir}/local"
override="false" />
<property name="ivy.local.default.ivy.pattern"
value="[organisation]/[module]/[revision]/[type]s/[artifact].[ext]"
override="false" />
<property name="ivy.local.default.artifact.pattern"
value="[organisation]/[module]/[revision]/[type]s/[artifact].[ext]"
override="false" />
<resolvers>
<filesystem name="local">
<ivy pattern="${ivy.local.default.root}/${ivy.local.default.ivy.pattern}" />
<artifact pattern="${ivy.local.default.root}/$ivy.local.default.artifact.pattern}" />
</filesystem>
</resolvers>
</ivysettings>
For local repository Ivy pattern and Artifact pattern
[organisation]/[module]/[revision]/[type]s/[artifact].[ext]
defines
the layout of Local repository.
Once, local repository is successfully created, it is always a good idea to do a quick resolve to ensure that Ivy is able to retrieve artifacts from our new repository without any naming conflicts. To do that, add ivy.xml to work directory
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="simpleivy" status="integration">
</info>
<dependencies>
<dependency org="commons-lang" name="commons-lang" rev="2.6" />
</dependencies>
</ivy-module>
This is the same old ivy.xml file which we used earlier for resolve task. Add following snippet to build.xml and run ant.
buil.xml
....
<target name="resolve" description="resolve dependencies with ivy">
<ivy:retrieve />
</target>
....
Ivy should do a resolve and retrieve and place the retrieved artifacts in the lib directory without any protest.
Figure 6.2. Retrieval from Local Repository
Prime Ivy cache from Local Repository
Our local repository is now good to go. But observe the output.
[ivy:resolve] confs: [default]
[ivy:resolve] found commons-lang#commons-lang;2.6 in public
[ivy:resolve] :: resolution report :: resolve 172ms :: artifacts dl 25ms
It indicates that commons-lang is found in public. By default, Ivy first searches in the local, then shared and then public. But it is still resolving from public repository, even though the module is in local. Reason is cache. During install, it has copied the module from public to cache and then to local and that copy is still exists in cache. On subsequent resolves, it finds the artifacts resolved from public repository in cache and says that it has found it in public.
Warning
In the next step, we are going to clear the cache which simply deletes
the $HOME/.ivy2/cache
directory. If your cache contains a large number
of modules then you will lose them. Just to explain the resolve
mechanism, we are going to clean the cache. So, try this when you have a
small cache.
Use <ivy:cleancache> task to clear the cache. Add following snippet to build.xml and run ant clean-cache
build.xml
....
<target name="clean-cache" description="--> clean the cache">
<ivy:cleancache />
</target>
....
<ivy:cleancache> task deletes the $HOME/.ivy2/cache directory and that clears the cache. Next, run <ivy:resolve> task and resolve happens from the local repository. Output indicates that commons-lang is found in local and triggers a download to the cache.
Local Resolve
It is important to note that in case of local resolve too Ivy first searches the cache for artifacts and if it is not found, then, it copies the artifacts from the local repository to cache and then say the module is resolved and downloaded.
Sequence of download or copy during a resolve from any type of the repository is as follows:
Public -> cache -> project build path
Local -> cache -> project build path
Ivy Local Repository - Overriding the default settings
There are two ways to override the default settings, either through setting the properties in Ant target or through ivysettings.xml file.
As an exercise, let’s change the layout of the local repository. Modify the build.xml.
build.xml
<project name="shared repository" default="install"
xmlns:ivy="antlib:org.apache.ivy.ant">
<target name="install" description="local at non default location">
<property name="ivy.local.default.ivy.pattern"
value="[organisation]/[module]/ivys/ivy-[revision].xml" />
<property name="ivy.local.default.artifact.pattern"
value="[organisation]/[module]/[type]s/[artifact]-[revision].[ext]" />
<ivy:install organisation="commons-lang" module="commons-lang" revision="2.6"
transitive="true" overwrite="false" from="public" to="local" />
</target>
</project>
We have used Ant property to change ivy pattern and artifact pattern. Install still uses default local resolver, but layout of repository is changed to the new pattern.
Delete Local Repository
Before running this example, you may have to clear the local repository as commons-lang module is already installed on local. Deleting the local repository is easy, just delete the directory $HOME/.ivy2/local.
Run Ant and see whether the local repository layout is changed as indented.
Alternatively, we may use ivysettings.xml to override the default
settings. Following ivysettings.xml defines a chain resolver named
myresolver which points to $HOME/.ivy2/local
but layout pattern is
different from the default local resolver. Place ivysettings.xml
file
along with build.xml
and Ivy loads it instead of default file that
comes with Ivy.
ivysettings.xml
<ivysettings>
<property name="ivy.local.default.root"
value="${ivy.default.ivy.user.dir}/local" override="false" />
<property name="ivy.local.default.ivy.pattern"
value="[organisation]/[module]/ivys/ivy-[revision].xml"
override="false" />
<property name="ivy.local.default.artifact.pattern"
value="[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"
override="false" />
<settings defaultResolver="myresolver" />
<resolvers>
<chain name="myresolver">
<filesystem name="mylocal">
<ivy
pattern="${ivy.local.default.root}/${ivy.local.default.ivy.pattern}" />
<artifact
pattern="${ivy.local.default.root}/${ivy.local.default.artifact.pattern}" />
</filesystem>
<ibiblio name="mypublic" m2compatible="true" />
</chain>
</resolvers>
</ivysettings>
Our ivysettings.xml defines two resolvers within chain resolver
mylocal – filesystem based repository with root at $HOME/.ivy2/local as defined by variable ivy.local.default.root.
mypublic – default maven2 public repository.
Ivy pattern [organisation]/[module]/ivys/ivy-[revision].xml
places
ivy.xml in ivys directory. Artifact pattern
[organisation]/[module]/[type]s/[artifact]-[revision].[ext]
places
jar, source and Javadoc artifacts in three subdirectories - jars,
sources and javadocs. Even though all three artifacts are named as
commons-lang-2.6.jar, Ivy distinguishes them from the directory where
they are placed.
With those changes in settings, Ivy now has only three resolvers myresolver (chain), mylocal and mypublic. As default ivysettings.xml is not loaded, default resolver default, main, local, shared and public are not available.
In <ivy:install> task, we have to use mylocal and mypublic in from and to attributes. Add build.xml with these changes to work dir
build.xml
<project name="shared repository" default="install"
xmlns:ivy="antlib:org.apache.ivy.ant">
<target name="install" description="local at non default location">
<property name="ivy.local.default.ivy.pattern"
value="[organisation]/[module]/ivys/ivy-[revision].xml" />
<property name="ivy.local.default.artifact.pattern"
value="[organisation]/[module]/[type]s/[artifact]-[revision].[ext]" />
<ivy:install organisation="commons-lang" module="commons-lang" revision="2.6"
transitive="true" overwrite="false" from="mypublic" to="mylocal" />
</target>
</project>
Delete the local repository and run Ant. Ivy Install task creates and populate the local repository using the custom resolvers from our ivysettings.xml.