If you want your open source project to succeed, write good documentation… or just have a bunch of people blog about it and do it for you.
I have recently been playing around with Apache Ivy and trying to get it to work. Yes, I’ve looked at Maven. To be honest, I don’t want / need a build system. Right click export is how I build and while that my seem crude to you, I really only release every two or so weeks. And, I full expect my CI to do my building and deploying for me (more in a later blog post).
When hunting down a dependency management system, these were the objectives I set out to conquer;
- Allows for privately hosted repository. Huge bonus points for being able to run this off an S3 web enabled bucket.
- Setting dependencies and configuration is easy and minimal. I hate xml, but hey, it’s ok for now.
- A cloud based service would be nice, but running my own would be fine as well. As long as I can host it off S3.
- Integrates well with eclipse / WTP. No command line here. IDE support is a must.
- Can pull down more than just jar files. I would like to expand this beyond the server side and potentially use it in our client side (flex / html5) projects.
But, enough talk, let’s get to it. Btw, this is all assuming your using
IvyDE.
1. Let’s get a basic ivy file going in our project;
{project_home}/ivy.xml
<?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="yourorg" module="yourproject"/>
<dependencies>
<dependency org="commons-lang" name="commons-lang" rev="2.0"/>
</dependencies>
</ivy-module>
The <info /> tag here is really of no consequence. It just tells Ivy what this file is for. We’ll see later how this fits in when we create our own repository.
The <dependencies /> tag is the meat of what we want. Here you can line item your dependencies that are included into your project.
Now, IvyDE includes some default settings;
- It will use the public ibiblio maven repository,
- It will automatically resolve (attempt to download) dependencies once you save the ivy file in your project,
- In your project library settings, you can simply choose to use the ‘ivy’ library and the plugin will realize you want the dependencies you’ve defined in ivy.xml to be included in your project build path.
With that being said, if you include the above line it might actually start downloading and resolving commons-lang. Btw, the org for commons-lang might need to be set to apache. But, we’ll see later about that.
2. Let’s write our own ivy settings file;
Now we can resolve dependencies (or maybe you’re stuck already) against the default settings, but what about resolving against our own settings file.
You can create an ivysettings.xml file that will allow you to tell Ivy what repositories to use when looking for dependencies. Here is a basic one.
ivysettings.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<ivysettings>
<property name="repo.url" value="http://repo.wookets.com"/>
<settings defaultResolver="myrepo"/>
<resolvers>
<url name="myrepo">
<ivy pattern="${repo.url}/[organisation]/[module]/ivy-[revision].xml" />
<artifact pattern="${repo.url}/[organisation]/[module]/[artifact]-[revision].[ext]" />
</url>
</resolvers>
</ivysettings>
You can place ivysettings.xml right next to your ivy.xml project file. Or, you can place it elsewhere. In IvyDE you simply go into your eclipse preferences -> ivy -> settings and change the location. Here is an example of my string; ${workspace_loc:TestIvy/ivysettings.xml} Where TestIvy is my project.
The settings file we’re using is intentionally non-complex. Ivy has a bunch of conf and namespace type stuff, but let’s keep it simple until we run into a problem and then adapt, rather than configuring things for the sake of configuring them.
The <property /> tag abstracts out repo.url. You can include this or not or add more.
The <settings /> tag is used to define a defaultResolver. In our case this is our private repository with our jar files.
The <resolvers /> tag is used to define our repo. There are a few more options for this tag… chaining, etc, but again, keep it simple.
The <url /> tag finally defines our repository. <ivy /> will resolve to the ivy file (see the next step) and <artifact /> will define the pattern to reach our files.
3. Let’s create our own repository using ivy files and jars;
Remember in our first step where we created our ivy.xml file and set stuff on the <info /> tag. Well, here is where that comes into play. ivy.xml tags are used to both define dependencies AND publish dependencies. It’s a little tricky, but ivy.xml files allow you to pull in jars and also pull together jars for other ivy.xml files.
So, here is an example of an ivy.xml jar that is publishing and also defining dependencies, which will resolve to their own ivy.xml files.
{repo}/spring/all/ivy-3.0.5.RELEASE.xml
<?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="spring" module="all" revision="3.0.5.RELEASE"/>
<publications>
<artifact name="org.springframework.aop" ext="jar" />
<artifact name="org.springframework.asm" ext="jar" />
<artifact name="org.springframework.aspects" ext="jar" />
<artifact name="org.springframework.beans" ext="jar" />
<artifact name="org.springframework.context" ext="jar" />
<artifact name="org.springframework.core" ext="jar" />
</publications>
<dependencies>
<dependency org="apache" name="commons-beanutils" rev="1.8.0"/>
<dependency org="apache" name="commons-logging" rev="1.1"/>
</dependencies>
</ivy-module>
First, you need to realize that the pattern we defined in ivysettings.xml is used to find this ivy.xml file. You can change ivysettings.xml and make the pattern more simple or more complex. It’s up to you.
Next, realize that this is just an ivy.xml file. Just like the one from step 1. Except, we have a <publications /> tag here that defines artifacts. Artifacts are jar or any other type of file that you want to have eventually downloaded into your project.
And since this is just an ivy.xml file, we can of course include <dependencies /> which will use our ivysettings.xml to resolve themselves to the proper location.
Now, all of these files I’ve presented probably won’t work together. But, how ivy.xml files are linked is by the following…
<dependency org=“” /> resolves itself to <info organisation=“”/> in another ivy.xml tag.
<dependency name=“”/> resolves itself to <info module=“”/> in another ivy.xml tag.
<dependency rev=“”/> resolves itself to <info revision=“”/> in another ivy.xml tag.
And, all of these are used in our ivysettings.xml patterns to resolve the file path.
You don’t need any special software or to run any ant build type stuff (if you’re using IvyDE), so it isn’t too bad. The files can be created by hand. There are ways to import existing repositories, so you don’t have to create as much. Me, I like to start fresh and clean.
I hope this has helped make Ivy a little bit clearer… It is really simply actually, but I don’t think the documentation is that great. A diagram or two would be nice. Perhaps in the future I will make one… But for now, I need to catch some sleep.
Btw, sorry about the lacky of script / xml styling… Still need to fix that… It’s on my todo list…