A new Sakaiger is born!

Those who follow me on Twitter or Facebook may have seen my recent posts and photos about the birth of my first child, Dexter James Swinsburg. Little Dex was born into this world at 7:36am on 19/10/2009; both mum and him are doing well. His first cries certainly sounded like Maven, Wicket and Java, but it might have just been waa waa, hic hic and gaga!

Advertisements

Binary deployment of your Sakai tool: Part I

This is the first in series of two articles that will cover the binary deployment of tools in Sakai. In this article we will get your project ready, first by polishing the Maven POMs.

An issue in Sakai today is that there is no real standard for how the Maven coordinates of a project (artifactId, groupId) should be laid out. You can give your POMs any value, it will still build and everything will be fine. You might run into an issue if other people need to depend on your project though the main issue is how it’s arranged in the repositories.

A quick glance in your ~/.m2/repository directory and you’ll notice that most projects are under the org/sakaiproject umbrella, which is great, but from then on its a free-for all. Some project’s main POMs are appended with ‘-base’, some are not, some are prepended with ‘sakai-‘, others are not, and there is even a mix of the two approaches within projects.

It’s a bit of a hassle when you are trying to find a group of artifacts for a project and and delete them so you can rebuild properly, often you just end up deleting the whole org/sakaiproject directory and rebuilding the lot. It also causes issues if you import a Sakai project into Eclipse, you’ll get the project being called whatever the base-pom’s name is.

What this article will cover is how to setup your poms to give them more structure in the repository. We’ll actually be following the Maven standard.

First up, the groupId. Most POMs in Sakai currently have org.sakaiproject as the groupId. This is fine but will cause the repository layout to be spread out as in the image below:

What is suggested is to append your particular project name to the org.sakaiproject groupId to make it unique.
For example:
<groupId>org.sakaiproject.profile2</groupId>

This will be consistent throughout the project’s POMs (ie the base POM, API, Impl, Pack, Tool and Util all have the same groupId), but different between projects, ie, SiteStats has:
<groupId>org.sakaiproject.sitestats</groupId>

This is the most important change you may need to make. You can even skip the next section if you like because its just a further refinement.

Next up is the artifactId. As recommended by Maven, the artifactId should be “the name that the project is known by”. In the case of the parent POM, this will be the name of the project, ie profile2 or sitestats or whatever your project is called. This is where a lot of projects prepend ‘sakai-‘ or append ‘-base’; this is unnecessary, the groupId already identifies that it’s a Sakai project.

For submodules in a project, the artifactId should simply be something like profile2-api or profile2-impl. These need to be unique amongst all submodules in this groupId so the -api and -impl appendages perform that purpose. Most projects are already setup this way so shouldn’t need much changed. Again, its unnecessary to prepend the ‘-sakai’ part but you can if you like.

Below is an extract from two POMs in Profile2, to illustrate some of these naming conventions discussed above:

The base POM:

<groupId>org.sakaiproject.profile2</groupId>
<artifactId>profile2</artifactId>
<packaging>pom</packaging>
<version>1.3-SNAPSHOT</version>

The API submodule POM, showing its own artifactId as well as the parent:

<groupId>org.sakaiproject.profile2</groupId>
<artifactId>profile2-api</artifactId>
<packaging>jar</packaging>

<parent>
<groupId>org.sakaiproject.profile2</groupId>
<artifactId>profile2</artifactId>
<version>1.3-SNAPSHOT</version>
</parent>

Performing these small POM maintenance tasks will mean the repositories are arranged much better. Compare the following diagram with the first:
Note that all artifacts for a particular project are now grouped together, rather than being lumped in with every other project’s artifacts.

Note that you’ll need to be careful in changing the POMs if any other projects depend on your project as they will also need to have their POMs updated to point to your new layout.

Next up, creating an assembly module for your project so it can be deployed as a binary artifact automatically.

Binary deployment of Sakai

If you ever use the cafe version of Sakai, you’ll know that if you want to add another tool into the mix, you often need to bring in half a dozen other projects just to get it to build because the dependencies were so interwined with each other, aka Dependency Hell. That is all beginning to change with the rationalisation of many dependencies into ‘mini-kernel’ type packages of common functionality so that we have fewer distributed services hanging around, and more pluggable modules.

We are also now seeing binary deployment of projects. Up until now, if you wanted to add a contrib project into your build you would have to check it out of SVN, resolve any dependencies for it, read up on any POMs you may need to change to get it to build in your environment, issue a maven clean install and see what happened. To the battle hardened Sakai developer, relatively painless but nonetheless a bit more involved than it need be.

Enter binary deployment. Using this, you never need to even look at the source, let alone check it out and build it. So long as the artifact has been assembled and added to the repository, you can add a few simple lines to a POM and get it to automatically download and deploy the project. Better yet, using a build profile, you can have complete control what tools get deployed. Here’s how:

Let’s say I want to add SiteStats to my build. Luckily, some savvy developer has already generated the artifact and added it to the Maven repo. I first created a separate POM that tracks all of these additional tools and I include that as a module to build in my base Sakai POM, then just add this to the custom POM to add the SiteStats binary:

<profile>
<id>sitestats</id>
<properties>
<clean.targets>
components/sitestats-component
</clean.targets>
<deploy.target>tomcat-overlay</deploy.target>
</properties>
<dependencies>
<dependency>
<groupId>org.sakaiproject.sitestats</groupId>
<artifactId>sitestats-assembly</artifactId>
<version>2.1-SNAPSHOT</version>
<classifier>tomcat-overlay</classifier>
<type>zip</type>
</dependency>
</dependencies>
</profile>

Then issue the build via:
mvn clean install sakai:deploy -Psitestats

and through the power of Maven voodoo (and the Assembly Plugin), the dependencies are downloaded from the repository as a Tomcat overlay, installed into your local repo, then deployed into Tomcat. Double up on the profile block for another binary tool and you can install that one as well:

mvn clean install sakai:deploy -Psitestats,otherone<

For this example you’ll need to make sure you have the snapshots repo added either to your master Sakai POM, or locally. Trunk and the maintenance branch of 2.6.x have this already, for tagged released (ie 2.6.0) adjust the master POM so that snapshots are enabled:

<repositories>

<repository>
<id>sakai-maven2-snapshots</id>
<name>Sakai Maven Repo</name>
<layout>default</layout>
<url>http://source.sakaiproject.org/maven2-snapshots</url&gt;
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>

</repositories>

This isn’t new, the Kernel has been using binary deployment for a while, but with the proliferation into other tools and contrib projects, the life of the Sakai developer is certainly going to be easier.

Much kudos to Anthony Whyte for creating and adding the core-deploy POM to trunk, David Horwitz for the assembly work, and Nuno Fernandes for porting SiteStats to Wicket!

Next up, how to get your own project ready for binary deployment using the Maven Assembly Plugin.