Ivy Dependency Manager

Like most of us often hear, “its another framework or dependency management tool”. But what exactly differentiates Ivy from Maven?

Ivy is much easier to use. The library is simpler since it doesn’t do so much. It only focuses on dependency management and use the already famous and powerful ant to build the application. In short, ant and ivy is used side by side.

Why I Choose Ivy?

The main thing I like about Ivy is its simplicity. You can use Ivy with only ant installed on your system (and of course, java). This means that you don’t need to download any Ivy related libraries or when using eclipse, no plug-in is needed. You can run everything using ant, from installing the ivy library to downloading the dependencies.

Ivy is a dependency management tool that can use other repository such as maven repository.

Installing Ivy

Before continuing, I’ll assume that you are using ant version 1.7. You can choose to run the ant script in either console or from inside eclipse (It depends on your preference).

Here is a build.xml file that contains several targets that will be used in this post:

<?xml version="1.0" encoding="UTF-8"?>

<project name="ivytest" basedir="." default="usage" xmlns:ivy="antlib:org.apache.ivy.ant">

<property name="lib.dir" value="lib" />
<property name="build.dir" value="build" />
<property name="src.dir" value="src" />

<path id="lib.path.id">
<fileset dir="${lib.dir}" />
</path>

<path id="run.path.id">
<path refid="lib.path.id" />
<path location="${build.dir}" />
</path>

<property name="ivy.install.version" value="2.0.0-beta1" />
<property name="ivy.jar.dir" value="${basedir}/ivy" />
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />

<target name="usage" description="Displays the command used with this build script">
<echo message="Usage" />
<echo message="-------------------------------------------" />
<echo message="Available targets are:" />
<echo message="download-ivy --> Download ivy library" />
<echo message="install-ivy --> Install ivy library" />
<echo message="clean-libs --> Delete lib files" />
<echo message="clean-ivy --> Delete the ivy files" />
<echo message="resolve --> Resolve/Download ivy dependencies" />
</target>

<target name="download-ivy" unless="skip.download" description="Download ivy.jar">
<mkdir dir="${ivy.jar.dir}"/>
<echo message="installing ivy..."/>
<get src="http://repo1.maven.org/maven2/org/apache/ivy/ivy/ ${ivy.install.version}/ivy-${ivy.install.version}.jar"
dest="${ivy.jar.file}" usetimestamp="true"/>
</target>

<target name="install-ivy" depends="download-ivy" description="Install ivy library">
<path id="ivy.lib.path">
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
</target>

<target name="clean-libs" description="Delete all libraries/dependencies">
<echo message="Deleting ${lib.dir}" />
<delete dir="${lib.dir}" />
</target>

<target name="clean-ivy" depends="clean-libs" description="Delete the all folders/files that was generated by ivy">
<echo message="Deleting ${ivy.jar.dir}" />
<delete dir="${ivy.jar.dir}" />
</target>

<target name="resolve" depends="install-ivy" description="Resolve the dependencies">
<ivy:retrieve/>
</target>

<target name="run" depends="resolve" description="Compile and run the project">
<mkdir dir="${build.dir}" />
<javac srcdir="${src.dir}" destdir="${build.dir}" classpathref="lib.path.id" />
<java classpathref="run.path.id" classname="Main"/>
</target>

</project>

Invoke “ant install-ivy” and the ivy jars will be downloaded. A new folder named “ivy” will be created with the ivy.jar in it.

Dowloading Dependencies

By default ivy uses maven 2 repository but you can certainly define other repository (It will be covered on later post).

The build.xml above contains a target named “resolve”. Running the target will cause the Ivy to download defined dependencies on ivy.xml (ivy.xml is needed since all the dependencies are defined on that file). Here is an example of ivy.xml:

<?xml version="1.0" encoding="UTF-8"?>

<ivy-module version="2.0">
<info organisation="ideyatech" module="ivytest"/>
<dependencies>
<dependency org="log4j" name="log4j" rev="1.2.8"/>
</dependencies>
</ivy-module>

The code above downloads the log4j and its dependencies from the defined repository (in our case, maven repo). I chose to use log4j because in the next section, I’ll be demonstrating to compile a simple java class that uses a Ivy managed library. Invoke “ant resolve” now and you will see a message saying that the library is being downloaded.

Compiling The Application

