Maven packaging for libmatthew-java

Rationale

maven-dbus-plugin needs to use dbus-java which needs to use unix-java, written by Matthew Johnson. On some distributions (e.g. RedHat, Debian) Matthew's software is available from standard package repositories. However,

  1. in order to satisfy maven-dbus-plugin dependencies,
  2. for those who need to create complete release packages,

I have packaged Matthew's software and deployed it to Maven Central. My libmatthew-java fork can be found at Bitbucket.

In order to make use of these libraries, you need to teach Maven a few tricks.

The dependency

In order to make use of unix-java from your Java code, you need a dependency. Nothing fancy about it:

<dependencies>
  <dependency>
    <groupId>cx.ath.matthew</groupId>
    <artifactId>unix-java</artifactId>
    <version>0.5</version>
  </dependency>
</dependencies>

Getting the native lib

Next, you will need to fetch and unpack the JNI that allows your JVM to actually do domain sockets. This has two steps. First, we need to figure out the so-called "aol". The native part of unix-java is built using maven-nar-plugin. It uses <architecture>-<os>-<linker> to identify target platform. The first two Maven know about, but there is no way for Maven to know about the linker name (and no way to tell the Nar plugin to mend its silly ways). Since, we probably need to refer to this part several times, a property is in order:

<properties>
  <aol>${os.arch}-${os.name}-gpp</aol>
</properties>

In order to run tests against it and to repack it later, we ask the dependency plugin to fetch and unpack the native bits for us. Each platform version is identified by a unique classifier using the form <aol>-jni.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <executions>
    <execution>
      <id>copy</id>
      <phase>compile</phase>
      <goals>
        <goal>unpack</goal>
      </goals>
      <configuration>
        <artifactItems>
          <artifactItem>
            <groupId>cx.ath.matthew</groupId>
            <artifactId>unix-java</artifactId>
            <version>0.5</version>
            <type>nar</type>
            <classifier>${aol}-jni</classifier>
            <overWrite>true</overWrite>
            <outputDirectory>${project.build.directory}</outputDirectory>
          </artifactItem>
        </artifactItems>
      </configuration>
    </execution>
  </executions>
</plugin>

The unpacked lib will now show up in your build directory, under lib/<aol>/jni, from whence it can be referenced or repackaged.

I normally use Maven 3. When I tried this with Maven 2.2, I received an error "No such archiver: 'nar'." Inserting the following dependency declaration solves that. I chose to insert it directly into the plugin:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <dependencies>
    <dependency>
      <groupId>org.codeswarm</groupId>
      <artifactId>maven-nar-plugin</artifactId>
      <version>20121119</version>
    </dependency>
  </dependencies>
  ...

Platforms

I will try to build it for as many platforms as possible. If you find that your platform is not listed, please contact me at quest (at) windwards net. Currently, the following "aol:s" are represented:

  • i386-Linux-gpp
  • amd64-Linux-gpp

Running tests

You probably want to run tests against your code as well. unix-java contains both a server and a client socket implementation, so you can write tests that mocks the other end. In order to run your tests, you need to tell surefire that the test-runner JVM needs to know about the native library that you just unpacked.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <configuration>
    <argLine>-Djava.library.path=target/lib/${aol}/jni</argLine>
  </configuration>
</plugin>

Enjoy.