Thursday, 31 January 2008

Building Eclipse RCP applications using Maven

Still experiencing some problems following the Codehaus tutorial. Downloaded the examples and unpacked them without problems into the correct directory structure in my workspace, but then found that Eclipse doesn't recognise the three examples as Java projects even after running mvn eclipse:eclipse on them. Moreover, trying to build the plugin using mvn clean install site produces the sad error message:

...\target\eclipse\startup.jar not found.
Have you set up your -DeclipseInstall?

My first thought was that my initial assumption must have been false (that it would be unnecessary to download the RCP Runtime and Delta Pack as detailed in the Codehaus tutorial, because we had started with the Eclipse RCP Developer edition). So I downloaded and unzipped them to a nice little target/eclipse folder of their own, and adjusted the three example POMs accordingly. While this is undoubtedly a Good Thing, because it masssively reduces the size of the exported product, it didn't magically cause a startup.jar to appear.

Luckily, René Gröschke has posted a commentary on the Codehaus tutorial, identifying where it leads the student astray. Luckily I can read German. I'll try to post here what I find out.

Friday, 25 January 2008

Where's the system bundle jar file? (cont.)

Well, you probably won't be surprised to learn that the result is no different using the latest maven-eclipse-plugin version 1.5-SNAPSHOT, dated 30th November 2007. I had to create an entire Maven project to invoke the to-maven goal on the maven-eclipse-plugin, just so that I could specify the version I wanted to run. But this should be quite a useful asset in the long run anyway: I can now type

mvn install

or

mvn deploy

to invoke the corresponding actions. At the moment, however, there is no way to get beyond any plugin whose MANIFEST.MF specifies system.bundle as a required bundle.

The OSGI Bundle Repository Browser confirms that system.bundle does in fact refer to the org.eclipse.osgi jar file. I therefore decided to supply the missing artifact, by using file:deploy-file to create it from org.eclipse.osgi...jar. I added this to the POM of my eclipse-to-maven project and linked it to the initialize phase.

It still doesn't work. For some reason, because the Require-Bundle instruction in MANIFEST.MF does not specify a version number, the maven-eclipse-plugin cannot find the artifact I created. It tells me that it was unable to resolve the version range for version [0,).

So as an experiment, I altered the MANIFEST.MF of the Xerces plugin to explicitly require the actual version number of the org.eclipse.osgi bundle - and hey presto, this was resolved successfully. But we really can't go through all manifests of all Eclipse plugins every time we want to run this plugin and update the system.bundle requirement!

This must be a bug in the maven-eclipse-plugin (caused by a documented incompatibility between Eclipse 3.2 and 3.3, which has led a number of bundle committers to add "Require-bundle: system.bundle" to their manifests), so I have submitted a bug report about it.

In fact, on closer investigation it transpired that there are currently only two Eclipse plugins that fall into this category: org.eclipse.xerces and org.eclipse.xml.resolver. In fact it wasn't even necessary to create a system.bundle artifact - I just altered the two manifests temporarily to express a dependency on the exact version of the org.eclipse.osgi plugin supplied with the Eclipse installation in question. With this modification, the eclipse:to-maven goal was able to run successfully to completion.

On to the next stage! But first, there is a weekend to take care of...

Where's the system bundle jar file?

Quick update to my last posting: a number of Eclipse plugins have recently sprouted this RequireBundle attribute thanks to a published incompatibility between Eclipse 3.2 and 3.3 in the area of Boot Delegation.

It looks as if the System Bundle is either mapped to org.eclipse.osgi or doesn't really exist as a separate jar file in its own right at all. Maybe there's a newer version of the Maven Eclipse plugin that understands this?

Creating Maven artifacts from Eclipse plugins

Along the long and tortuous road of creating Maven builds for Eclipse RCP applications, one of the first steps is to take the Eclipse plugins that make up the target platform and convert them into Maven artifacts. This ensures that the Maven POM is able to refer to them by its holy triad of group ID, artifact ID and version.

In the Maven Eclipse Plugin, a goal eclipse:to-maven is provided that is meant to satisfy exactly this need. Given an Eclipse installation directory, it trawls through all the plugins it can find and installs them in your local Maven repository, even generating POMs that correctly show interdependencies between plugins. If you optionally specify a deployTo parameter, it will even deploy the resulting artifacts to a remote repository for everyone on your project to use.

When I tried this for my Eclipse RCP installation, however, it failed. There were two versions of the plugin org.apache.xerces in the plugins folder, and Maven could not resolve which of them to turn into a Maven artifact. This might not have been a problem but for the fact that the version numbers of both were the same (2.0.8) apart from the timestamp - one was a folder, the other a self-contained jar file.

The same problem has also been encountered by others - e.g. when trying to use the slightly older but equivalent eclipse:make-artifacts goal.