Main.java:

import org.apache.log4j.Logger;
public class Main {
    private static final Logger log = Logger.getLogger(Main.class);
    public static void main(String[] args) {
        System.out.println(”Printed using system.out.println”);
        log.info(”Printed using log4j logger”);
     }
}

The sample java file won’t really print the message being logged. The purpose of this example is to test compiling the application with the Ivy libraries being referenced. The idea is to simply add the “lib” dir to the classpath on compilation.

Try invoking “ant run” and the application will be compiled and executed. Note that invoking the “ant clean-libs” and removing the “resolve” dependency on run target will cause the compilation to throw some error.

References:

http://ant.apache.org/ivy/index.html

Note:

  • Ivy logo is property of Apache Ivy and is not connected with Ideyatech.



We’ve been using Continuum for quite some time now. While Continuum does seem to do a good job managing our builds, its limited support for JUnit Test reports made us evaluate an alternative, Hudson. Hudson is the new guy on the block, aside from cool icons and more intuitive interface, this tool seems to be quite competitive and feature-packed.

So, I’m listing down a head-to-head comparison between Continuum and Hudson as we’ve used them and based on features we are looking for:

Build Management:

Continuum seems to perform better in this area. It allows multiple jobs/script configured on a single project. Projects can also be logically grouped. Hudson only supports one job per workspace, which I find very limiting. This means that if we need 3 jobs (e.g. build-war, deploy, run-test), each job needs its own workspace, which doesn’t make sense because all these job share the same source code.

User Management:

I prefer Hudson a little over Continuum because I like simplicity over flexibility. Considering our small team size, there is no point of grouping people with several permissions across multiple projects. All we need is the ability to restrict the developer’s access within their projects. Hudson has a simple, easy-to-use permission system–I was able to setup user access rights within 30 minutes. Continuum seems to be a little over-complicated on this. Continuum also has a strict password policy which makes it more difficult to manage.

Scheduling:

Once again, Hudson is better due to its simplicity. To configure a schedule, simply add “@daily” on schedule option and you’re all set. While Continuum’s scheduling isn’t complex, there’s more clicking involved. Again, Simplicity over Flexibility.

Email Alerts/Notification:

Although both tools provide email support, Hudson has a more detailed email report. Hudson allows the tracking of JUnit test reports for every test, while Continuum only provides notifications on failed or successful builds.

In the end, we decided to switch to Hudson because it is easier to use and it includes the Junit test reporting feature.

Note: The Continuum and Hudson logos are properties of Apache Continuum and Hudson, respectively.

Elegance in Approach

Another form of art in programming is the approach or architectural design. This topic requires strong technical background and experience, but still, designing your architecture requires artistic skills. There are many ways to skin a cat, so is there to design an architecture. Although design patterns help standardize approaches in software programming, decisions have to be made on which patterns to use, more so, to mix and match. Some patterns have similar purpose and overlaps, so choosing the best pattern requires some craftsmanship.

One major factor that affects architecture is the system requirements a.k.a. non-functional requirements, such as reliability, performance, maintainability and others. Having said that, I’m assuming that the functional requirements is already being taken care of and you are aware of what functionalities need to be supported… you’re now asking yourself how it should be supported.

Now, let’s go through some examples. When parsing a string for a certain pattern, do you use standard string operators (e.g. indexOf, substr) or regular expressions? Normally, you’d say regular expression will be easier - more readable and easier to maintain. However, there is a major performance degradation in regular expressions. So, if performance is important, you’d reconsider using indexOf. But then the maintaining such codes will be a nightmare. You might end up implementing your own parsing libraries using standard string operators - this will be a balanced between maintainability and performance. Such is a case of choosing the best approach, all solutions will perform the required functionality… but one will be better in some aspects than the other. Knowing which one works best requires some creativity and mastery. Thereby becoming your masterpiece.

There are so many scenarios that will let you weigh and analyze the different approaches, and there might be no perfect answer, only good answer. In any case, deriving the best possible approach requires some intuition, foresight and creativity. With so many factors to consider in choosing a design, you might as well leave it to your artistic skills to decide.

Many conceive that programming is a science of computational logic but that’s only half the truth. Programming is more than science, it’s an art. If you disagree, then you’re as good as someone fresh out of college - brainwashed on algorithms, computational complexity, and neural networks.

