Apache Maven

By Maurizio Farina | Posted on December 2017

A maven is a trusted expert in a particular field so Apache Maven is a build automation tool used primarily for Java projects. The Maven project is hosted by the Apache Software Foundation (formerly part of the Jakarta Project).

Maven covers two basic software development topics:

  • software building lifecycle (compile, test, deploy and many others)
  • manage dependencies package (console application, web application, java library, etc..)

Maven uses a Project Object Model file (a pom.xml file) to describe building, dependencies and components used by the application, the build order, directories, and required plug-ins.

Maven downloads Java libraries and plug-ins from one or more repositories over the web (the most famouses is Maven 2 Central Repository) and stores them in a local Maven repository cache.

Maven defines phases to manage application lifecycle development :

  • validate
  • generate-sources
  • process-sources
  • generate-resources
  • process-resources
  • compile
  • process-test-sources
  • process-test-resources
  • test-compile
  • test
  • package
  • install
  • deploy

Maven includes a Unix shell script and MSDOS batch file named mvn and mvn.bat respectively to execute the phases

1
2
3
4
5
mvn [options] [<phase(s)>]

An example,

mvn -DskipTests clean deploy

Maven Structure folders

Eclipse Project
Maven Folders The following picture is grabbed from Eclipse IDE with Maven plug-in installed.
The folders are grouped by Eclipse IDE to simplify the access to the files.
M2Eclipse is the official Eclipse project for Maven integration for the Eclipse IDE.
Folder name Purpose
project home Contains the pom.xml and all subdirectories.
src/main/java Contains the deliverable Java sourcecode for the project.
src/main/resources Contains the deliverable resources for the project, such as property files.
src/test/java Contains the testing Java sourcecodefor the project.
src/test/resources Contains resources necessary for testing.

Project Object Model

A Project Object Model (POM) provides all the configuration for a single project. General configuration covers the project's name, its owner and its dependencies on other projects. One can also configure individual phases of the build process, which are implemented as plugins. For example, one can configure the compiler-plugin to use Java version 1.5 for compilation, or specify packaging the project even if some unit tests fail.

Larger projects should be divided into several modules, or sub-projects, each with its own POM. One can then write a root POM through which one can compile all the modules with a single command. POMs can also inherit configuration from other POMs. All POMs inherit from the Super POM[8] by default. The Super POM provides default configuration, such as default source directories, default plugins, and so on.

1
2
3
4
5
6
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.listfeeds</groupId>
    <artifactId>ListFeeds</artifactId>
    <version>1.0.0-SNAPSHOT</version>
</project>

Super POM

The Super POM is a virtual pom.xml file that ships inside the core Maven JARs, and provides numerous default settings. All projects automatically inherit from the Super POM, much like the Object super class in Java. Its contents can be viewed in one of two ways:

Multi-Module Projects

Maven showcases exceptional support for componentization via its concept of multi-module builds. Place sub-projects in sub-folders beneath your top level project and reference each with a module tag. To build all sub projects, just execute your normal mvn command and goals from a prompt in the top-most directory.

1
2
3
4
5
6
7
8
9
<project>
  <!-- ... -->
  <packaging>pom</packaging>
  <modules>
    <module>servlets</module>
    <module>ejbs</module>
    <module>ear</module>
  </modules>
</project>

Plugins

All Maven functionalities are implemented using plugins. Basic plugins are included in every project by default, for example compiler plugin, and they are the way to extend Maven for different operations (building, testing, dependency management and many others).

Each plugins defines a set of goal to use during Maven lifecycle or manually; for example:

1
mvn [plugin-name]:[goal-name]

Plugins are configured in two different sections in pom.xml file:

  • build/pluginManagement/plugins: used to define the plugins to use; the version and configuration
  • build/plugins: the plugins to use during Maven lifecycle activities

The following example is the pluginManagement section extracted from ListFeeds parent pom.xml file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<pluginManagement>
    <plugins>
        <plugin>
            <groupId>com.google.code.maven-replacer-plugin</groupId>
            <artifactId>replacer</artifactId>
            <version>1.5.3</version>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.16</version>
            <configuration>
                <skipTests>${test.Skip}</skipTests>
                <systemPropertyVariables>
                    <jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
                </systemPropertyVariables>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                    </manifest>
                </archive>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.4</version>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.7</version>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-enforcer-plugin</artifactId>
            <version>1.3.1</version>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-release-plugin</artifactId>
            <version>2.4.1</version>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>2.2.1</version>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.8</version>
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxb2-maven-plugin</artifactId>
            <version>1.5</version>
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>sonar-maven-plugin</artifactId>
            <version>2.1</version>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.0</version>
        </plugin>
    </plugins>
</pluginManagement>

To use a plugin inside a Java project is enough to add plugins section in the pom.xml file.

Dependency plug-ins

A useful plugins to analyze all dependencies packages used by our application. The following commands copy all dependecies in the folder target/dependency:

Plugin declaration:

1
2
3
4
5
6
7
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <configuration>
    <includeScope>runtime</includeScope>
  </configuration>
</plugin>

The includeScope configuration tag allows to copy only dependencies used at runtime. For a complete list of configuration tags: Apache Dependency plugin documentation

To execute the plugin:

1
mvn dependency:copy-dependencies

Using Maven behind a proxy

Maven configuration file is settings.xml usually stored in ${user.home}/.m2/settings.xml folder.

an extracted from Apache Maven web site

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<settings>
  .
  .
  <proxies>
   <proxy>
      <id>example-proxy</id>
      <active>true</active>
      <protocol>http</protocol>
      <host>proxy.example.com</host>
      <port>8080</port>
      <username>proxyuser</username>
      <password>somepassword</password>
      <nonProxyHosts>www.google.com|*.example.com</nonProxyHosts>
    </proxy>
  </proxies>
  .
  .
</settings>

References

Curiosity: In Yiddish, the word maven means "accumulator of knowledge"