One of the nicest features of Maven is its ability to specify some dependencies as compile time only, and they won’t be
included at runtime because they are already provided by the target web container. Here is an example of it.
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
But that’s it! I don’t remember any other feature in Maven if I want to download some jars for only Tomcat v6, but
some others only for Tomcat v5 container. In Ivy, there is a very powerful dependency grouping mechanism called
configurations. You can easily achieve the above “provided” effect and the other conditional case using Ivy conf feature.
<ivy-module version="1.4">
<info organisation="org.ems4j" module="test.webproject" />
<configurations>
<conf name="compile"/>
<conf name="tomcatv5"/>
<conf name="tomcatv6"/>
</configurations>
<dependencies>
<dependency org="apache" name="commons-lang" rev="2.2" />
<dependency org="sun" name="servlet" rev="2.4" conf="compile->default"/>
<dependency org="sun" name="el" rev="1.0" conf="tomcatv5->default"/>
<dependency org="apache" name="jasper-el" rev="6.0.14" conf="tomcatv6->default"/>
</dependencies>
</ivy-module>
Here above is an example ivy.xml file to demonstrate the power and flexibility of Ivy configurations. First of all,
you must define which configurations your current module should have: compile, tomcatv5, tomcatv6 in our case. Then
in your dependencies, you need to specify how each dependency will be resolved according to those configurations. For
example, when your module is built with the “compile” parameter, Ivy will include servlet-2.4.jar in your dependency
list, and any of servlet-2.4.jar’s (transitive) dependencies, if they exist, will be resolved with the “default”
configuration. The “default” configuration exists by default and is valid until you define any conf explicitly in the
ivy.xml file of your module. As you guess, you can specify any available conf definition on both sides of the ->
equation. In other words, you map how configurations of your module (test.webproject) are mapped to configurations of
its dependent modules. If you omit the conf attribute in your dependency element, then it is assumed as *->* by
default, which means it will be resolved from any configuration to any other configuration.
Here is another example to illustrate this mapping concept.
<ivy-module version="1.4">
<info organisation="org.ems4j" module="ems4j" />
<configurations>
<conf name="apache-tomcatv5"/>
<conf name="apache-tomcatv6"/>
</configurations>
<publications>
<artifact name="ems4j" type="jar" ext="jar"/>
</publications>
<dependencies>
<dependency org="apache" name="myfaces" rev="1.2.0" conf="apache-tomcatv6->default"/>
<dependency org="apache" name="myfaces" rev="1.1.5" conf="apache-tomcatv5->default"/>
</dependencies>
</ivy-module>
Let’s say I have another module called “ems4j”. For example, I want it to depend on myfaces 1.1.5 impl when tomcatv5
is used, and depend on 1.2.0 when tomcatv6 is used. In our test.webproject’s ivy.xml file, we can add a dependency
element for our ems4j.jar.
<dependency org="org.ems4j" name="ems4j" rev="latest.integration" conf="tomcatv5->apache-tomcatv5;tomcatv6->apache-tomcatv6"/>
If you look at its confattribute closely, you will notice that when our test.webproject is built for tomcatv5, the
ems4j module will be resolved with its apache-tomcatv5 configuration, and when conf is tomcatv6, then the conf
for ems4j module will be apache-tomcatv6. Hence, for the ems4j module, myfaces 1.1.5 will be resolved for
apache-tomcatv5, and 1.2.0for apache-tomcatv6, and will be included in the dependency list of test.web project as
a transitive dependency. You don’t have to make conf names different in your different ivy.xml files of your module.
I here preferred to make confdefinitions for tomcat version 5 in those two ivy.xml files, but it is also valid to
make them the same.
There are several other features related to Ivy configurations, such as inheritance between configurations, and
defaultconfmapping for dependencies, etc. However, in my opinion, the above part is enough to show how Ivy
configurations are powerful and flexible.