Let’s begin by putting things in proper context. Art, as defined in Wikipedia, is “a particular type of creative production generated by human beings” or in simpler terms “products of human creativity”. Such definition may have convinced you to agree, if not, then you’re likely a geek trying to find for the most efficient solution to the traveling salesman problem for the past 10 years.

Let’s cut the chase. So, what’s the art in programming?

Artistic Codes
There are many forms of art that can be expressed by your source code - and I’m referring to art as an aesthetic and visually stimulating piece - just like Picasso’s paintings or poems from Shakespeare.

Think of your source code as a masterpiece. Indention, comments, newlines, variable naming are your tools. All of these components must be balanced, easy to read, and inspiring.

The simplest form of art in your source code is “indention”. Block statements must be consistently indented thereby, making it easier to understand. Indention must also be equal in spaces - most Java programs are indented by 4 characters. Personally, I felt uneasy and can’t think clearly whenever I see misaligned codes. It just needs to get fixed otherwise, I won’t be able to think on the next steps.

“Comments” is another form of art but this requires a bit more creativity. Putting comments is not just rewriting what’s represented in the code, rather it must relate to a specific purpose. There is no need to describe the algorithm since its already shown in the code, instead explain the purpose of the code. Remember, comments are intended for humans to read so don’t write something in machine language. Here’s a classic example:

//loop the ArrayList
for (int i=0;i

instead try something more meaningful,

//let’s sum up all the values in the list
for (int i=0;i

The proportion of source codes to comments is also an art. If you’re writing more comments than the codes, then chances are the code is not readable and not well written. Unless of course you’re trying to write for efficiency. To illustrate:

// let’s get the middle index
mid = (max+min) >> 1;

While the code above can be easily understood using mid = (max+min)/2, you may want to use the shift operator since it takes less CPU time to shift the memory register than do a division.

The third form of art in your source code is “naming”. Choosing the right name can take a lot of thinking time. The worst variable names are generic x and y. Always use something more meaningful to make your codes more readable. More importantly, make sure the names are representative of its purpose.

For example, what variable name would you assign to “number of records per page”?

  • numberRecords. This can be interpreted a total number of records, or record number.
  • recordsPage. This can be interpreted are the page number or a list of records, or something else.
  • numRecordsPerPage. Might work, but probably too long.
  • recordsPerPage. The preferred name.

Again, it’s an art so there are no hard and fast rules how to name variable or method names. But always make sure that the names well represent it’s purpose otherwise, it can get confusing when you start debugging your source codes.

A requirements document is a very powerful tool if used properly. This maybe the most hated task of developers, yet it is essential. As the saying goes - “Do the right things, then do things right“. Requirements documentation helps ensure that developers are doing the right things, before they do it right. Although new methodologies have been developed to reduced documentation, I still believe that requirements document should be maintained throughout the project cycle.

Some benefits of proper requirements documentation are:

  • Serves as a tool to communicate with various stakeholders. This document will help you ensure that all stakeholders are aware of the project requirements. Any conflicts on the requirement with various stakeholders must be resolved and documented here.
  • Validates the project objectives. The requirements listed in the document can be mapped against the project objectives to see if they are met.
  • Helps uncover loopholes, defects in the requirements. Defects due to requirements are costly if not uncovered early during the project cycle. This is because you have to go back and change the requirements, update the design, test scripts, source codes and retest the application. So, well thought and well written requirements will definitely save you time and money in the long run.
  • Serves as your bible for the rest of the project activities - analysis, design, programming and testing. All activities performed in the project should be associated to a requirement as listed in this document. Otherwise, you might be doing something that is not needed.

I am not recommending any specific process in performing requirements gathering. In my years of experience, I have seen various methods of eliciting requirements from client and there is no universal way of getting it. So, it really depends on the client’s role, knowledge, authority, attitude, working habits, among others. Nevertheless, I believe that there needs to be some standard form of organizing requirements - that is… I believe in establishing standard template to document requirements. It doesn’t really matter how you collect and elicit requirements, as long as you write it down in a standard format that everybody in your project understands.

Here is the Requirements Document Template that we use during requirements gathering. This template is a simplified version of Volere Requirements Template and has been customized to fit our needs. Some items in the template may not be relevant to other projects - in such case, specify none instead of removing the section.