Maven

Summary

Notes on the Maven build system.

Modes

Daemon

This build mode relies on the Maven daemon, itself inspired by the Gradle daemon:

The Maven Daemon process does not reload classes unless they are changed.

The daemon is called with mvnd instead of mvn, for instance

$ mvnd clean install

The daemon uses multiple threads by default, with $N_{cores}-1$.

Artifacts

Über JARs

There are many ways to build über JARs, but we will talk about two, maven-assembly-plugin and maven-shade-plugin.

Assembly

The maven-assembly-plugin 1 adds all dependencies inside the final fat JAR and can be used by adding the following to your pom.xml:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <configuration>
    <descriptorRefs>
      <descriptorRef>jar-with-dependencies</descriptorRef>
    </descriptorRefs>
    <archive>
      <manifest>
        <mainClass>{your.package.main.class}</mainClass>
      </manifest>
    </archive>
  </configuration>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Maven plugins should be specified inside a <plugins></plugins> scope, which itself must be inside <build></build> scope. As you can see from execution phase, the Über JAR is built when calling mvn package.

Shade

The maven-shade-plugin 2 also adds all dependencies inside the final fat JAR, but additionally executes shading. Add the following to your pom.xml:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <configuration>
    <transformers>
      <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
        <mainClass>{your.package.main.class}</mainClass>
      </transformer>
    </transformers>
  </configuration>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>shade</goal>
      </goals>
    </execution>
  </executions>
</plugin>

The shade plugin also allows to specify dependency inclusion/exclusion using a variety of specifiers. The following example from the official docs3 illustrates this:

<project>
...
<build>
  <plugins>
	<plugin>
	  <groupId>org.apache.maven.plugins</groupId>
	  <artifactId>maven-shade-plugin</artifactId>
	  <version>3.3.0</version>
	  <executions>
		<execution>
		  <phase>package</phase>
		  <goals>
			<goal>shade</goal>
		  </goals>
		  <configuration>
			<artifactSet>
			  <excludes>                    
				<exclude>classworlds:classworlds</exclude>
				<exclude>junit:junit</exclude>
				<exclude>jmock:*</exclude>
				<exclude>*:xml-apis</exclude>
				<exclude>org.apache.maven:lib:tests</exclude>
				<exclude>log4j:log4j:jar:</exclude>
			  </excludes>
			</artifactSet>
		  </configuration>
		</execution>
	  </executions>
	</plugin>
  </plugins>
</build>
...
</project>

Dependencies

Tree

The dependency-tree plugin4 allows to display a project’s dependency tree. At it’s simplest running mvn dependency:tree will print a tree with the project’s depency hierarchy.

Testing

Excluding tests

To exclude test from Maven use the following notation5

# Exclude specific class with (!)
$ mvn test -Dtest=!ExcludedClass
# Exclude specific method 
$ mvn test -Dtest=!ExcludedClass#excludedMethod
# Exclude more than one method
$ mvn test -Dtest=!ExcludedClass#excludedMethod+excludedMethod2
# Exclude a package with a wildcard (*)
$ mvn test -Dtest=!dev.ruivieira.test.Excluded*