/airbase

Base POM for Airlift

Apache License 2.0Apache-2.0

Airbase

Maven Central Build Status

Usage

Add Airbase as the parent to a project:

<parent>
  <groupId>com.facebook.airlift</groupId>
  <artifactId>airbase</artifactId>
  <version> ... current pom release version ...</version>
</parent>

Project pom structure

The following elements should be present in a pom using Airbase as parent:

  • groupId, artifactId, version, packaging, name, description and inceptionYear

    Define the new project. These elements should always be present. If any of those fields are missing from the project, the values from Airbase are picked up instead.

  • scm

    Defines the SCM location and URL for the project. This is required to use the release:prepare and release:perform targets to deploy artifacts to Maven Central.

  • organization, developers, distributionManagement

    Empty elements override the values inherited from Airbase.

This is a sample skeleton pom using Airbase:

<?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>

  <parent>
    <groupId>com.facebook.airlift</groupId>
    <artifactId>airbase</artifactId>
    <version> ... current version ...</version>
  </parent>

  <groupId> ... group id of the new project ... </groupId>
  <artifactId> ... artifact id of the new project ... </artifactId>
  <version> ... version of the new project ... </version>
  <packaging> ... jar|pom ... </packaging>
  <description> ... description of the new project ...  </description>
  <name>${project.artifactId}</name>
  <inceptionYear>2013</inceptionYear>

  <scm>
    <connection> ... scm read only connection ... </connection>
    <developerConnection>... scm read write connection ... </developerConnection>
    <url> ... project url ... </url>
  </scm>

  <distributionManagement/>
  <developers/>
  <organization/>
  ...
</project>

Project POM conventions

In large maven projects, especially with multi-module builds, the pom files can become quite large. In many places, properties defined in the <properties> section of the pom are used.

To avoid confusion with properties, the following conventions are used in Airbase:

  • Properties defined in the POM that influence the build configuration are prefixed with air.
  • Properties that factor out plugin versions (because the plugin is used in multiple places in the POM and the versions should be uniform) start with dep.plugin and end with version.
  • Properties that factor out dependency versions (to enforce uniform dependency versions across multiple, related dependencies) start with dep and end with version.

Examples:

<properties>
  <!-- Sets the minimum maven version to build (influences build) -->
  <air.maven.version>3.0.4</air.maven.version>

  <!-- The surefire plugin version -->
  <dep.plugin.surefire.version>2.13</dep.plugin.surefire.version>

  <!-- The version for all guice related dependencies -->
  <dep.guice.version>3.0</dep.guice.version>
<properties>

Deploy to Maven Central (oss.sonatype.org)

Airbase is intended for open source projects that should be deployed to Maven Central.

As described in the OSSRH Guide, the ossrh repository must be configured:

<servers>
  ...
  <server>
    <id>ossrh</id>
    <username>user</username>
    <password>password</password>
  </server>
  ...
</servers>

Project Build and Checkers

Airbase hooks various checkers into the build lifecycle and executes them on each build.

Generally speaking, running a set of checks at each build is a good way to catch problems early and any problem reported by a checker should be treated as something that needs to be fixed before releasing.

Checkers are organized in two groups, basic and extended.

Basic checkers

Extended checkers

All checkers are enabled by default and will fail the build if a problem is encountered.

Each checker has a switch to turn it on or off and also whether a problem will be a warning or fatal to the build.

...
<properties>
  <!-- Do not run the duplicate finder --->
  <air.check.skip-duplicate-finder>true</air.check.skip-duplicate-finder>
</properties>
...

The following switches exist:

Group Check Skip check (Setting to true skips the check) Fail build (Setting to false only reports a warning)
Basic Maven Enforcer air.check.skip-enforcer air.check.fail-enforcer
Basic Maven Dependencies air.check.skip-dependency air.check.fail-dependency
Basic Maven Duplicate finder air.check.skip-duplicate-finder air.check.fail-duplicate-finder
Basic Maven Dependency scope air.check.skip-dependency-scope air.check.fail-dependency-scope
Extended SpotBugs air.check.skip-spotbugs air.check.fail-spotbugs
Extended PMD air.check.skip-pmd air.check.fail-pmd
Extended License check air.check.skip-license air.check.fail-license
Extended Code coverage air.check.skip-jacoco air.check.fail-jacoco
Extended Modernizer air.check.skip-modernizer air.check.fail-modernizer
Extended Checkstyle air.check.skip-checkstyle air.check.fail-checkstyle

Checks can be turned on and off in groups:

Group Skip checks Fail build
All Checks air.check.skip-all air.check.fail-all
All Basic checks air.check.skip-basic air.check.fail-basic
All Extended Checks air.check.skip-extended air.check.fail-extended

A more specific setting (checker specific, then group, then all) overrides a more general setting:

...
<properties>
  <air.check.skip-all>true</air.check.skip-all>
  <air.check.skip-duplicate-finder>false</air.check.skip-duplicate-finder>
</properties>
...

will skip all checks except the duplicate finder.

Checker notes

License checker

To ensure that a project has an uniform license header in all source files, the Maven license plugin can be used to check and format license headers.

