Code and Snow and Stuff

Musings on software and the quality of the white stuff…

Archive for the ‘ivy’ Category

Adding Test Dependencies To The Example Project

Apache IvyThis post follows on from my previous post where we set up Ivy and cloned an example project. I hope you had time to look at the code and at least manage to compile the example. Excellent!. As promised, we are going to add in a very simple unit test for the HelloWorld#saySomethingToUpperCase method. However, in order to do that we need to bring in JUnit and another favourite library of mine Hamcrest.

Telling Ivy about where to find the good stuff

To help Ivy find dependencies, it needs to know where to search. It does this by using a resolver. A resolver is nothing more than a way, be it http, ftp, file system (and others) that knows how to look for artifacts. Let’s look at one now:

<ibiblio name="repo2" m2compatible="true" root="http://repo2.maven.org/maven2" />

This resolver is actually “baked into” ivy. It doesn’t have to be explicitly declared, but I believe it makes it clearer later on what is resolving to where if we are up-front about everything to begin with.

What the heck is ibiblio and what does this resolver do? Ibiblio is a public digitial archive that just so happens to also store lots and lots of artifacts as a public service. It stores these artifacts in a way that is maven 2 compatible. Ivy knows how to work with Ibiblio to find stuff. What you may notice however is that instead of giving Ivy the Ibiblio address, we are using the maven repository – this is okay – I’m using the functionality that the Ibiblio resolver gives me, but instead pointing Ivy to look at another repository (which just so happens to be maven 2 compatible as well…). Ivy gives you that flexibility of reusing a resolver that knows how to do “stuff” but get the resolver to look elsewhere for files.

We will be using the Ibiblio resolver quite a bit…

Let’s add that line into our ivysettings.xml file…

<chain name="default" returnFirst="true" checkmodified="true" changingPattern="*-SNAPSHOT*">

        <ibiblio name="repo2" m2compatible="true" root="http://repo2.maven.org/maven2" />

</chain>

Recap

So far so good. We have edited ivysettings.xml to add in a resolver. This resolver will tell Ivy where to look for dependencies. We can now leave ivysettings.xml alone for a while…

Adding in JUnit

It is now the turn of the ivy.xml file. When Ivy is asked to fetch dependencies (or resolve in Ivy-speak), Ivy looks to the ivy.xml file and the ivysettings.xml file. We have told ivy.xml where to look for dependencies, now we have to tell Ivy what dependencies are required. Let’s do that now:

In the ivy.xml we are going to add just one line that will tell Ivy to go fetch the JUnit library – smart!:

<dependency org="junit" name="junit" rev="4.8.1" conf="test->default" />

What does this all mean? Well, it means:

  • There is an dependency that lives in a repository somewhere called junit.junit
  • The particular version of the junit.junit we want is 4.8.1
  • Our test configuration will depend on junit.junit’s default configuration

The last point, configurations, will be talked about in a later article. We will leave that for now. Another question is where on earth do you find out the names of the dependency – it’s organisation, it’s name, what revisions there are??? The answer is to use mvnrepository to search for what you want. If you go there now and type in junit, you will see that the top hit is the dependency we are looking for. If you click on the link and drill down past the revision 4.8.1, you will see that mvnrepository helpfully shows what we need to type into our ivy.xml to pull down this dependency (minus the conf details).

Let’s add that line now to ivy.xml

<dependencies>

    <dependency org="junit" name="junit" rev="4.8.1" conf="test->default" />

</dependencies>

What happens if the library we are after is not in mvnrepository (such as some Sun/Oracle Jars)? An interesting question and one which we will talk about later in a following article. Also, in the interests of fairness, you can lookup artifact information from the Sonatype Nexus Maven Repository in addition to mvnrepository.

Recap

Already we have covered quite a bit. We have not only told Ivy where to look for dependencies (the maven2 repository) but now we have declared that our module depends upon the JUnit artifact. We can use mvnrepository to look for libraries that we require and we can simply add the helpful information that mvnrepository gives to us into our ivy.xml file. After a short while, once you become familiar with using Ivy and using repositories you won’t even have to look at mvnrepository for the commonly used jars since you will be able to easily guess what to put into your ivy.xml file.

Adding in Hamcrest

Before we write a little bit of code, let’s add in one more dependency:

