Max Did It
Coding
,Thu
2 Comments
Tagged ,

Committing Artifacts with Ivy

In my last post, I talked about the build automatisation tool Apache Ant. Ant originated as a tool for Java developers and has been succeeded by Maven, which provides many nice features like dependency management.

Imagine you wouldn’t have to download and copy any libraries into your project path and configure the classpath every time you start a new project or a new version of a library comes out. What if you had a tool that did that automatically for you? Maven does that, and more.

The Trouble With Flash And Maven

I guess for a Java developer there is currently no good reason to use Ant instead of Maven, but if you work with Actionscript or Flex, things are a little more complicated. Right now, FlexMojos is the only current plugin for Maven that allows you to compile SWF or SWC files.

Now, when FlexMojos happens to do what you want it to do, it’s great! It’s convenient and you can set up projects with unit tests and code coverage very quickly. However, if FlexMojos doesn’t do what you expect it to, and that still happens quite often, you will have a very hard time figuring out what the problem is and how to fix it.

Because of this, I decided to keep using Ant to build my Actionscript projects for the moment. However, you can use Maven’s automatic dependency management feature in Ant build scripts as well.

Apache Ivy

Apache Ivy LogoApache Ivy is a dependency management system that can be used together with Ant. You could call Ivy a bridge between Maven and Ant, since you can use Ivy to download dependencies from Maven repositories.

You can also use Ivy to upload your own artifacts to a repository. Not only that, but Ivy can maintain it’s own local repository, which gives you the opportunity to work without Maven entirely.

Committing Artifacts with Ivy

In this article, I want to show how I commit SWC library files to my local Ivy repository. After committing an artifact like a SWC library to a repository that can be accessed by Ivy, you can then use it as dependency in other projects. I assume that you already have downloaded and set up both Ant and Ivy.

As described in my previous post, I have taken up on separating my Ant build scripts into several central files which I then include in the actual build.xml as needed.

I did so with my Ivy targets as well, putting them into ivy-targets.xml.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0"?>
<project xmlns:ivy="antlib:org.apache.ivy.ant"
		 name="ivy-targets"
		 default=""
		 basedir=".">
 
	<!-- Path to Ivy Home -->
	<property name="ivy-home"
			  location="${env.TOOLS}\apache-ivy-2.3.0-rc1" />
 
	<!-- Define Ivy Ant Tasks -->
	<path id="ivy.lib.path">
		<fileset dir="${ivy-home}"
				 includes="*.jar" />
	</path>
	<taskdef resource="org/apache/ivy/ant/antlib.xml"
			 uri="antlib:org.apache.ivy.ant"
			 classpathref="ivy.lib.path" />
 
	<!-- Targets -->	
	<target name="publish">
		<!-- Check if expected properties are set in the including file -->
		<fail unless="target-dir" />
		<!-- resolve, deliver and then publish artifact -->
		<ivy:resolve refresh="true" showprogress="true"  />
		<ivy:deliver />
		<ivy:publish resolver="local" overwrite="true" artifactspattern="${target-dir}/[module]-[revision].[ext]" />
	</target>
</project>

The first half of the file is more or less taken from the Apache Ivy reference on Ant tasks. Here, I

  • set up the Ivy namespace in the project tag,
  • define the path to my local Ivy folder and
  • define the Ivy ant tasks.

The last bit in the file is the actual target that publishes the artifact to the Ivy repository. This assumes that you have already built your artifact, for example with the targets described in the last post.

Before you can publish your compiled files, you need to resolve the dependencies first and then deliver the resolved descriptor of the current module. The descriptor is an automatically generated XML that gives Ivy the necessary information about the project.

Take note that the publish Ant task can perform the deliver step automatically. I had put the deliver task in there explicitly when I had trouble to get the publish task to run and wanted to eleminate sources of error. Now it works, and I don’t see any reason right now to tinker with it any further.

The artifactspattern property of the ivy:publish tag tells Ivy where to look for files that should be published to the repository. The target above assumes that the compiled files follow the pattern [module]-[revision].[ext]. That means that the first element of the file name is the name of the project/library, the second is the version number and the last one is the file extension, for example linkedlist-0.0.1.swc.

The ivy.xml File

Before you can actually publish the SWC file, you have to give Ivy a little more information yet. Notice, for example, that the variables used in the artifactspattern above are not defined anywhere. These information are taken from the ivy.xml file that should be present in every project using Ivy.

This file tells Ivy what name the artifact has, what version it is and in what organisation folder to store it. This basically follows Maven’s standard of organising it’s artifact repository. While the above XML file containing the Ant tasks is stored centrally, the following example for an ivy.xml is project specific and is usually found in the same folder as the project’s build.xml.

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<ivy-module version="2.0">
	<info organisation="de.maxdidit"
		  module="${artifact-name}"
		  revision="${version}">
	</info>
</ivy-module>

Not so bad, is it? This assumes that our project doesn’t require any dependencies yet, which would be listed in the ivy.xml as well.

Also, take note of the Ant properties used for module and revision. You can actually use properties used in your build.xml in your ivy.xml, which is neat.

However, using this XML would cause the following error in our case:

impossible to publish artifacts for de.maxdidit#linked-list;0.0.1: java.io.IOException: missing artifact de.maxdidit #linked-list;0.0.1!linked-list.jar

Ant and Ivy originally are tools for Java developers and so Ivy assumes that any artifacts we want to publish must be JAR files. You need to tell Ivy explicitly that the files which you want to publish have a different type. You can do that with the artifact tag.

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<ivy-module version="2.0">
	<info organisation="de.maxdidit"
		  module="${artifact-name}"
		  revision="${version}">
	</info>
	<publications>
		<artifact name="${artifact-name}-${version}"
				  type="swc"
				  ext="swc" />
	</publications>
</ivy-module>

Now our build should be executed successfully.

The Result

If everything worked out, executing the publish Ant task should upload our library into our local repository. That also means that, if necessary, Ivy will create all necessary folders and even the repository folder itself automatically.

Under Windows, you can find the local repository under C:\Users$$!USERNAME]\.ivy2\local. In my case publishing my library automatically created this folder structure:

Ivy Folder Structure Ivy will automatically create new folders for every new version number and store the respective artifacts there. Then, I can access these folders in other projects depending on these libraries.

Next Up

In my next posts, I want to show how to let Ivy resolve and copy dependencies to your project folder automatically and how let ivy.xml files inherit properties from other, “parent”-Ivy XMLs.

Comments

2 Comments have been posted so far - Leave a Comment

Aris J. Green
,Thu

Thanks for the article, I have been using Ivy for .NET builds and have only used file system repositories for Ivy. I tried Artifactory OSS, but they make you use the paid version if you want to change your repository layou as I explain in a blog post/rant here. Apache Archiva and Nexus OSS seem to require you to use Maven 1/2. For .NET project, not so good. Do you know of any build archive repsoitories that are free and do not require Maven?

Reply

Max Knoblich
Max Knoblich
,Fri

I have to admit, I don't use any dedicated build repository software so far.

But, Apache Ivy basically uses the same parameters and properties for artifacts as Maven, even though they are named differently.

I know for a fact that you can download dependencies from a Maven repository via Ivy, maybe you can use it to commit artifacts as well?


Leave A Comment

Your email address will not be published. Required fields are marked *

Connect with Facebook

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>