The plugin expects the license header file as src/license/LICENSE-HEADER.txt in the root folder of a project.

For a multi-module project, this file should exist only once, in the root pom of the project. In all other sub-modules, add

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

to each pom. This is a limitation of the Maven multi-module build process (see http://stackoverflow.com/questions/1012402/maven2-property-that-indicates-the-parent-directory for details).

Enforcer checker

The Enforcer plugin outlaws a number of dependencies that project might use for various reasons:

Outlawed dependency Rationale What to use
commons-logging:commons-logging-api Ill-fated attempt to split commons-logging implementation and commons-logging API. commons-logging:commons-logging
cglib:cglib Has all its dependencies packed inside, therefore leads to duplicate classes. cglib:cglib-nodep
junit:junit Has all its dependencies packed inside, therefore leads to duplicate classes. junit:junit-dep
com.google.collections:google-collections Superseded by Guava, duplicate classes with Guava. com.google.guava:guava
com.google.code.findbugs:annotations Contains FindBugs annotations, JSR-305 and JCIP annotations. com.github.spotbugs:spotbugs-annotations

com.google.code.findbugs:jsr305

org.eclipse.jetty.orbit:javax.servlet Jetty variant of the 3.x servlet API jar. javax.servlet:javax.servlet-api

Well known dependencies

Airbase provides a number of dependencies to projects. These dependencies are considered "well known and stable". When a project wants to use any of these dependencies, it can declare them in the project <dependencies> section without a version and automatically pick it up from Airbase.

Airbase provides versions for the following well-known dependencies:

Dependency nameGroup/Artifact Ids
Google Guice com.google.inject:guice

com.google.inject.extensions:guice-servlet

com.google.inject.extensions:guice-assistedinject

com.google.inject.extensions:guice-multibindings

com.google.inject.extensions:guice-throwingproviders

Google Guava com.google.guava:guava
Joda Time joda-time:joda-time
Java Inject API javax.inject:javax.inject
Java Servlet API javax.servlet:javax.servlet-api
Java Validation API javax.validation:validation-api
slf4j (Simple Logging Facade for Java) org.slf4j:slf4j-api

org.slf4j:slf4j-nop

org.slf4j:slf4j-simple

org.slf4j:slf4j-ext

org.slf4j:jcl-over-slf4j

org.slf4j:jul-to-slf4j

org.slf4j:log4j-over-slf4j

org.slf4j:slf4j-jdk14

Logback ch.qos.logback:logback-core

ch.qos.logback:logback-classic

Jackson com.fasterxml.jackson.core:jackson-annotations

com.fasterxml.jackson.core:jackson-core

com.fasterxml.jackson.core:jackson-databind

com.fasterxml.jackson.datatype:jackson-datatype-guava

com.fasterxml.jackson.datatype:jackson-datatype-joda

com.fasterxml.jackson.dataformat:jackson-dataformat-smile

Bean Validation Framework org.apache.bval:bval-jsr
JmxUtils org.weakref:jmxutils
Joda Time joda-time:joda-time
CGLib cglib:cglib-nodep
FindBugs / SpotBugs Annotations com.github.spotbugs:spotbugs-annotations
JSR-305 Annotations com.google.code.findbugs:jsr305
TestNG testing org.testng:testng
AssertJ org.assertj:assertj-core

org.assertj:assertj-guava

org.assertj:assertj-joda-time

org.assertj:assertj-db

Mockito org.mockito:mockito-core
Hamcrest matchers org.hamcrest:hamcrest-core

org.hamcrest:hamcrest-library

org.objenesis:objenesis

Airlift Slice io.airlift:slice

Other properties

These are default properties that affect some aspects of the build. All of them can be overriden in the <properties> section of the project pom.

project.build.targetJdk

By default, Airbase enforces JDK 1.8. To use another version, add

<properties>
  <project.build.targetJdk>1.6</project.build.targetJdk>
  ...
</properties>

air.build.jvmsize

Sets the default heap size for the compiler, javadoc generation and other plugins. Default is 1024M.

air.release.push-changes

When a project creates a release using the maven-release-plugin and mvn release:prepare, this switch controls whether the generated tags, modified POM files etc. are pushed automatically to the upstream repository or not. Default is false (do not push the changes).

air.maven.version

The minimum version of Maven to build a project. Default is "3.0".

air.main.basedir

The 'root' directory of a project. For a simple project, this is identical to project.basedir. In a multi-module build, it should point at the root project.

For a multi-module project, all other sub-modules must have this explicitly set to the root directory and therefore the following code

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

must be added to each pom. This is a limitation of the Maven multi-module build process (see http://stackoverflow.com/questions/1012402/maven2-property-that-indicates-the-parent-directory for details).

Deploy profiles

airlift packaging build

A module or sub-module can produce a tarball using the airlift packaging. This profile is activated by creating a file .build-airlift in the root of the module or submodule. This file can be empty. The tarball is attached as an additional artifact.

The necessary launchers from the airlift launcher package are included. The version of the launcher included is controlled by the dep.packaging.version property.