[ImageJ-devel] [fiji-devel] Re: New imglib2-algorithms-legacy

Johannes Schindelin Johannes.Schindelin at gmx.de
Tue Jul 10 12:50:12 CDT 2012


Hi Curtis,

On Tue, 10 Jul 2012, Curtis Rueden wrote:

> On Tue, Jul 10, 2012 at 11:21 AM, Johannes Schindelin
<
> Johannes.Schindelin at gmx.de> wrote:
> > I will make a branch with a simple pom and will be on Skype later.
> > Fair ennough?
> 
> I have done this for imglib2-algorithms-legacy and pushed to master.

Darn, you beat me to it! ;-)

But that gives me more time to explain what it takes to make a new Maven
project.

All it really takes is a pom.xml file and a certain directory structure.
Technically, you can override the default directory layout in the pom.xml,
but why do so? It only breaks expectations and is more hassle than it is
worth, really.

So the directory structure is: you put your .java files under
src/main/java/ and the other files you need to be included into
src/main/resources/. Should you want to apply the best practices called
"regression tests" or even "test-driven development": your tests' .java
files go to src/test/java/ and the non-.java files you might require
unsurprisingly into src/test/resources/.

So what does a pom.xml look like? This is a very simple example:

	<?xml version="1.0" encoding="UTF-8"?>
	<project xmlns="http://maven.apache.org/POM/4.0.0"
			xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
			xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
			http://maven.apache.org/xsd/maven-4.0.0.xsd">
		<modelVersion>4.0.0</modelVersion>

		<groupId>sc.fiji</groupId>
		<artifactId>my-uber-library</artifactId>
		<version>2.0.0-SNAPSHOT</version>
	</project>

The first 6 lines are of course just a way to say "Hi, Maven? How are you
today? This is what I would like you to do:".

The only relevant parts are the groupId, which by convention is something
like the inverted domain name (similar to the Java package convention),
the name of the artifact to build (it will be put into target/, under the
name <artifactId>-<version>.jar). And of course the version.

Now, why did I bother so much with Mavenization of Fiji? The real reason
is that Maven is not only a build tool but first and foremost a dependency
management tool. Maven has so-called Maven repositories where it stores
compiled artifacts. ImageJ2's Maven repository lives here:
http://maven.imagej.net:8081/ (most functions can be accessed via
http://maven.imagej.net/ just as well). It is like Fiji's precompiled/
directory, but done right.

Next, for Maven to know what you are looking for, you typically have to
add the dependencies into the pom.xml file. For example, every ImageJ 1.x
plugin will depend on ImageJ 1.x. So let's add that (before the final
</project> line):

	<dependencies>
		<dependency>
			<groupId>net.imagej</groupId>
			<artifactId>ij</artifactId>
			<version>1.45b</version>
		</dependency>
	</dependencies>

As you can see, dependencies are referenced under the same groupId,
artifactId and version triplet (also known as GAV parameters) that you had
to declare for the current project.

For Maven to find the dependencies, it has to know about the location of
the repositories. As you know, we are strong proponents of collaboration
within the scientific community, so we started the scijava effort last
hackathon in December. To this end, Curtis began the scijava "super POM"
which is supposed to declare repositories we use (and other metadata as
well, such as current artifact versions we provide). To benefit from this
in your project, add this to your pom.xml:

	<parent>
		<groupId>org.scijava</groupId>
		<artifactId>pom-scijava</artifactId>
		<version>1.15</version>
	</parent>

	<!-- NB: for project parent -->
	<repositories>
		<repository>
			<id>imagej.releases</id>
			<url>http://maven.imagej.net/content/repositories/releases</url>
		</repository>
		<repository>
			<id>imagej.snapshots</id>
			<url>http://maven.imagej.net/content/repositories/snapshots</url>
		</repository>
	</repositories>

You will see that there are two different repository types: releases and
snapshots. The snapshot versions are "in-progress" versions. If you
declare a dependency with a "-SNAPSHOT" suffix in the version, Maven will
look once a day for new artifacts of the same versions; otherwise, Maven
will look whether it has that version already and not bother
re-downloading.

So what if you have multiple .jar files you want to build in the same
project? Then these need to live in their own subdirectories and there
needs to be a common parent POM, a so-called "aggregator" POM. For an
example, look at Fiji's src-plugins/pom.xml. Basically, it is adding the
<packaging>pom</packaging> entry as well as a couple of subdirectory names
to the <modules> section.

There are many more things you can do with Maven, but chances are you will
not need them.

The simplicity of the pom.xml you need comes from the fact that Maven
defines implicit defaults. It calls that "convention over configuration".
But since we are not converting projects (or at least since we are
flexible enough to adapt), I would strongly recommend staying with the
defaults as much as possible. It also makes your project more accessible,
something that I think we excel at.

Now, in the context of scijava, you will most likely never write a pom.xml
from scratch. You will rather more likely edit an existing one, possibly
after having copied it.

Ciao,
Dscho



More information about the ImageJ-devel mailing list