Having checked in the Eclipse Plugin View that there was nothing dependent on it, I removed the older of the two Xerces plugins. The to-maven goal was now able to run - but the build still didn't complete (see below).

I consider this to be a bug in the Eclipse RCP distribution version 3.3.1.1. Despite a lengthy discussion in the bug tracker five years ago, nothing appears to have been done. I have accordingly lodged a new bug report and we'll see whether this gets fixed in a future release.

The new problem now is the generated POM for org.apache.xerces. For some reason the Maven eclipse plugin is unable to determine the version number of some dependency (the error message doesn't make a lot of sense):

[INFO] Unable to resolve version range for dependency
Dependency {groupId=system, artifactId=bundle,
version=[0,), type=jar} in project org.apache.xerces

Inspection of the MANIFEST.MF in the Xerces plugin jar file reveals:

Bundle-Version: 2.8.0.v200705301630
Require-Bundle: system.bundle,org.apache.xml.resolver;
visibility:=reexport

So that is why Maven can't be sure what version is wanted. Luckily, this particular artifact is already in the Maven central repository, so to short-circuit all this I removed the Xerces plugin jar temporarily as well and re-ran the Maven command.

To my surprise, the build failed this time with the following message:

[INFO] Unable to resolve version range for dependency
Dependency {groupId=org.apache, artifactId=xerces,
version=[2.8.0,3.0.0), type=jar}
in project org.eclipse.wst.xml.core

This makes no sense, since version 2.8.0 of org.apache.xerces clearly does exist in the central repository. Maybe Maven doesn't consider 2.8.0-v200705301630 to be in the above range?

So I tried another tack: restore the older Xerces plugin to the Eclipse plugins folder. This time the Xerces plugin is successfully installed in the local repository, and the plugin org.eclipse.wst.xml.core likewise. Instead, the build fails a bit later with:

[INFO] Unable to resolve version range for dependency
Dependency {groupId=system, artifactId=bundle,
version=[0,), type=jar}
in project org.apache.xml.resolver

This is exactly the problem that the Xerces plugin failed on in the first instance. So I suspect that I'm going to have to find out how to create a Maven artifact called system.bundle. Watch this space.

Wednesday, 23 January 2008

Build Eclipse RCP products using Maven 2 - how hard can it be?

I am working as part of a project team developing a suite of applications that use Eclipse RCP as their platform. We are also using CruiseControl for continuous integration and testing. We currently build Eclipse RCP products, features and fragments using Eclipse PDE, partly because of its OSGI support. We would like to move to using Maven 2 in order to match the way we build all our Eclipse plugins and Java libraries. This will make it straightforward to generate comprehensive documentation on the Web, stay in control of dependencies, link into our bug tracking and progress tracking system and so on.

A parallel initiative is my attempt to set up the Eclipse development environment for each team member so that Maven builds and Eclipse builds work seamlessly together on the workstation. Initially I thought that this would require the use of the Maven 2 Integration for Eclipse plugin. However, it turned out that even this is not nearly as closely integrated into Eclipse as Ralf Quebbemann's equivalent Maven 2 Integration is integrated into IntelliJ IDEA, for example. We found it easiest to configure various Maven goals as "external tools" in Eclipse's Run menu and to use the Maven eclipse plugin to generate or update the Eclipse classpath and project files (mvn eclipse:eclipse).

[Footnote: mvn eclipse:configure-workspace works during installation, but only if the configured Maven repositories are online, which rather defeated my objective of creating a standalone developer kit installer. I found that this goal simply inserts a definition of the M2_REPO classpath variable into one of Eclipse's metadata files, so I made the installer do that directly instead. It now runs much faster too.]

Despite the existence of the book Better Builds with Maven, a common complaint about Maven 2 is that it is not sufficiently well documented for heavy-duty use. The book was last updated in August 2007, since when two further releases of Maven have come out. The book doesn't mention Eclipse RCP or PDE. In trying to marry the use of Maven with Eclipse, we are very much having to hoe our own furrow.

I'm using this blog to record the approaches we take and how we fare. Hopefully after a few weeks (not too many!) it will be possible to summarise all the findings into a "how to" for future reference.

My current understanding is that the most promising approach would be using a combination of the maven-eclipse-plugin (with the PDE property set to true) and the pde-maven-plugin. These allow us to create the Eclipse project and classpath files slightly differently in order to permit "headless" PDE builds to take place. As I understand it, the PDE Maven plugin generates an Ant build file that can then be used to run the headless PDE build. There are a few wrinkles; for example we may have to obtain a more recent snapshot of the pde-maven-plugin because the last official release doesn't appear to work with Europa.

One project which does appear to have been successful in building RCP products using Maven is jLibrary, an open source document management / content management system. Martin Perez and Ryszard Petrowski have documented their build approach for jLibrary 1.2. I intend to study this and learn from it. More anon!