<dependencies>

    <dependency org="junit" name="junit" rev="4.8.1" conf="test->default" />
    <dependency org="org.hamcrest" name="hamcrest-all" rev="1.1" conf="test->default"/>

</dependencies>

I hope you see how easy it is to add in a dependency.

Writing a simple unit test

For the sake of brevity, this is what my unit test (HelloWorldTest.java) looks like (you can find this in ivy-example2 source code – detail of how to download are at the bottom of this article):

package com.dharrigan;

import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class HelloWorldTest {

    final HelloWorld helloWorld = new HelloWorld();

    @Test
    public void saySomethingShouldRespondWithHelloWorldUppercased() {
        assertThat(helloWorld.saySomethingToUpperCase("ivy!"), is(equalTo("IVY!")));
    }
}

Running our Unit Test

Cool, time to run our unit test…If you execute:

ant test

in the project folder, you will see some real magic. Not only will Ivy go and get the dependencies for us, but it will put them in the right place. The project should compile and the unit test should run and pass with flying colours (or green colours at least)…

Building and Testing using Ivy

Building and Testing using Ivy

What just happened?

As part of the build step, Ant asked Ivy to resolve all dependencies. Ivy looked at the ivysettings.xml file to find out where to resolve dependencies from, then it looked at the ivy.xml file to find out what dependencies had been declared. It then went out to the internet, downloaded the dependencies and stored it in your machine. After it had done that, it placed a copy of the jars into the libs/test directory. Ivy was now done. Control was passed back to Ant which compiled the classes (using the jars that Ivy just downloaded) and ran tests. I would encourage you to have a look around the project structure now and see what has been added (hint: libs) and how the compilation proceeded.

What is cool about this?

Well, if you where to run:

ant test

again, Ivy would know that it has already downloaded these jars so it won’t go out to the internet again. This will save enormous time when building projects.

and

Ivy copied the jars into the right location in your project without you doing anything. Ivy uses patterns for placing the jars in the right location. The pattern it uses is completely configurable by you. I have it configured to put it into the libs/[conf] directory (i.e., libs/runtime, libs/test, libs/build-support and so on…).

These are big wins in my book and already we have covered the day-to-day use of Ivy!

Recap

We have discovered how we can add a resolver to the ivysettings.xml file and we have discovered how to add dependencies into your ivy.xml file. Then, we have watched as Ivy did a resolve when building the project and how the unit test worked. Finally we have talked about some of the bonuses of doing it the Ivy way :-)

Getting hold of the source

To view the source directly, you can clone it from here:

hg clone http://bitbucket.org/dharrigan/ivy-example2

or

git clone git://github.org/dharrigan/ivy-example2.git

Coming up next

In my next article, I’ll be covering some of the behind-the-scenes work. I will be talking about my ant build files, how Ivy places files in the right location using patterns and the local ivy cache. I hope you can join me in that adventure!

-=david=-

Written by dharrigan

October 10, 2010 at 11:42 am

Posted in ivy

Tagged with , , ,

Getting Started with Apache Ivy.

Apache IvyApache Ivy is a wonderful way to manage your dependencies for your project. It can retrieve artifacts from remote sites or locally on your filesystem and it can publish your own artifacts remotely or locally. It is a great tool for ensuring that everyone uses the same version of a library/deployable and for rapid sharing of artifacts produced by your team. Since it works with Ant, Ivy can be incorporated into your continuous build server (you do have a continuous build server don’t you? ;-)) very easily.

Ivy primarily works with Java artifacts, although it can be configured to work with any type of artifact – zip files, tar files, gzip files, the list goes on…

The documentation for Ivy is very complete, but it can be a little hard to get into, so I decided to write a few words on how I use it. Perhaps you may find what I have to share useful for you. Perhaps not ;-) Anyway…

This is what I plan to cover in the next few articles:

  • Introduction to Ivy – downloading and initial configuration.
  • Working with a small project to declare and resolve dependencies.
  • Ivy Configurations and excluding artifacts we don’t want.
  • Installing and working with Artifactory.
  • Changing our small project to publish local and shared artifacts.

It is my hope that by the end of my series of articles you should feel relatively comfortable about installing and using Ivy for your projects and maybe gain an appreciation of how powerful and flexible Ivy is.

Prerequisites:

I do all my development either in Vim or in Eclipse. I use Java 6 and I use a unix-like operating system.

