Friday, February 14, 2014

Using Ivy for dependency management - IvyDE on Eclipse Tutorial

In this running example, you will understand what Ivy dependency management is and how to use it in Eclipse (I am using Rational RSA IDE in this example which is built on the top of eclipse) using the IvyDE plugin.

In one of my previous posts, I explained a few concepts about Maven (http://runningexample.blogspot.com/2011/01/apache-maven-tutorial-basic-setup.html ). Maven has the capacity to do dependency management along with a host of other things. However, if your requirement is JUST TO MANAGE JAVA JAR DEPENDENCIES (and not worry about project/shared code management, build.xml configuration, continuous integration etc. ), Ivy might be the tool for you.

Example scenario: You are building a simple project and you need some classes from a shared Apache jar (commons or codec or whatever). To use the jar file in your project, you can manually download the jar file from a server/internet. However, if you need a different version of that jar later or if you need many jars later in the project  it makes sense to set up a system where all you need to is declare the jar files you need and that system/mechanism downloads the jars (the exact versions that you need) from a server/internet.

The key concepts in Ivy:

1.  Ivy settings file: This is where you specify the repository paths from where the jar files that you need will be downloaded. We manually create this file JUST ONCE and save it in a folder. You can have only one settings file for all your projects across your organization.
Explanation: Repository paths are the places where the jar files are stored in a particular structure according to the versions. These repositories can be the ones that are maintained by open source/commerical project servers(Apache/JBoss etc.) or the ones that are hosted by your organization.

2.  Ivy.xml:  This is the back bone of this mechanism. This class has the jar file declarations that you need in your project. This is also called the Ivy configuration file.  Each project will have it’s own ivy.xml file. We can manually create this file or we can have the IvyDE plugin generate this file for us. 

In this post, we let the plugin generate the file for us. A few sample lines from a sample file

 <dependencies>
 <dependency org="commons-validator" name="commons-validator" rev="1.3.1" transitive="false" />
                </dependencies>



In this example, to use Ivy in Eclipse, we use the IvyDE plugin.
To setup IvyDE, go to Help à Install New Software



Click on Add. Enter the following
Name: IvyDE
Click OK.


IvyDE will install as a plugin for Eclipse. You might need to restart your workspace for this to take effect.
After that, go to Window à Preferences à Ivy -à Settings



Here you can point the Ivy Settings path to your custom settings file. (A sample settings file below. You can create the below sample files and save them to your file location and point the path here),

Sample ivysettings.xml.
<ivysettings>
 <settings defaultResolver="default"/>
 <include url="ivysettings-public.xml"/>
 <include url="ivysettings-shared.xml"/>
 <include url="ivysettings-local.xml"/>
 <include url="ivysettings-main-chain.xml"/>
 <include url="ivysettings-default-chain.xml"/>
</ivysettings>
This settings file can have the pointers to multiple settings files.

Please note: In the above settings file, you can delete the entries that you don’t have. Such separation of entries will help manage local jars/ shared jars in your organization on a shared drive, jars on the internet respositories etc. If you plan to download the jars from the public respositories on the internet, you can retain just the ivysettings-public.xml entry and delete the remaining lines. Create a new file like the one shown below.
Sample ivysettings-public.xml
<?xml version="1.0" encoding="UTF-8"?>
<ivysettings>
    <resolvers>
        <chain name="public">
            
            <ibiblio name="ibiblio" m2compatible="true"/>
                                                <ibiblio name="JbossCommunityRepository" root="http://repository.jboss.org/nexus/content/groups/public/" m2compatible="true"/>
                                
        </chain>
    </resolvers>
</ivysettings>
Note: Keep both the files in the same folder.

Create a new Dynamic Web Project (or any other project as per your preference).


Right click on the Web Project, Select New à Ivy file (You may have to click on Show All Wizards checkbox at the bottom if you don’t see this option)



Enter your application specific details:




This creates the ivy.xml file for your project.

<?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="com.test"
        module="Tutorial"
        status="integration">
                </info>
</ivy-module>

Let us create a sample class. Right click on the Web Project à New à Class


In this class, we do a simple validation to check if an email string is of a valid format. We use Apache’s GenericValidator class that is inside the commons-validator jar.
package com.test;
public class Sample {

                public void emailValidation()
                {
                                String email = "test@test.com";

                                if(! GenericValidator.isEmail(email))
                                {
                                                System.out.println("Not a valid email");
                                }
                               
                }
}

To resolve the Apache’s GenericValidator class,add the following lines to the ivy.xml file manually:
<dependencies>
  <dependency org="commons-validator" name="commons-validator" rev="1.3.1" transitive="false" />
</dependencies>

Save the file.

After that in any view (Package Explorer/Navigator etc.), right click on the ivy.xml file and select Add Ivy Library. This step will do the magic and download the jar file from the repository that we specified in the ivy settings file (ivysettings-public.xml to be more specific)

If you look the Package explore view (or other views), you will see that the jar file is downloaded and kept under the ivy.xml java library.


Configure the build path in this step if you are still getting Compilation errors. If not, ignore this step. Right click on the Web Project à Build Path à Add Libraries à IvyDE Managed Dependencies


Now go to the class Sample.java and press Ctrl+Space at the compilation error. This will bring up the list of suggested classes, one of which is the desired Apache’s class

That’s pretty much it. Now, just keep adding as many entries in the ivy.xml file as you need when you need any jar file.

Note: The transitive=”false” at the end of the entry in the ivy.xml file is used to prevent downloading all the dependent jars for any specific jar. If you need ALL the dependent jars downloaded, remove the transitive=”false”. But, my suggestion is use it by default and remove when necessary.

BONUS:
After you are done testing and when you export the EAR file, you might want the jars that were resolved by Ivy bundled in your EAR. To do this, right click on the Web project à Properties à Deployment Assembly



Click on Add à Java Build Path Entries


Click on Next and select ivy.xml




Click Finish.

All the Ivy jars will now become a part of WEB-INF/lib when you export the EAR file.