Maven License Plugin in Multi Module Builds

When you’re developing APIs, you need to be careful to make sure all files contain a license header. There are two Maven plugins which can help you with that:

  • com.mycila.maven-license-plugin:maven-license-plugin
  • org.codehaus.mojo:maven-license-plugin

Most of the time we use the one from “org.codehaus.mojo”. One annoying thing about this plugin is, that it can make multi-module builds painful. The problem is, that you usually configure the plugin in the parent. The resources (header and license) are located relative to the parent pom-file. While the build works fine from the parent project, it fails from the child modules, because the plugin tries to resolve the resource files relative to the project dir:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>license-maven-plugin</artifactId>
    <version>1.16</version>
    <configuration>
        <inceptionYear>2018</inceptionYear>
        <organizationName>Dukehoff GmbH</organizationName>
        <licenseName>mit</licenseName>
        <failOnMissingHeader>true</failOnMissingHeader>
        <descriptionTemplate>/src/license/header.txt</descriptionTemplate>
        <!-- More stuff.... -->
    </configuration>
    <!-- Executions.... -->
</plugin>        

In the case of a subproject it would need to be “../src/license/header.txt”. Now you could override the configuration in the child module with this value. This works fine when running the build from the child, but then the build from the parent will fail.

There are several solutions to this:

  • Using absolute paths
  • Copying the resources to the child modules
  • Skip the module by putting it in a profile
  • Using a custom license resolver
  • Using properties

The first solution is horrible and kills portability. The second one is horrible, as it duplicates stuff. I saw some solutions using maven resources plugin to copy the resources to subdirs automatically, but it’s still horrible.

Pragmatic approach with profile

The third one is a pragmatic approach I used a lot in the past. I simply put the license check in a profile which is active by default, but can be disabled via a property. I then defined a run configuration which sets this property (-DskipLicenses) and disables the license check. The dukescript-canvas project does this, as you can see here. That’s OK, but often enough I would forget about it and the build would fail. So there should be a better way.

The official way

The fourth solution is the cleanest one, but it can be painful as well. It requires an extra module, and it requires you to copy the license there, even when using a license that is predefined, like MIT.

I recently used this approach when publishing the AmaronUi Layouts project, a collection of (currently one) layout algorithm(s) for different platforms (iOS, Android, JavaFX). Besides packing the license and the header in a jar, I also had to define a license.properties file. You can find the license resolver here if you want to check it out.

How to prevent the release of the license-resolver

And finally I needed to prevent the license resolver itself from being deployed to Maven Central. So I needed to configure the maven-deploy-plugin to skip it:

<?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>com.dukescript.amaronui</groupId>
<artifactId>gplv2cpe-license-resolver</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>gplv2cpe-license-resolver</name>
<build>
    <plugins>     
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-deploy-plugin</artifactId>
            <version>2.8.2</version>
            <configuration>
                <skip>true</skip>
            </configuration>
        </plugin>
    </plugins>
</build>
</project>

It works, but as you can see, it’s not the quickest and simplest solution.

Pragmatic solution 2

It made sense for the AmaronUI Layouts to use a custom resolver, because I published it under a not-predefined license, but in other project I only need a custom header.

We recently started collecting demos in a single location. All of them are published under the permissive MIT license, so a license resolver didn’t feel right. When looking for a solution I found this neat trick, a property that locates the parent base directory. With this you can define a property (e.g. main.basedir) and redefine it in the child modules to point to the parent. So on every level of the build it will be able to resolve the relative link:

So now this is my configuration:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>license-maven-plugin</artifactId>
    <version>1.16</version>
    <configuration>
        <inceptionYear>2018</inceptionYear>
        <organizationName>Dukehoff GmbH</organizationName>
        <licenseName>mit</licenseName>
        <failOnMissingHeader>true</failOnMissingHeader>
        <descriptionTemplate>${main.basedir}/src/license/header.txt</descriptionTemplate>
        <!-- More stuff.... -->
    </configuration>
    <!-- Executions.... -->
</plugin>        

In the parent the property is defined like this:

<properties>
    <main.basedir>${project.basedir}</main.basedir>
</properties>

In the children it’s:

<properties>
    <main.basedir>${project.parent.basedir}</main.basedir>
</properties>

And for grandchildren it’s:

<properties>
    <main.basedir>${project.parent.parent.basedir}</main.basedir>
</properties>

I hope you find it useful. It sure saves me a lot of pain :-). Enjoy coding!