However, as a basic setup all you need is:

  • Java 5 or 6.
  • Ant installed and working.
  • A text editor.
  • A console, shell, prompt or terminal.
  • Internet access ;-)

Therefore, these articles should also be accessible to Windows users, or to anyone else who meets the basic requirements.

First Things First!

Let’s be very very clear, Ivy is not Maven. Ivy does not enforce any convention upon you apart from what you decide yourself. You are free to choose any name or location for your source files, your binary files, your resources and so on. Since Ivy works best with Ant, you can script your builds to do what is
required for your project. Instead of being a hinderance, this gives you great freedom to structure your project as you require, yet still get the benefit of intelligently managing your dependencies. Ivy understands Maven-speak, so it natively has the ability to download dependencies from maven structured repositories…which is a good thing! :-) therefore you are not missing out on all the lovely jars out there that live on maven repositories :-)

Downloading Ivy:

Let’s get started then!

There are several ways to get Ivy, but the two most popular are downloading from the Ivy website or compiling directly from source. Personally I do the later since I like to keep up to date with the latest changes.

Both ways are described on the Ivy Download page.

Choose whichever you desire :-)

Once you have Ivy downloaded or built from source, you should find you have an ivy.jar file. What I normally do is create a $HOME/.ant/lib directory and symlink the ivy.jar directly in there. This allows Ant to add Ivy to the classpath when launching. I guess you could say it is the bare minimum
bootstrap needed to allow Ivy to work with Ant.

For those coming from a Windows background, this .ant/lib folder will need to be created somewhere like “C:\Documents and Settings\username\.ant\lib”. Drop the ivy.jar into that folder and we’re good to go.

Update: It has recently been pointed out to me that Windows won’t allow you to create a dot-folder in Explorer (.ant). It complains with an invalid filename error. The solution is to open up a cmd prompt and do it there (cd into the “C:\Documents and Settings\username” folder and then enter “mkdir .ant”). From that point onwards you can view the folder in Explorer and create the lib directory. Thanks to Damian for that tip!

Downloading The Example:

I work best with examples, so to help clarify the next few steps, you will need to clone (using mercurial or git) either from bitbucket or from github the following project (the projects on each site are identical – personally I use mercurial …)

Choose one and roll with it…

hg clone http://bitbucket.org/dharrigan/ivy-example

or

git clone git://github.org/dharrigan/ivy-example.git

If you examine the structure of the example project, you should see it’s pretty simple – it doesn’t do much.

The Two Most Important Ivy Files:

Ivy needs to files to work with – ivy.xml and ivysettings.xml.

ivy.xml
This file declares information about the module (project) you are working with. It defines the name of the module, what configurations your module supports, what artifacts will be produced and what dependencies your module relies upon.

ivysettings.xml
The companion to ivy.xml. This file tells Ivy information about itself, namely where Ivy can look to resolve the dependencies declared in the ivy.xml file. There are other things that can be configured here, but for the moment they aren’t that interesting to know.

In the upcoming articles we will explore these files more in-depth.

Building The Project

Firstly, you need to copy the conf/project/build-example.properties to conf/project/build.properties. If you are using Java 1.5, change the build.properties property java.target.version to read 1.5. Then, assuming you have javac on your path somewhere, you can simply run

ant

and watch the magic happen.

Well, nothing really happens. The project compiles successfully – which is nice, but no dependencies are downloaded, no library structure is set up, nothing. That’s okay – it’s sufficient for this first look at Ivy just to get it working. In the next article I’ll be adding a unit test in – which will require junit and hamcrest on the classpath…

I hope you have enjoyed this first article and I look forward to seeing you all again soon! Don’t forget you can post a comment in the comments section – anything constructive appreciated! :-)

-=david=-

Written by dharrigan

October 7, 2010 at 5:34 pm

Posted in ivy

Tagged with , , ,

What’s coming up?

In the next couple of weeks, I’m aiming to publish a few articles on using Apache Ivy. It will take someone from installing Ivy, through declaring and resolving dependencies and finally publishing a sample project into a local and shared repository (I’ll be using Artifactory to host shared artifacts). I do hope you can join me in this quest!

-=david=-

Written by dharrigan

October 6, 2010 at 8:02 pm

Posted in development, ivy

Tagged with , ,

Follow

Get every new post delivered to your Inbox.

Join 54 other followers