0% found this document useful (0 votes)
34 views108 pages

BRM Lab

Uploaded by

sbhatlabe21
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views108 pages

BRM Lab

Uploaded by

sbhatlabe21
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 108

Build and Release

Management
2. Build and Release Management Lab
Prerequisites for this lab

2.1 Setting Up Maven and Understanding POM Hierarchy

2.1.1 What is Maven?

2.1.1.1 POM Files

2.1.1.2 Build Life Cycles, Phases and Goals

2.1.1.3 Dependencies and Repositories

2.1.1.4 Build Plugins

2.1.1.5 Build Profiles

2.1.2 Setting Up Maven

2.1.2.1 Download Java

2.1.2.2 Set JAVA_HOME

2.1.2.3 Download Apache Maven

2.1.2.4 Installing Maven

2.1.2.5 Common Issues with Maven Installation

2.1.3 Creating a Project Using Maven

2.1.3.1 Understanding the Pom File

2.2 Maven Configuration

2.2.1 Using a Repository Manager

2.2.1.1 Benefits and Features

2.2.1.2 Available Repository Managers

1
2.2.1.3 Repository Settings Details

2.2.1.4 Nexus Requirements in the pom.xml

2.2.2 Password Encryption

2.2.3 Profiles

2.2.4 Repositories Configuration

2.2.5 Plugin Repositories

2.2.6 Deploying Artifacts to Nexus Repository

2.2.7 Maven 3.3.x Logging

2.2.8 Configuring a Proxy

2.2.9 Using Mirrors for Repositories

2.3 Maven Plugins

2.3.1 Using the Maven Clean plugin

2.3.2 Using the Maven Compiler Plugin

2.3.3 Using the Maven Surefire Plugin to Run Unit Tests

2.3.4 Using the Maven Resources Plugin

2.3.5 Using Eclipse to Run Maven Goals

2.4 Maven Assembly

2.5 Maven Repository Management

2.6 Best Practices

2
Prerequisites for this lab:

1. Openjdk-1.8

2. Apache Maven 3.3.9

3. Nexus Repository

4. Windows 7/10

5. Eclipse Mars Versions

6. Proxy URL (If you are using a proxy)

2.1 Setting Up Maven and Understanding POM Hierarchy

2.1.1 What is Maven?

Maven is based on the concept of POM files (Project Object Model). It is an XML
representation of project resources like dependencies, source code, test code,
etc. All the references of these resources are configured in the POM. The POM file
is present in the root directory of the project.

3
Below diagram illustrates how POM file is used by maven and what POM files
contain:

All the above steps mentioned in the picture are briefly explained in the below
sections of this lab guide:

2.1.1.1 POM Files


When a maven command is executed it reads the POM file and executed the
required commands on resources mentioned in the POM.

2.1.1.2 Build Life Cycles, Phases and Goals

In maven the build process is split into different build life cycles, phases and goals.
Build life cycle is a sequence of build phases, and each build phase consists of a
sequence of goals. When you run Maven you pass a command to Maven. This
command is the name of a build life cycle, phase or goal. If a life cycle is requested
executed, all build phases in that life cycle are executed. If a build phase is

4
requested executed, all build phases before it in the pre-defined sequence of
build phases are executed too.

2.1.1.3 Dependencies and Repositories

One of the first goals Maven executes is to check the dependencies needed by
your project. Dependencies are external JAR files (Java libraries) that your project
uses. If the dependencies are not found in the local Maven repository, Maven
downloads them from a central Maven repository and puts them in your local
repository. The local repository is just a directory on your computer's hard disk.
You can specify where the local repository should be located if you want to (I do).
You can also specify which remote repository to use for downloading
dependencies. All this will be explained in more detail later in this tutorial.

2.1.1.4 Build Plugins

Build plugins are used to insert extra goals into a build phase. If you need to
perform a set of actions for your project which are not covered by the standard
Maven build phases and goals, you can add a plugin to the POM file. Maven has
some standard plugins you can use, and you can also implement your own in Java
if you need to.

2.1.1.5 Build Profiles

Build profiles are used if you need to build your project in different ways. For
instance, you may need to build your project for your local computer, for
development and test. And you may need to build it for deployment on your
production environment. These two builds may be different. To enable different
builds you can add different build profiles to your POM files. When executing
Maven you can tell which build profile to use.

5
2.1.2 Setting up maven

Maven installation is simple. To install Apache Maven on Windows, you need to


download the Maven’s zip file, unzip it to a folder, and configure the Windows
environment variables.

Note: Maven requires a Java platform to run the commands. First, make sure
that you have installed the Java environment on your system, Java Development
Kit (JDK) specifically; Java Runtime Environment (JRE) is not sufficient.

1. Maven 3.3+ requires JDK 1.7+

2. Maven 3.2 requires JDK 1.6+

3. Maven 3.0/3.1 requires JDK 1.5+

Lab:

2.1.2.1 Download Java

1. Windows (X86/64)

Download and install Openjdk 1.8 from Redhat Website

2. Debian, Ubuntu, etc.

On the command line, type:

$ sudo apt-get install openjdk-8-jre

The openjdk-8-jre package contains just the Java Runtime Environment. If you
want to develop Java programs then please install the openjdk-8-jdk package.

6
3. Fedora, Oracle Linux, Red Hat Enterprise Linux, etc.

On the command line, type:

$ su -c "yum install java-1.8.0-openjdk"

The java-1.8.0-openjdk package contains just the Java Runtime Environment. If


you want to develop Java programs then install the java-1.8.0-openjdk-
develpackage.

2.1.2.2 Set JAVA_HOME

7
Type C:> java -version

2.1.2.3 Download Apache Maven

Note: Make sure JDK is installed, and JAVA_HOME environment variable is


configured.

2.1.2.4 Installing Maven

To install Maven on your own system (computer), go to the Maven download


page and follow the instructions there. In summary, what you need to do is:

1. Set the JAVA_HOME environment variable to point to a valid Java SDK (e.g.,
Java 8).

2. Download and unzip Maven.

3. Set the M2_HOME environment variable to point to the directory you


unzipped Maven to.

4. Set the M2 environment variable to point


to M2_HOME/bin (%M2_HOME%\bin on Windows, $M2_HOME/bin on unix).

5. Add M2 to the PATH environment variable (%M2% on Windows, $M2 on unix).

6. Open a command prompt and type 'mvn -version' (without quotes) and press
enter.

8
After running mvn -version command you can see that maven command is
executed, and the version details of Maven is written out to the command
prompt.

Ensure the contents of you maven installation are similar to the following screenshot:

The preceding screenshot displays a list of directories contained in Maven.

Now, let's briefly discuss what these directories contain:

● The bin folder contains the batch files and shell scripts to run Maven on
various platforms.

● The boot folder contains the jars required for Maven to start.

● The conf folder contains the default settings.xml file used by Maven.

● The lib folder contains the libraries used by Maven. It also contains
an ext folder in which third-party extensions, which can extend or override the
default Maven implementation, can be placed.

9
More details:

A Maven installation is essentially a set of JAR files, configuration files, and a


Microsoft Windows batch file, mvn.bat.

The mvn command essentially runs this batch file. It first checks for JAVA_HOME.
This file is present in the bin folder of the Maven installation and, hence, it needs
to be in PATH.

If the batch file does not find JAVA_HOME, it looks for Java in its PATH. This can
lead to unexpected results, as typically the Java in PATH is usually the JRE and not
the JDK.

The batch file, then looks for M2_HOME, which is the location of the Maven
installation. It does this so that it can load the libraries that are present.

Additionally, it also reads values specified in MAVEN_OPTS. This variable allows


you to run Maven with an additional heap size and other Java parameters.

Using the values for JAVA_HOME, M2_HOME, and Maven_OPTS, the batch file
run its main class org.codehaus.plexus.classworlds.launcher.Launcher.

2.1.2.5 Common Issues with Maven Installation

1. ‘mvn’ is not recognized as an internal or external command?

Solution: 1. Go to path_to_maven/bin and type mvn -version . If that works then it's a PATH
problem.In command prompt type set PATH=path_to_maven/bin;%PATH%

10
Solution: 2. JAVA_HOME should be set to fix this issue. Refer 2.1.2.2

Note: Restart your command prompt for the changes to PATH to take effect

Lab:

2.1.3 Creating a Project Using Maven

1. Create a folder and open command prompt from that folder

Run this command to create a sample maven project:

mvn archetype:generate -DgroupId=com.skaas.sample -DartifactId=my-app -


DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Command output: It will take a while to execute the command because maven is downloading
the most recent artifacts into the local repository. Once the command is executed successfully,
you would see the similar output as below:

[INFO] Parameter: package, Value: com.skaas.sample

[INFO] Parameter: groupId, Value: com.skaas.sample

[INFO] Parameter: artifactId, Value: my-app

[INFO] Parameter: packageName, Value: com.skaas.sample

[INFO] Parameter: version, Value: 1.0-SNAPSHOT

[INFO] project created from Old (1.x) Archetype in dir:


C:\Users\gnanendra\Desktop\Git\Maven\my-app

[INFO]

[INFO] BUILD SUCCESS

11
[INFO]

[INFO] Total time: 50.277 s

[INFO] Finished at: 2018-12-04T18:38:11+05:30

[INFO] Final Memory: 18M/247M

[INFO]

2.1.3.1 Understanding the Pom File

Every Maven project has a pom file that defines what the project is all about and
how it should be built. Pom is an acronym for the project object model. Let us
take a peek at this file.

Lab:

Let's understand the pom file, by performing the following steps:

1. Go to a Maven project that we created in the previous sections.

2. Open the file named pom.xml.

A pom file is an XML file that is based on a specific schema, as specified at the top
of the file:

<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/maven-v4_0_0.xsd">

12
<modelVersion>4.0.0</modelVersion>

<groupId>com.skaas.app</groupId>

<artifactId>my-app</artifactId>

<packaging>jar</packaging>

<version>1.0-SNAPSHOT</version>

<name>my-app</name>

<url>http://maven.apache.org</url>

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>3.8.1</version>

<scope>test</scope>

</dependency>

</dependencies>

</project>

There is also a modelVersion element that defines the version of this schema:

13
<modelVersion>4.0.0</modelVersion>

These are the basic elements of a pom file.

The groupId element is a unique identifier of the organization to which the


project belongs. For our sample project, it is org.skaas.sample. It is a good
practice to follow the reverse domain name notation to specify this:

<groupId>...</groupId>

The artifactId element is the name of the project. For our sample project, it
is simple-project:

<artifactId>...</artifactId>

The version element is the specific instance of the project, corresponding to the
source code at a particular instance of time. In our case, it is 1.0-SNAPSHOT,
which is a default version during development:

<version>...</version>

We will explore the difference between the SNAPSHOT and concrete versions
later in the book.

The combination of groupId, artifactId, and version uniquely identifies the project.
In this sense, they are the coordinates of the project.

14
The packaging element indicates the artifact type of the project. This is typically
a jar, war, zip, or in some cases, a pom:

<packaging>...</packaging>

The dependencies element section of the pom file defines all the dependent
projects of this project. This would typically be third-party libraries required to
build, test, and run the project:

<dependencies>...</dependencies>

The parent section is used to indicate a relationship, specifically a parent-child


relationship. If the project is part of a multi-module project or inherits project
information from another project, then the details are specified in this section:

<parent>...</parent>

Maven properties are placeholders. Their values are accessible anywhere in the
pom file by using ${key}, where key is the property name:

<properties>...</properties>

A project with modules is known as a multi-module or aggregator project.


Modules are projects that this pom file lists and are executed as a group:

<modules>...</modules>

15
This section will show how to deploy the artifacts of a project to Nexus, with
Maven.

2.2 Maven Configuration

The configuration for Apache Maven usage itself and projects built with resides in
a number of places:

• MAVEN_OPTS environment variable:

This variable contains parameters used to start up the JVM running Maven and
can be used to supply additional options to globally to Maven. E.g., JVM memory
settings could be defined with the value -Xms256m -Xmx512m.

• settings.xml file:

Located in USER_HOME/.m2 the settings files is designed to contain any


configuration for Maven usage across projects.

• .mvn folder:

Located within the projects top level folder, the files maven.config and
extensions.xml contain the project specific configuration for running Maven.

Lab:

You can use the MAVEN_OPTS environment variable to set the maximum allowed
heap size for Maven at a global level. The following command will set the heap
size in any Unix-based operating system, including Linux and Mac OS X. Make sure
that the value set as the maximum heap size does not exceed your system
memory of the machine, which runs Maven:

16
Open a command prompt on windows and run below command:

$ set MAVEN_OPTS=-Xmx1024m -XX:MaxPermSize=128m

If you are running this command on Linux, run the below ommand:

$ export MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=128m"

2.2.1 Using a Repository Manager

A repository manager is a dedicated server application designed to manage


repositories of binary components. The usage of a repository manager is
considered an essential best practice for any significant usage of Maven.

Purpose

A repository manager serves these essential purposes:

• Act as a dedicated proxy server for public Maven repositories

• Provide repositories as a deployment destination for your Maven project


outputs

2.2.1.1 Benefits and Features

Using a repository manager provides the following benefits and features:

• Significantly reduced number of downloads off remote repositories, saving


time and bandwidth resulting in increased build performance

• Improved build stability due to reduced reliance on external repositories

17
• Increased performance for interaction with remote SNAPSHOT repositories

• Potential for control of consumed and provided artifacts

• Creates a central storage and access to artifacts and meta data about them,
exposing build outputs to consumer such as other projects and developers, but
also QA or operations teams or even customers

• Provides an effective platform for exchanging binary artifacts within your


organization and beyond without the need for building artifact from source

2.2.1.2 Available Repository Managers

The following list of open source and commercial repository managers are
known to support the repository format used by Maven. Please refer to the
respective linked web sites for further information about repository
management in general and the features provided by these products.

• Apache Archiva (open source)

• CloudRepo (commercial)

• Cloudsmith Package (commercial)

• JFrog Artifactory Open Source (open source)

• JFrog Artifactory Pro (commercial)

• Sonatype Nexus OSS (open source)

• Sonatype Nexus Pro (commercial)

• packagecloud.io (commercial)

18
The settings element in the settings.xml file contains elements used to define
values which configure Maven execution in various ways, like the pom.xml, but
should not be bundled to any specific project, or distributed to an audience.
These include values such as the local repository location, alternate remote
repository servers, and authentication information.

There are two locations where a settings.xml file may live:

• The Maven install: ${maven.home}/conf/settings.xml

• A user’s install: ${user.home}/.m2/settings.xml

The former settings.xml is also called global settings, the latter settings.xml is
referred to as user settings. If both files exist, their contents gets merged, with
the user-specific settings.xml being dominant.

Tip: If you need to create user-specific settings from scratch, it’s easiest to copy
the global settings from your Maven installation to
your ${user.home}/.m2 directory. Maven’s default settings.xml is a template with
comments and examples so you can quickly tweak it to match your needs.

Here is an overview of the top elements under settings:

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0

19
https://maven.apache.org/xsd/settings-1.0.0.xsd">

<localRepository/>

<interactiveMode/>

<usePluginRegistry/>

<offline/>

<pluginGroups/>

<servers/>

<mirrors/>

<proxies/>

<profiles/>

<activeProfiles/>

</settings>

The contents of the settings.xml can be interpolated using the following


expressions:

1. ${user.home} and all other system properties (since Maven 3.0)

2. ${env.HOME} etc. for environment variables

Note that properties defined in profiles within the settings.xml cannot be used
for interpolation.

20
2.2.1.3 Repository Settings Details

Simple Values

Half of the top-level settings elements are simple values, representing a range of
values which describe elements of the build system that are active full-time.

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0

https://maven.apache.org/xsd/settings-
1.0.0.xsd">

<localRepository>${user.home}/.m2/repository</localRepository>

<interactiveMode>true</interactiveMode>

<usePluginRegistry>false</usePluginRegistry>

<offline>false</offline>

...

</settings>

• localRepository: This value is the path of this build system’s local repository.
The default value is ${user.home}/.m2/repository. This element is especially useful
for a main build server, allowing all logged-in users to build from a common
local repository.

21
• interactiveMode: true if Maven should attempt to interact with the user for
input, false if not. Defaults to true.

• usePluginRegistry: true if Maven should use the ${user.home}/.m2/plugin-


registry.xml file to manage plugin versions, defaults to false. Note that for the

current version of Maven 2.0, the plugin-registry.xml file should not be


depended upon. Consider it dormant for now.

• offline: true if this build system should operate in offline mode, defaults
to false. This element is useful for build servers which cannot connect to a
remote repository, either because of network setup or security reasons.

Plugin Groups

This element contains a list of pluginGroup elements, each contains a groupId.


The list is searched when a plugin is used and the groupId is not provided in the
command line. This list automatically
contains org.apache.maven.plugins and org.codehaus.mojo.

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0

https://maven.apache.org/xsd/settings-
1.0.0.xsd">

...

<pluginGroups>

<pluginGroup>org.mortbay.jetty</pluginGroup>

22
</pluginGroups>

...

</settings>

For example, given the above settings the Maven command line may
execute org.mortbay.jetty:jetty-maven-plugin:run with the truncated command:

Lab:

mvn jetty:run

2.2.1.4 Nexus Requirements in the pom.xml

In order for Maven to be able to deploy the artifacts it creates in


the package phase of the build, it needs to define the repository information
where the packaged artifacts will be deployed, via
the distributionManagement element:

<distributionManagement>

<snapshotRepository>

<id>nexus-snapshots</id>

<url>http://localhost:8081/nexus/content/repositories/
snapshots</url>

</snapshotRepository>

</distributionManagement>

23
A hosted, public Snapshots repository comes out of the box on Nexus, so there’s
no need to create or configure anything further. Nexus makes it easy to
determine the URLs of its hosted repositories – each repository displays the exact
entry to be added in the <distributionManagement> of the project pom

2.2.2 Password Encryption

A new feature - server password and passphrase encryption has been added to
2.1.0+.

Password Encryption

1. Introduction

2. How to create a master password

3. How to encrypt server passwords

4. How to keep the master password on removable drive

5. Tips

Introduction

Maven 2.1.0+ now supports server password encryption. The main use case,
addressed by this solution is:

• multiple users share the same build machine (server, CI box)

• some users have the privilege to deploy Maven artifacts to repositories, some
don't.

24
o this applies to any server operations, requiring authorization, not only
deployment

• settings.xml is shared between users

The implemented solution adds the following capabilities:

• authorized users have an additional settings-security.xml file in


their ${user.home}/.m2 folder

o this file either contains encrypted master password, used to encrypt other
passwords

o or it can contain a relocation - reference to another file, possibly on


removable storage

o this password is created first via CLI for now

• server entries in the settings.xml have passwords and/or keystore passphrases


encrypted

o for now - this is done via CLI after master password has been created and
stored in appropriate location

Lab:

How to create a master password

Use the following command line:

mvn --encrypt-master-password <password>

25
Maven will prompt for the password. Earlier versions of Maven will not prompt
for a password, so it must be typed on the command-line in plaintext.

This command will produce an encrypted version of the password, something


like

{RbzGWnojSMOVrIt5kPFgsHVpMvz5pI8u+9EF1iFQyJQ=}

Store this password in the ${user.home}/.m2/settings-security.xml; it should look


like

<settingsSecurity>

<master>{ RbzGWnojSMOVrIt5kPFgsHVpMvz5pI8u+9EF1iFQyJQ
}</master>

</settingsSecurity>

When this is done, you can start encrypting existing server passwords.

How to encrypt server passwords

You will have to use the following command line:

mvn --encrypt-password <password>

Note:Just like --encrypt-master-password the password argument should no


longer be used since Maven 3.2.1

26
This command will produce an encrypted version of it, something like

{6DU6COtcS5PQLCEG=}

Cut-n-paste it into your settings.xml file in the server section. This will look like:

<settings>

...

<servers>

...

<server>

<id>my.server</id>

<username>foo</username>

<password>{COQLCE6DU6GtcS5P=}</password>

</server>

...

</servers>

...

</settings>

27
Please note that the password can contain any information outside of the curly
brackets, so that the following will still work:

<settings>

...

<servers>

...

<server>

<id>my.server</id>

<username>foo</username>

<password>Oleg reset this password on 2009-03-11,


expires on 2009-04-11 {COQLCE6DU6GtcS5P=}</password>

</server>

...

</servers>

...

</settings>

Then you can use, say, deploy plugin, to write to this server:

mvn deploy:deploy-file -Durl=https://maven.corp.com/repo \

-DrepositoryId=my.server \

-Dfile=your-artifact-1.0.jar \

28
How to keep the master password on removable drive

Create the master password exactly as described above, and store it on a


removable drive, for instance on OSX, my USB drive mounts
as /Volumes/mySecureUsb, so you store

<settingsSecurity>

<master>{jSMOWnoPFgsHVpMvz5VrIt5kRbzGpI8u+9EF1iFQyJQ=}</master>

</settingsSecurity>

in the file /Volumes/mySecureUsb/secure/settings-security.xml

And then you create ${user.home}/.m2/settings-security.xml with the following


content:

<settingsSecurity>

<relocation>/Volumes/mySecureUsb/secure/settings-
security.xml</relocation>

</settingsSecurity>

This assures that encryption will only work when the USB drive is mounted by
the OS. This addresses an use case where only a certain people are authorized to
deploy and are issued these devices.

29
Tips

Escaping curly-brace literals in your password (Since: Maven 2.2.0)

At times, you might find that your password (or the encrypted form of it) may
actually contain '{' or '}' as a literal value. If you added such a password as-is to
your settings.xml file, you would find that Maven does strange things with it.
Specifically, Maven will treat all the characters preceding the '{' literal, and all the
characters after the '}' literal, as comments. Obviously, this is not the behavior
you want in such a situation. What you really need is a way of escaping the curly-
brace literals in your password.

Starting in Maven 2.2.0, you can do just this, with the widely used '\' escape
character. If your password looks like this:

jSMOWnoPFgsHVpMvz5VrIt5kRbzGpI8u+{EF1iFQyJQ=

Then, the value you would add to your settings.xml would look like this:

{jSMOWnoPFgsHVpMvz5VrIt5kRbzGpI8u+\{EF1iFQyJQ=}

Password Security

Editing settings.xml and running the above commands can still leave your
password stored locally in plaintext. You may want to check the following
locations:

• Shell history (e.g. by running history). You may want to clear your history after
encrypting the above passwords

30
• Editor caches (e.g. ~/.viminfo)

Also note that the encrypted passwords can be decrypted by someone that has
the master password and settings security file. Keep this file secure (or stored
separately) if you expect the possibility that the settings.xml file may be
retrieved.

Password Escaping on different platforms

On some platforms it might be necessary to quote your password based on the


content of your password in particular having special characters like %, !, $ etc.,
in there. For example on Windows you have to be careful about things like the
following:

The following example will not work on Windows:

mvn --encrypt-master-password a!$%^b

whereas, the following will work on Windows:

mvn --encrypt-master-password "a!$%^b"

If you are on a linux/unix platform you should use single quotes for the above
master password, otherwise you will be astonished that the usage of the master-
password will not work (caused by the dollar sign and furthermore the
exclamation mark).

31
Prompting for Password

In Maven before version 3.2.1 you have to give the password on command line
as argument, which means you might need to escape your password. In addition
usually the shell stores the full history of commands you have entered, therefore
anyone with access to your computer could restore the password from the
shell`s history.

Starting with Maven 3.2.1 the password is an optional argument, which means if
you omit the password you will be prompted for it which prevents all the issues
mentioned above.

Therefore, we strongly recommend to use Maven 3.2.1 and above to prevent


problems with escaping special characters and of course security issues related
to bash history or environment issues in relationship with the password.

Mirrors

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0

https://maven.apache.org/xsd/settings-1.0.0.xsd">

...

<mirrors>

<mirror>

32
<id>planetmirror.com</id>

<name>PlanetMirror Australia</name>

<url>http://downloads.planetmirror.com/pub/maven2</url>

<mirrorOf>central</mirrorOf>

</mirror>

</mirrors>

...

</settings>

• id, name: The unique identifier and user-friendly name of this mirror. The id is
used to differentiate between mirror elements and to pick the corresponding
credentials from the <servers>section when connecting to the mirror.

• url: The base URL of this mirror. The build system will use this URL to connect
to a repository rather than the original repository URL.

• mirrorOf: The id of the repository that this is a mirror of. For example, to point
to a mirror of the Maven central repository
(https://repo.maven.apache.org/maven2/), set this element to central. More
advanced mappings like repo1,repo2 or *,!inhouse are also possible. This must
not match the mirror id.

33
Proxies

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0

https://maven.apache.org/xsd/settings-
1.0.0.xsd">

...

<proxies>

<proxy>

<id>myproxy</id>

<active>true</active>

<protocol>http</protocol>

<host>proxy.somewhere.com</host>

<port>8080</port>

<username>proxyuser</username>

<password>somepassword</password>

<nonProxyHosts>*.google.com|ibiblio.org</nonProxyHosts>

</proxy>

</proxies>

...

</settings>

34
• id: The unique identifier for this proxy. This is used to differentiate
between proxy elements.

• active: true if this proxy is active. This is useful for declaring a set of proxies,
but only one may be active at a time.

• protocol, host, port: The protocol://host:port of the proxy, separated into


discrete elements.

• username, password: These elements appear as a pair denoting the login and
password required to authenticate to this proxy server.

• nonProxyHosts: This is a list of hosts which should not be proxied. The


delimiter of the list is the expected type of the proxy server; the example
above is pipe delimited - comma delimited is also common.

2.2.3 Profiles

The profile element in the settings.xml is a truncated version of the pom.xml


profile element. It consists of the activation, repositories, pluginRepositories and
properties elements. The profile elements only include these four elements
because they concerns themselves with the build system as a whole (which is the
role of the settings.xml file), not about individual project object model settings.

If a profile is active from settings, its values will override any equivalently ID’d
profiles in a POM or profiles.xml file.

35
Lab:

Activation

Activations are the key of a profile. Like the POM’s profiles, the power of a
profile comes from its ability to modify some values only under certain
circumstances; those circumstances are specified via an activation element.

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0

https://maven.apache.org/xsd/settings-
1.0.0.xsd">

...

<profiles>

<profile>

<id>test</id>

<activation>

<activeByDefault>false</activeByDefault>

<jdk>1.5</jdk>

<os>

<name>Windows 7</name>

<family>Windows</family>

<arch>x86</arch>

<version>5.1.2600</version>

36
</os>

<property>

<name>mavenVersion</name>

<value>2.0.3</value>

</property>

<file>

<exists>${basedir}/file2.properties</exists>

<missing>${basedir}/file1.properties</missing>

</file>

</activation>

...

</profile>

</profiles>

...

</settings>

Activation occurs when all specified criteria have been met, though not all are
required at once.

• jdk: activation has a built in, Java-centric check in the jdk element. This will
activate if the test is run under a jdk version number that matches the prefix
given. In the above example, 1.5.0_06 will match. Ranges are also supported as
of Maven 2.1. See the maven-enforcer-plugin for more details about supported
ranges.

37
• os: The os element can define some operating system specific properties
shown above. See the maven-enforcer-plugin for more details about OS values.

• property: The profile will activate if Maven detects a property (a value which
can be dereferenced within the POM by ${name}) of the
corresponding name=value pair.

• file: Finally, a given filename may activate the profile by the existence of a file, or
if it is missing.

The activation element is not the only way that a profile may be activated.
The settings.xml file’s activeProfile element may contain the profile’s id. They
may also be activated explicitly through the command line via a comma
separated list after the -P flag (e.g. -P test).

To see which profile will activate in a certain build, use the maven-help-plugin.

mvn help:active-profiles

Activation of build profiles example:

A profile in Maven is an alternative set of configuration values which set or


override default values. Using a profile, you can customize a build for different
environments. Profiles are configured in the pom.xml and are given an identifier.
Then you can run Maven with a command-line flag that tells Maven to execute
goals in a specific profile. The following pom.xml uses a production profile to
override the default settings of the Compiler plugin.

38
In this example, we’ve added a profile named production that overrides the
default configuration of the Maven Compiler plugin. Let’s examine the syntax of
this profile in detail.

1. The profile element is in the pom.xml, it contains one or more profile


elements. Since profiles override the default settings in a pom.xml, the profile
element is usually listed as the last element in a pom.xml.

2. Each profile has to have an id element. This id element contains the name
which is used to invoke this profile from the command-line. A profile is
invoked by passing the -P<profile_id> command-line argument to Maven.

3. A profile element can contain many of the elements which can appear under
the project element of a POM XML Document. In this example, we’re
overriding the behavior of the Compiler plugin and we have to override the
plugin configuration which is normally enclosed in a build and a plugins
element.

4. We’re overriding the configuration of the Maven Compiler plugin. We’re


making sure that the bytecode produced by the production profile doesn’t
contain debug information and that the bytecode has gone through the
compiler’s optimization routines.

To execute mvn install under the production profile, you need to pass the -
Pproduction argument on the command-line. To verify that
the production profile overrides the default Compiler plugin configuration

mvn clean install -Pproduction -X

39
Using a Maven Profile to Override Production Compiler Settings

<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/maven-
v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>org.sonatype.mavenbook</groupId>

<artifactId>simple</artifactId>

<packaging>jar</packaging>

<version>1.0-SNAPSHOT</version>

<name>simple</name>

<url>http://maven.apache.org</url>

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>3.8.1</version>

<scope>test</scope>

</dependency>

</dependencies>

40
<profiles> (1)

<profile>

<id>production</id> (2)

<build> (3)

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-
compiler-plugin</artifactId>

<configuration>

<debug>false</debug>
(4)

<optimize>true</optimize>

</configuration>

</plugin>

</plugins>

</build>

</profile>

</profiles>

</project>

41
Properties

Maven properties are value placeholder, like properties in Ant. Their values are
accessible anywhere within a POM by using the notation ${X}, where X is the
property. They come in five different styles, all accessible from
the settings.xml file:

1. env.X: Prefixing a variable with “env.” will return the shell’s environment
variable. For example, ${env.PATH} contains the $path environment variable
(%PATH% in Windows).

2. project.x: A dot (.) notated path in the POM will contain the corresponding
element’s value. For example: <project><version>1.0</version></project> is
accessible via ${project.version}.

3. settings.x: A dot (.) notated path in the settings.xml will contain the
corresponding element’s value. For
example: <settings><offline>false</offline></settings> is accessible
via ${settings.offline}.

4. Java System Properties: All properties accessible


via java.lang.System.getProperties() are available as POM properties, such
as ${java.home}.

5. x: Set within a <properties /> element or an external files, the value may be
used as ${someVar}.

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

42
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0

https://maven.apache.org/xsd/settings-
1.0.0.xsd">

...

<profiles>

<profile>

...

<properties>

<user.install>${user.home}/our-
project</user.install>

</properties>

...

</profile>

</profiles>

...

</settings>

The property ${user.install} is accessible from a POM if this profile is active.

Example properties file:

<project>

...

<properties>

43
<server.url>http://localhost:8080/manager/html</server.url>

</properties>

...

<build>

<plugins>

<plugin>

...

<configuration>

<url>${server.url}</url>

<server>tomcat</server>

</configuration>

...

</plugin>

</plugins>

</build>

</project>

In the above example {Server.url} will be replaced by the actual URL at the run
time.

2.2.4 Repositories Configuration

Repositories are remote collections of projects from which Maven uses to


populate the local repository of the build system. It is from this local repository
that Maven calls its plugins and dependencies. Different remote repositories may

44
contain different projects, and under the active profile they may be searched for
a matching release or snapshot artifact.

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0

https://maven.apache.org/xsd/settings-
1.0.0.xsd">

...

<profiles>

<profile>

...

<repositories>

<repository>

<id>codehausSnapshots</id>

<name>Codehaus Snapshots</name>

<releases>

<enabled>false</enabled>

<updatePolicy>always</updatePolicy>

<checksumPolicy>warn</checksumPolicy>

</releases>

<snapshots>

<enabled>true</enabled>

45
<updatePolicy>never</updatePolicy>

<checksumPolicy>fail</checksumPolicy>

</snapshots>

<url>http://snapshots.maven.codehaus.org/maven2</url>

<layout>default</layout>

</repository>

</repositories>

<pluginRepositories>

...

</pluginRepositories>

...

</profile>

</profiles>

...

</settings>

• releases, snapshots: These are the policies for each type of artifact, Release or
snapshot. With these two sets, a POM has the power to alter the policies for
each type independently of the other within a single repository. For example,
one may decide to enable only snapshot downloads, possibly for development
purposes.

• enabled: true or false for whether this repository is enabled for the respective
type (releases or snapshots).

46
• updatePolicy: This element specifies how often updates should attempt to
occur. Maven will compare the local POM’s timestamp (stored in a repository’s
maven-metadata file) to the remote. The choices
are: always, daily (default), interval:X (where X is an integer in minutes) or never.

• checksumPolicy: When Maven deploys files to the repository, it also deploys


corresponding checksum files. Your options are to ignore, fail, or warn on
missing or incorrect checksums.

• layout: In the above description of repositories, it was mentioned that they all
follow a common layout. This is mostly correct. Maven 2 has a default layout
for its repositories; however, Maven 1.x had a different layout. Use this
element to specify which, if it is default or legacy.

2.2.5 Plugin Repositories

Repositories are home to two major types of artifacts. The first is artifacts that
are used as dependencies of other artifacts. These are the majority of plugins
that reside within central. The other type of artifact is plugins. Maven plugins are
themselves a special type of artifact. Because of this, plugin repositories may be
separated from other repositories (although, I have yet to hear a convincing
argument for doing so). In any case, the structure of
the pluginRepositories element block is similar to the repositories element.
The pluginRepository elements, each specify a remote location of where Maven
can find new plugins.

47
Active Profiles

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0

https://maven.apache.org/xsd/settings-
1.0.0.xsd">

...

<activeProfiles>

<activeProfile>env-test</activeProfile>

</activeProfiles>

</settings>

The final piece of the settings.xml puzzle is the activeProfiles element. This
contains a set of activeProfile elements, which each have a value of a profile id.
Any profile iddefined as an activeProfile will be active, regardless of any
environment settings. If no matching profile is found, nothing will happen. For
example, if env-test is an activeProfile, a profile in a pom.xml (or profile.xml with
a corresponding id will be active. If no such profile is found, then execution will
continue as normal.

2.2.6 Deploying Artifacts to Nexus Repository

In order for Maven to be able to deploy the artifacts it creates in


the package phase of the build, it needs to define the repository information
where the packaged artifacts will be deployed, via
the distributionManagement element:

48
Lab:

Note: This lab requires the Nexus server to be up and running on the local host
with port 8081

1. Add distribution management tag in pom.xml

<distributionManagement>

<snapshotRepository>

<id>nexus-snapshots</id>

<url>http://localhost:8081/nexus/content/repositories/snap
shots</url>

</snapshotRepository>

</distributionManagement>

2. Maven handles the deployment mechanism via the maven-deploy-plugin – this


mapped to the deployment phase of the default Maven lifecycle.

Add maven deploy plugin to pom.xml

<plugin>

<artifactId>maven-deploy-plugin</artifactId>

<version>2.8.1</version>

<executions>

<execution>

<id>default-deploy</id>

49
<phase>deploy</phase>

<goals>

<goal>deploy</goal>

</goals>

</execution>

</executions>

</plugin>

3. Define the nexus server URL in plugin section in pom.xml

<plugin>

<configuration>

<serverId>nexus</serverId>

<nexusUrl>http://localhost:8081/nexus/</nexusUrl>

<skipStaging>true</skipStaging>

</configuration>

</plugin>

Deployment to Nexus is a secured operation – and a deployment user exists for


this operation on Nexus instance. Add the nexus server credentials in settings.xml

<servers>

<server>

<id>nexus</id>

50
<username>deployment</username>

<password>password_for_the_deployment_user</password>

</server>

</servers>

Now run below command to deploy the project artifacts to nexus repository:

mvn clean deploy

2.2.7 Maven 3.3.x Logging

Maven 2.x and 3.3.x use Plexus logging API with basic Maven implementation
writing to stdout.

We have reached the decision that SLF4J is the best option for a logging API: SLF4J
has reached a certain level of ubiquity and while SLF4J may not be perfect, it's the
de facto standard and it's pointless to try and remake another one. There are
many implementations to choose from, including Logback and Log4j2. All the hard
work has been done. All the bridges and funnels for other systems function well,
which allows others to use whatever logging implementation they like in their
components, while still being able to have integrated logging.

The standard Maven distribution, from Maven 3.1.0 onward, uses the SLF4J
API for logging combined with the SLF4J Simple implementation. Future versions
may use a more advanced implementation, but we chose to start simple.

Looking at the distribution you will see the following layout where
the simplelogger.properties, slf4j-api-x.y.z-jar and slf4j-simple-
x.y.z.jar specifically relates to the SLF4J implementation:

51
1. apache-maven-3.x.y

2. ├── LICENSE.txt

3. ├── NOTICE.txt

4. ├── README.txt

5. ├── bin

6. │ └── ...

7. ├── boot

8. │ └── ...

9. ├── conf

10. │ ├── logging

11. │ │ └── simplelogger.properties

12.│ └── settings.xml

13.└── lib

14. ├── ...

15. ├── slf4j-api-x.y.z.jar

16. ├── slf4j-simple-x.y.z.jar

17. └── ...

2.2.8 Configuring a Proxy

You can configure a proxy to use for some or all of your HTTP requests with
Maven. The username and password are only required if your proxy requires
basic authentication (note that later releases may support storing your
passwords in a secured keystore - in the meantime, please ensure your

52
settings.xml file (usually ${user.home}/.m2/settings.xml) is secured with
permissions appropriate for your operating system).

The nonProxyHosts setting accepts wild cards, and each host not to proxy is
separated by the | character. This matches the JDK configuration equivalent.

Lab:

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

53
.

</settings>

2.2.9 Using Mirrors for Repositories

With Repositories you specify from which locations you want


to download certain artifacts, such as dependencies and maven-plugins.
Repositories can be declared inside a project, which means that if you have your
own custom repositories, those sharing your project easily get the right settings
out of the box. However, you may want to use an alternative mirror for a
particular repository without changing the project files.

• Some reasons to use a mirror are as follows:

• There is a synchronized mirror on the internet that is geographically closer and


faster.

• You want to replace a particular repository with your own internal repository
which you have greater control over.

• You want to run a repository manager to provide a local cache to a mirror and
need to use its URL instead.

To configure a mirror of a given repository, you provide it in your settings file


(${user.home}/.m2/settings.xml), giving the new repository its own id and url,
and specify the mirrorOfsetting that is the ID of the repository you are using a
mirror of. For example, the ID of the main Maven Central US repository included
by default is central, so to use the European Central instance, you would
configure the following:

54
<settings>

...

<mirrors>

<mirror>

<id>UK</id>

<name>UK Central</name>

<url>http://uk.maven.org/maven2</url>

<mirrorOf>central</mirrorOf>

</mirror>

</mirrors>

...

</settings>

Note that there can be at most one mirror for a given repository. In other words,
you cannot map a single repository to a group of mirrors that all define the
same <mirrorOf> value. Maven will not aggregate the mirrors, but simply picks
the first match. If you want to provide a combined view of several repositories,
use a repository manager instead.

The settings descriptor documentation can be found on the Maven Local Settings
Model Website.

Note: The official Maven 2 repository is


at http://repo.maven.apache.org/maven2 hosted in the US,
or http://uk.maven.org/maven2 hosted in the UK.

55
A list of known mirrors is available in the Repository Metadata. These mirrors
may not have the same contents and we don't support them in any way.

Using A Single Repository

You can force Maven to use a single repository by having it mirror all repository
requests. The repository must contain all of the desired artifacts, or be able to
proxy the requests to other repositories. This setting is most useful when using
an internal company repository with the Maven Repository Manager to proxy
external requests.

To achieve this, set mirrorOf to *.

Note: This feature is only available in Maven 2.0.5+.

<settings>

...

<mirrors>

<mirror>

<id>internal-repository</id>

<name>Maven Repository Manager running on


repo.mycompany.com</name>

<url>http://repo.mycompany.com/proxy</url>

<mirrorOf>*</mirrorOf>

</mirror>

</mirrors>

...

56
</settings>

Advanced Mirror Specification

A single mirror can handle multiple repositories when used in conjunction with a
repository manager.

The syntax as of Maven 2.0.9:

• * matches all repo ids.

• external:* matches all repositories except those using localhost or file based

repositories. This is used in conjunction with a repository manager when you


want to exclude redirecting repositories that are defined for Integration
Testing.

• multiple repositories may be specified using a comma as the delimiter.

• an exclamation mark may be used in conjunction with one of the above


wildcards to exclude a repository id.

The position of wildcards within a comma separated list of repository identifiers


is not important as the wildcards defer to further processing and explicit includes
or excludes stop the processing, overruling any wildcard match.

When you use the advanced syntax and configure multiple mirrors, keep in mind
that their declaration order matters. When Maven looks for a mirror of some
repository, it first checks for a mirror whose <mirrorOf> exactly matches the
repository identifier. If no direct match is found, Maven picks the first mirror
declaration that matches according to the rules above (if any). Hence, you may

57
influence the match order by changing the order of the definitions in
the settings.xml

Examples:

• * = everything

• external:* = everything not on the localhost and not file based.

• repo,repo1 = repo or repo1

• *,!repo1 = everything except repo1

Note: This feature is available from Maven 2.0.9+.

<settings>

...

<mirrors>

<mirror>

<id>internal-repository</id>

<name>Maven Repository Manager running on


repo.mycompany.com</name>

<url>http://repo.mycompany.com/proxy</url>

<mirrorOf>external:*,!foo</mirrorOf>

</mirror>

<mirror>

<id>foo-repository</id>

<name>Foo</name>

58
<url>http://repo.mycompany.com/foo</url>

<mirrorOf>foo</mirrorOf>

</mirror>

</mirrors>

...

</settings>

2.3 Maven Plugins

By default, Maven handles the deployment mechanism via the maven-deploy-


plugin – this mapped to the deployment phase of the default Maven lifecycle:

<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.1</version>
<executions>
<execution>
<id>default-deploy</id>
<phase>deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>

59
The maven-deploy-plugin is a viable option to handle the task of deploying to
artifacts of a project to Nexus, but it was not built to take full advantage of what
Nexus has to offer. Because of that fact, Sonatype built a Nexus specific plugin –
the nexus-staging-maven-plugin – that is actually designed to take full advantage
of the more advanced functionality that Nexus has to offer – functionality such as
staging.

Although, for a simple deployment process we do not require staging


functionality, we will go forward with this custom Nexus plugin since it was built
with the clear purpose to talk to Nexus well.

The only reason to use the maven-deploy-plugin is to keep open the option of
using an alternative to Nexus in the future – for example,
an Artifactory repository. However, unlike other components that may actually
change throughout the lifecycle of a project, the Maven Repository Manager is
highly unlikely to change, so that flexibility is not required.

So, the first step in using another deployment plugin in the deploy phase is to
disable the existing, default mapping:

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-deploy-plugin</artifactId>

<version>${maven-deploy-plugin.version}</version>

<configuration>

<skip>true</skip>

</configuration>

60
</plugin>

Now, we can define:

<plugin>

<groupId>org.sonatype.plugins</groupId>

<artifactId>nexus-staging-maven-plugin</artifactId>

<version>1.5.1</version>

<executions>

<execution>

<id>default-deploy</id>

<phase>deploy</phase>

<goals>

<goal>deploy</goal>

</goals>

</execution>

</executions>

<configuration>

<serverId>nexus</serverId>

<nexusUrl>http://localhost:8081/nexus/</nexusUrl>

<skipStaging>true</skipStaging>

</configuration>

</plugin>

The deploy goal of the plugin is mapped to the deploy phase of the Maven build.

61
Also notice that, as discussed, we do not need staging functionality in a simple
deployment of -SNAPSHOT artifacts to Nexus, so that is fully disabled via
the <skipStaging> element.

The Global settings.xml

Deployment to Nexus is a secured operation – and a deployment user exists for


this purpose out of the box on any Nexus instance.

Configuring Maven with the credentials of this deployment user, so that it can
interact correctly with Nexus, cannot be done in the pom.xml of the project. This
is because the syntax of the pom doesn’t allow it, not to mention the fact that
the pom may be a public artifact, so not well suited to hold credential
information.

The credentials of the server have to be defined in the global Maven setting.xml:

<servers>

<server>

<id>nexus-snapshots</id>

<username>deployment</username>

<password>the_pass_for_the_deployment_user</password>

</server>

</servers>

62
The server can also be configured to use key based security instead of raw and
plaintext credentials.

Maven Plugins

Maven is—at its heart—a plugin execution framework; all work is done by
plugins. Looking for a specific goal to execute? This page lists the core plugins
and others. There are the build and the reporting plugins:

• Build plugins will be executed during the build and they should be configured
in the <build/> element from the POM.

• Reporting plugins will be executed during the site generation and they should
be configured in the <reporting/> element from the POM. Because the result of
a Reporting plugin is part of the generated site, Reporting plugins should be
both internationalized and localized. You can read more about the localization
of our plugins and how you can help.

Plugin Version Description

Core plugins Plugins corresponding to default core phases (ie.


clean, compile). They may have multiple goals as
well.

clean 3.1.0 Clean up after the build.

compiler 3.8.0 Compiles Java sources.

deploy 3.0.0-M1 Deploy the built artifact to the remote repository.

63
Plugin Version Description

failsafe 3.0.0-M1 Run the JUnit integration tests in an isolated


classloader.

install 3.0.0-M1 Install the built artifact into the local repository.

resources 3.1.0 Copy the resources to the output directory for


including in the JAR.

site 3.7.1 Generate a site for the current project.

surefire 3.0.0-M1 Run the JUnit unit tests in an isolated classloader.

verifier 1.1 Useful for integration tests - verifies the existence of


certain conditions.

Packaging These plugins relate to packaging respective artifact


types/tools types.

ear 3.0.1 Generate an EAR from the current project.

ejb 3.0.1 Build an EJB (and optional client) from the current
project.

jar 3.1.0 Build a JAR from the current project.

rar 2.4 Build a RAR from the current project.

war 3.2.2 Build a WAR from the current project.

64
Plugin Version Description

app-client/acr 3.1.0 Build a JavaEE application client from the current


project.

shade 3.2.1 Build an Uber-JAR from the current project, including


dependencies.

source 3.0.1 Build a source-JAR from the current project.

jlink 3.0.0-alpha-1 Build Java Run Time Image.

jmod 3.0.0-alpha-1 Build Java JMod files.

Reporting Plugins which generate reports, are configured as


plugins reports in the POM and run under the site
generation lifecycle.

changelog 2.3 Generate a list of recent changes from your SCM.

changes 2.12.1 Generate a report from an issue tracker or a change


document.

checkstyle 3.0.0 Generate a Checkstyle report.

doap 1.2 Generate a Description of a Project (DOAP) file from a


POM.

docck 1.1 Documentation checker plugin.

javadoc 3.0.1 Generate Javadoc for the project.

65
Plugin Version Description

jdeps 3.1.1 Run JDK's JDeps tool on the project.

jxr 3.0.0 Generate a source cross reference.

linkcheck 1.2 Generate a Linkcheck report of your project's


documentation.

pmd 3.11.0 Generate a PMD report.

project-info- 3.0.0 Generate standard project reports.


reports

surefire- 3.0.0-M1 Generate a report based on the results of unit tests.


report

Tools These are miscellaneous tools available through


Maven by default.

ant 2.4 Generate an Ant build file for the project.

antrun 1.8 Run a set of ant tasks from a phase of the build.

archetype 3.0.1 Generate a skeleton project structure from an


archetype.

assembly 3.1.0 Build an assembly (distribution) of sources and/or


binaries.

dependency 3.1.1 Dependency manipulation (copy, unpack) and

66
Plugin Version Description

analysis.

enforcer 3.0.0-M2 Environmental constraint checking (Maven Version,


JDK etc), User Custom Rule Execution.

gpg 1.6 Create signatures for the artifacts and poms.

help 3.1.0 Get information about the working environment for


the project.

invoker 3.1.0 Run a set of Maven projects and verify the output.

jarsigner 3.0.0 Signs or verifies project artifacts.

jdeprscan 3.0.0-alpha-1 Run JDK's JDeprScan tool on the project.

patch 1.2 Use the gnu patch tool to apply patch files to source
code.

pdf 1.4 Generate a PDF version of your project's


documentation.

plugin 3.6.0 Create a Maven plugin descriptor for any mojos found
in the source tree, to include in the JAR.

release 2.5.3 Release the current project - updating the POM and
tagging in the SCM.

remote- 1.6.0 Copy remote resources to the output directory for

67
Plugin Version Description

resources inclusion in the artifact.

repository 2.4 Plugin to help with repository-based tasks.

scm 1.11.1 Execute SCM commands for the current project.

scm-publish 3.0.0 Publish your Maven website to a scm location.

stage 1.0 Assists with release staging and promotion.

toolchains 1.1 Allows to share configuration across plugins.

2.3.1 Using the Maven Clean plugin

● When a project is built, it is important to ensure that it is not adversely


affected by artifacts of an earlier build. Usually, build tools generate artifacts in
a well-defined folder, namely the target folder, called project working
directory. Before a new build, this folder is usually deleted.

Lab:

Let's start using the Maven Clean plugin by performing the following steps:

1. Open the command prompt.

2. Run the following Maven command in the simple Maven project that we
created in the Creating a simple project with Maven recipe in the
previous section

68
mvn clean

Observe the various steps that get executed:

[INFO] --- maven-clean-plugin:2.4.1:clean (default-


clean) @ simple-project ---

[INFO] Deleting C:\projects\apache-maven-


cookbook\simple-project\target

If there are no files/folders to delete, you will not see the similar output:

[INFO] --- maven-clean-plugin:2.5:clean (default-


clean) @ simple-project ---

[INFO]

[INFO] BUILD SUCCESS

When the clean phase is invoked, Maven automatically infers that


the clean lifecycle is invoked.

It uses the Maven Clean plugin for this. The plugin has only one goal,
namely clean, to clean the working directory.

In the case of Maven, the working directory is called target . Maven creates this
directory when a build is done. The clean goal of the plugin attempts to delete
this directory.

69
As clean is a separate lifecycle from the default (build) lifecycle, clean needs
to be explicitly called before the default lifecycle if you need to ensure that the
working directory is removed.

CLEANING AUTOMATICALLY

In the previous example, as we used the default behavior of the plugin and did
not need to make any configurations, we did not need to make any change to the
pom configuration file. However, what if we want to ensure that the clean goal
is run without explicitly calling it?

To do this, we need to define the plugin with some parameters in our pom file:

Lab:

1. Let us add the following code in our pom file:

<build>

<plugins>

<plugin>

<artifactId>maven-clean-
plugin</artifactId>

<version>2.6</version>

<executions>

<execution>

<id>auto-clean</id>

<phase>initialize</phase>

<goals>

70
<goal>clean</goal>

</goals>

</execution>

</executions>

</plugin>

</plugins>

</build>

Though the preceding declaration may look verbose, all we are asking is for
the clean goal to be invoked during the initialize phase of the project. We
are identifying this execution with an id called auto-clean.

2. Now run the following command on the command prompt:

mvn package

3. You will see the following screenshot:

Even though we did not call the clean phase, the clean goal got invoked
because it was configured in the pom file to run in the initialize phase.

71
SKIPPING THE DELETION OF THE WORKING DIRECTORY

Let us look at the converse of the preceding use case. For some reason, we do not
want the working directory to be deleted, even if clean is run. To do this,
perform the following steps:

1. Configure the plugin as follows:

<plugin>

<artifactId>maven-clean-plugin</artifactId>

<version>2.6</version>

<configuration>

<skip>true</skip>

</configuration>

</plugin>

2. Run the following command on the command prompt:

mvn clean

3. Observe the output, which is as follows:

C:\projects\apache-maven-cookbook\project-with-clean-
disabled>mvn clean

[INFO] Scanning for projects...

[INFO]

[INFO]

72
[INFO] Building Project with clean disabled 1.0-
SNAPSHOT

[INFO]

[INFO]

[INFO] --- maven-clean-plugin:2.6:clean (default-


clean) @ project-with-clean-disabled ---

[INFO] Clean is skipped.

Setting the skip plugin property to true indicates to Maven that the clean goal
must be skipped.

DELETING ADDITIONAL FOLDERS/FILES

What if your project has an additional folder, say report , besides target , which
is perhaps created by another script, and you want that to be deleted as well? We
use the following steps to do the same:

Lab:

1. Configure the plugin as follows:

<plugin>

<artifactId>maven-clean-plugin</artifactId>

<version>2.6</version>

<configuration>

<filesets>

73
<fileset>

<directory>${basedir}/report</directory>

</fileset>

</filesets>

</configuration>

</plugin>

You have now configured the plugin to delete an additional directory

2. Create a report folder for the purpose of testing.

3. Run the following command on command prompt:

mvn clean

4. You will now see the similar output:

C:\projects\apache-maven-cookbook\project-with-
clean-additional-folder>mvn clean

[INFO] Scanning for projects...

[INFO]

[INFO]

[INFO] Building Project with clean additional folder


1.0-SNAPSHOT

[INFO]

74
[INFO]

[INFO] --- maven-clean-plugin:2.6:clean (default-


clean) @ project-with-clean-additional-folder ---

[INFO] Deleting C:\projects\apache-maven-


cookbook\project-with-clean-additional-folder\report
(includes = [], excludes = [])

The report folder is deleted as well. In fact, Maven can be configured to delete
(or not delete) specific folders and files inside that folder as well.

2.3.2 Using the Maven Compiler plugin

Compilation is an essential task performed by a build tool. Maven uses the Maven
Compiler plugin to do the compilation. The plugin provides several configurations
to make the compilation flexible.

Lab:

To use the Maven Compiler plugin, perform the following steps:

1. Open a command prompt.

2. Run the following Maven command on the simple project that we created in
the Creating a simple project with Maven recipe in the previous section

mvn compile

3. Observe the output, which is as follows:

[INFO] --- maven-compiler-plugin:2.3.2:compile


(default-compile) @ simple-project ---

75
[INFO] Compiling 1 source file to
C:\projects\apache-maven-cookbook\simple-
project\target\classes

Lab:

The compile parameter indicates the invocation of the default lifecycle to


Maven. Maven Lifecycle, Maven runs all the phases up to and including
the compile phase in order.

The compile phase itself essentially runs the compile goal of the Maven
Compiler plugin.

This compiles the Java source files to classes in the target/classes folder.

One question would have struck you. What about the test classes? Why does
the compile phase not compile the test sources?

The answer lies in the way Maven handles the lifecycle and phases of the
lifecycle. Why would you want to compile the test sources unless you want to run
the tests?

What if we want to compile the test sources?

Let us try running the following command on the command prompt:

mvn test

76
Observe the output as shown in the following screenshot:

As we specified the test phase, Maven ran all phases prior to it, which includes
compiling the test sources using the testCompile goal of the Maven Compiler
plugin.

2.3.3 Using the Maven Surefire Plugin to Run Unit Tests

A best practice of software development is writing automated unit tests for the
code that you develop. Let us now see how to run these tests.

The plugin that does this job is the Maven Surefire plugin.

Lab:

To run unit tests using the Maven Surefire plugin, perform the following steps:

1. Open the command prompt.

2. Run the following command on one of our sample projects:

mvn test

3. Observe the various steps that get executed:

[INFO] --- maven-surefire-plugin:2.10:test (default-


test) @ simple-project ---

77
[INFO] Surefire report directory:
C:\projects\apache-maven-cookbook\simple-
project\target\surefire-reports

---

T E S T S

---

Running com.skaas.sample.AppTest

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0,


Time elapsed: 0 sec

Results:

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

The test parameter indicates the invocation of the default lifecycle to Maven.
Maven Lifecycle, Maven runs all the phases up to and including the test phase,
in order.

The test phase itself essentially runs the test goal of the Maven Surefire plugin.

This runs the test classes that are present in the target/test-classes folder.

The test that we have is a test written using the JUnit framework. Not only does
the plugin run the test, it also generates a test report that can be used to analyze
failures as well as test coverage.

78
Check the surefire-reports folder:

While the text file contains the summary report, the XML file has the details of
each of the tests.

The Surefire plugin provides many configurations to make testing easier.

USING TESTNG

JUnit is not the only way to write automated unit tests. You could use TestNG
(http://testng.org) or even write your tests without using any framework (by
using Java asserts).

Surefire determines the framework to be used based on the dependencies that


have been defined.

Our earlier example, ran JUnit tests because we had defined


the junit dependency in the pom file.

Let us now write a test using TestNG and see what needs to change for it to work.
Refer to the Maven project with TestNG.

Lab:

The only change in the pom file is to replace the junit dependency
with testng :

79
<dependency>

<groupId>org.testng</groupId>

<artifactId>testng</artifactId>

<version>6.8.8</version>

<scope>test</scope>

</dependency>

Run the following command on command prompt:

mvn test

The tests are now run in using TestNG:

[INFO]

[INFO] --- maven-surefire-plugin:2.10:test (default-


test) @ project-with-testNG---

[INFO] Surefire report directory: C:\projects\apache-


maven-cookbook\project-with-testNG\target\surefire-
reports

T E S T S

Running com.skaas.sample.AppTest

Set up run

80
Fast test

Slow test

Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time


elapsed: 0.609 sec

Now, examine the surefire-reports folder. It has a different set of files


corresponding to testng :

The same tests work with TestNG and JUnit as TestNG can run JUnit tests.

81
SKIPPING TESTS

There may be situations where you might not want to run the tests; some tests
are possibly broken. This can be done in the following ways:

Lab:

● Configuring the Surefire plugin in the pom file: Configure your Surefire plugin
in the pom.xml file using the following code:

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-surefire-
plugin</artifactId>

<version>2.17</version>

<configuration>

<skipTests>true</skipTests>

</configuration>

</plugin>

</plugins>

Now, run the following command:

mvn test

82
You will see the similar output:

[INFO]

[INFO] --- maven-surefire-plugin:2.17:test


(default-test) @ project-with-tests-skipped ---

[INFO] Tests are skipped.

● Issuing an mvn command with a command-line parameter: The tests can be


skipped even by issuing the following command:

mvn –DskipTests tests

SKIPPING THE COMPILATION OF TEST SOURCES

The skipTests parameter used in the preceding mvn command skips running of
tests, but the test sources still get compiled by the earlier phases/goals. To skip
the compilation of test sources, you can run the following command:

mvn –Dmaven.test.skip=true package

This will completely skip the test compilation and test execution.

2.3.4 Using the Maven Resources Plugin

The Resources plugin comes into picture to copy project resources to the output
directory. The resources can be for the project to run or for the purpose of
testing.

83
Lab:

Let's start using the Maven Resources plugin by performing the following steps:

1. Open the command prompt.

2. Run the following command on the simple project that we created earlier:

mvn process-resources

3. Observe what happens:

[INFO] --- maven-resources-plugin:2.5:resources


(default-resources) @ simple-project ---

[INFO] skip non existing resourceDirectory


C:\projects\apache-maven-cookbook\simple-
project\src\main\resources

When we specify the process-resources phase, Maven executes


the resources goal of maven-resources-plugin , which is bound to
the process-resources lifecycle phase.

In the earlier project, there are no resources and hence, resources are not copied.

If you add a file in src\main\resources (as in the case of the project-


with-resources project), you will see the similar output:

[INFO] --- maven-resources-plugin:2.5:resources


(default-resources) @ project-with-properties ---

[INFO] Copying 1 resource

84
You could also explicitly invoke the plugin's goal as follows:

mvn resources:resources

You could also invoke any phase following the process-resources phase,
which will trigger resource processing as well:

mvn compile

There is a separate goal to copy test resources to provide separation of the main
and test resources. Like project resources, the test resource processing can be
invoked in three ways, which are as follows:

● By specifying a phase that will automatically invoke phases before it:

mvn process-test-resources

● By explicitly stating the plugin's goal:

mvn resources:testResources

● By a phase following process-test-resources :

mvn test

What if we had resources in additional folders? The Maven Resources plugin


allows us to configure these additional folders.

Let's say we have an additional resources folder,


namely src/main/additional . We can configure the pom.xml file as follows:

85
<build>

<resources>

<resource>

<directory>src/main/resources</directory>

</resource>

<resource>

<directory>src/main/additional</directory>

</resource>

</resources>

</build>

Now, run the following command:

mvn process-resources

Observe the output:

[INFO] --- maven-resources-plugin:2.5:resources


(default-resources) @ project-with-additional-
resources ---

[INFO] Copying 1 resource

[INFO] Copying 1 resource

The line Copying 1 resource repeats twice, indicating the copying happening
from two folders.

86
2.3.5 Using Eclipse to Run Maven Goals

If you are using Eclipse to develop your project, it is good to know how to run
some of the plugins we have discussed earlier using the IDE.

Lab:

To run Maven goals using Eclipse, use the following steps:

1. Open the simple project in Eclipse.

2. Right-click on the project.

3. Choose Run As.

4. View the available Maven options:

87
Eclipse provides an option to run various goals from the IDE. Among the ones we
have seen in this section, clean , compile , and test are offered by Eclipse.
There are a few other options as well.

In addition, Eclipse also allows us to modify the configurations as suitable.

Eclipse also allows the project to be Run As a Java Application in the traditional
way (without using any Maven plugins). Likewise, it allows a JUnit Test to be run
without using Maven.

2.4 Maven Assembly

A typical project requirement is to aggregate the project output along with its
dependencies, modules, and other files into a single distributable archive. An
assembly is a group of files, directories, and dependencies that are assembled
into an archive format and distributed. Maven provides prefabricated assembly
descriptors to build these assemblies. The descriptors handle common
operations, such as packaging a project's artifact, along with the dependencies.

Maven should be set up on your system and verified to work.

Lab:

1. Open a Maven project for which you want to generate the assembly; in our
case, project-with-assembly .

2. Add the following plugin and configuration to the pom file:

<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>

88
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-
dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.skaas.sample.App</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>

3. Run the following Maven command:

mvn clean package

89
4. Observe the output:

[INFO] --- maven-assembly-plugin:2.5.3:single (make-


assembly) @ project-with-assembly ---

5. [INFO] Building jar: C:\projects\apache-maven-


cookbook\project-with-assembly\target\project-
with-assembly-1.0-SNAPSHOT-jar-with-
dependencies.jar

6. Run the created distribution JAR:

C:\projects\apache-maven-cookbook\project-with-
assembly\target>java -jar project-with-assembly-1.0-
SNAPSHOT-jar-with-dependencies.jar

07:13:25.660 [main] INFO com.skaas.sample.App -


Hello World

We made the following changes to the pom file:

● We chose jar-with-dependencies , one of the prefabricated assembly


descriptors provided by the Maven Assembly plugin. This creates a single
JAR with all the dependencies of the project.

● We also used the archive configuration to specify the main class of the
project. This is to make the JAR file executable.

● We then specified when the single goal of assembly should be run, namely,
the package phase.

90
When Maven ran, it used the preceding configurations to assemble a JAR with
dependencies in the package phase. We could run this as a normal executable
JAR.

Besides predefined descriptors, the Maven Assembly plugin also allows us to


create custom descriptors that can have fine-grained control over the contents of
the assembly.

The Assembly plugin can also build an assembly from a multi-module project,
where the modules can be part of the final assembly.

While opening the JAR file, you would have observed that all the dependent JARs
have been unpacked as well.

This is due to the default configuration for the predefined descriptor. Let us see
how to create the same distribution but retain dependant JARs as they are. To do
this, we will now use one Maven JAR plugin, which uses a custom class loader to
load dependant JARs within the parent JAR:

Lab:

1. Open the project for which you want to create an executable with unpackaged
dependant jars ( project-with-one-jar ).

2. Add the following plugin in the pom file:

91
<plugin>

<groupId>org.dstovall</groupId>

<artifactId>onejar-maven-plugin</artifactId>

<version>1.4.4</version>

<executions>

<execution>

<id>make-assembly</id>

<phase>package</phase>

<goals>

<goal>one-jar</goal>

</goals>

</execution>

</executions>

</plugin>

3. Add the JAR plugin to specify the main class for the executable JAR:

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-jar-plugin</artifactId>

<configuration>

<archive>

<manifest>

92
<mainClass>com.skaas.sample.App</mainClass>

</manifest>

</archive>

</configuration>

</plugin>

4. Add the following code as the plugin binaries are not in the central Maven
repository:

<pluginRepositories>

<pluginRepository>

<id>onejar-maven-
plugin.googlecode.com</id>

<url>http://onejar-maven-
plugin.googlecode.com/svn/mavenrepo</url>

</pluginRepository>

</pluginRepositories>

5. Run the following command:

mvn package

6. Run the generated executable and observe the result:

java -jar project-with-one-jar-1.0-SNAPSHOT.one-


jar.jar

06:57:45.995 [main] INFO com.skaas.sample.App -


Hello World

93
7. Open the created JAR file:

We can see that in contrast to the assembly JAR, the executable JAR is created
without unpacking the libraries (dependencies) involved.

8. Navigate to the lib folder in the JAR:

The dependant JARs are stored in the lib folder.

2.5 Maven Repository Management


There are three types of Maven repositories:

● Local: This is the repository in your computer filesystem.

94
● Remote: This is the repository from where the required Maven files get
downloaded.

● Mirrors: These are repository managers, such as Nexus and Artifactory, that
mirror various repositories.

You will have seen Maven downloading a number of files (called poms and jars).
Let us see where they are located in your computer:

● Go to your HOME folder (C:\Users\username) in the case of Microsoft


Windows, /Users/username for Mac, and, /home/username (or a similar
location) for Linux

● You will notice the .m2 folder and within that, a subfolder called repository

● You will see a number of folders and files that are used by Maven

You may want to change this location for the following reasons:

● You may want to conserve space in the C drive and store these folders and files
in the D drive on Microsoft Windows.

● You may want to take a back up of the contents. Backup software usually
backs up contents in specific folders of the filesystem.

● Your organization may have a policy for all users to store a local repository in
the same folder.

To change the location of the Maven repository, perform the following steps:

1. Create a file called settings.xml in the .m2 folder.

2. Add the following contents to the settings.xml file that you just created:

95
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0

http://maven.apache.org/xsd/settings-1.0.0.xsd">

<localRepository>C:/software/maven</localRepository>

</settings>

Notice the highlighted part of the preceding code. We have changed the location
of the repository contents to C:\software\maven. You can change it to any valid
folder name.

3. Delete the repository subfolder and run the mvn package command again.

You will now notice that the repository folder is not created in the .m2 folder.
Instead, it is created in C:\software\maven.

Maven determines the location of the local repository in the following way:

● If settings.xml exists in the user's .m2 folder, which contains


the <localRepository> tag, then Maven uses its contents to determine
the location

● If not, Maven will check if localRepository is explicitly defined in the


default settings.xml, present in the conf folder of the Maven installation

● If it is not present there, Maven will use the default value for the local
repository, which is the user's .m2 folder

96
Manually installing dependencies that are not available in a repository:

There may be situations where a library, which is not present in any Maven
repository, needs to be used. We have seen one way to use it, that is, specifying it
as a dependency with system scope and explicitly specifying the path to it.

The problem with this approach is that this dependency will not be available if
you need to distribute your project as a library.

Maven provides a mechanism to install an artifact to your local repository so that


you can declare and use it like other dependencies.

Lab:

Use the following steps to manually install the dependencies that aren't available
in a repository:

1. Add the following dependency to the simple project that we created earlier:

<dependency>

<groupId>org.apache.tomcat</groupId>

<artifactId>apache-tomcat</artifactId>

<version>8.0.14</version>

<type>tar.gz</type>

</dependency>

The project will fail to compile with the error of a missing dependency

97
2. Now run the following Maven command:

mvn install:install-file -DgroupId=org.apache.tomcat -


DartifactId=apache-tomcat -Dversion=8.0.14 -
Dpackaging=tar.gz -
Dfile=C:\Users\gnanendra\Downloads\apache-tomcat-
8.0.14.tar.gz -DgeneratePom=true

3. Note the result:

[INFO] --- maven-install-plugin:2.4:install-file (default-


cli) @ project-with-dependency-not-in-repo ---

[INFO] Installing C:\Users\raghu\Downloads\apache-tomcat-


8.0.14.tar.gz to C:\software\maven\org\apache\tomcat\apache-
tomcat\8.0.14\apache-tomcat-8.0.14.tar.gz

[INFO] Installing

C:\Users\raghu\AppData\Local\Temp\mvninstall8295760271813162
395.pom to C:\software\maven\org\apache\tomcat\apache-
tomcat\8.0.14\apache-tomcat-8.0.14.pom

The install-file goal of the Maven Install plugin allows dependencies to be installed
to the local repository. It takes groupId, artifactId, version, and packaging type as
parameters so that it can place the dependency suitably in the repository as well
as create a simple pom file for it.

This method is not ideal in a project with multiple developers, as each developer
needs to perform this step manually. One way to deal with this is to install this
dependency in a repository manager that is used by the organization. As the

98
developers will be using this repository manager as a mirror, Maven will find the
dependency from the mirror and proceed.

In such a case, we could use the deploy goal of the Maven deploy plugin to install
the artifact to the remote repository.

Some remote repositories have access control. Maven allows access details to be
specified in the server element. It is best to specify this in settings.xml as this file
is specific to each user.

Projects with dependencies that are installed by this method are again not
distributable, as those using them will fail to find the dependencies.

Where projects are expected to be distributed and included by others as


dependencies, a different approach needs to be followed—the static in-project
repository solution. Use the following steps to follow the in-project repository
approach:

1. Create a repository inside your project by adding the following in your pom
file:

<repository>

<id>in-project-repo</id>

<releases>

<checksumPolicy>ignore</checksumPolicy>

</releases>

<url>file://${project.basedir}/lib</url>

</repository>

99
2. Use the following command to install the dependency to this repository:

mvn install:install-file -DgroupId=org.apache.tomcat -


DartifactId=apache-tomcat -Dversion=8.0.14 -
Dpackaging=tar.gz -
Dfile=C:\Users\raghu\Downloads\apache-tomcat-
8.0.14.tar.gz -DgeneratePom=true -
DlocalRepositoryPath=lib

What have we achieved? Now, the dependency is packaged along with the source
code in the lib folder of our project and available for distribution. This is
transparent to the user as they do not need to do anything special to access it.

2.6 Best Practices

Maven is a great tool, but it has a steep learning curve. Therefore, have Maven:
The Complete Reference in your bookmarks and refer to it frequently.

Know Maven's command-line options

To learn about Maven's command-line options, run mvn -?. Useful options
include:

-B - runs Maven in batch mode, which is particularly useful when invoking Maven
from a continuous server, such as Bamboo because it avoids Maven's reporting of
downloading progress

-e - configures Maven to report detailed information about errors, which is


particularly useful to debug problems that occur when Maven is invoked from a
continuous server such as Atlassian Bamboo

100
1. Know the standard Maven plugins

To learn about a specific Maven plugin, browse the plugin's Maven site and
read the details on each of the plugin's goals.

2. Prefer a one-to-one relationship between artifacts and Maven projects

For example, if your code base creates three JAR files, have three Maven
projects. If all three JAR files share common code, use a fourth Maven project
to store the common code. Have the original three projects defined a
dependency on the common code.

3. Name your project

Even though the <name data-preserve-html-node="true" data-preserve-html-


node="true"> element is optional in a pom.xml, use it! Forge services (such as
Sonar) use a project's name. In IDEs it is hard to distinguish between two
unnamed projects.

4. Put all generated artifacts in the target folder

The target folder is automatically deleted when you run mvn clean. Therefore,
it's the best place to put all build artifacts, such as Java .class files, JAR files, and
temporary files created during the build process. Maven plugins typically place
the temporary artifacts they create somewhere within the target folder.

Use a dependencyManagement section in a parent pom.xml to avoid


duplicating dependency information in child projects

Maven's dependencyManagement section allows a parent pom.xml to define


dependencies that are potentially reused in child projects. This avoids

101
duplication; without the dependencyManagement section, each child project
has to define its own dependency and duplicate the version, scope, and type of
the dependency. For example, suppose a multi-module Java project makes
extensive use of JUnit for unit testing. To specify the project dependency on
JUnit, the project's parent pom.xml can use a dependencyManagementsection
as follows:

5. Dependency management in parent pom.xml

<dependencyManagement>

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.8.1</version>

<scope>test</scope>

</dependency>

</dependencies>

</dependencyManagement>

Note that each child project that uses JUnit must still specify its dependency on
JUnit. However, the version and scope of the dependency should be omitted as
this avoids duplication and ensures that the same dependency is used
throughout the project.

102
6. Dependency in child pom.xml (Version and scope inherited from parent)

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

</dependency>

</dependencies>

Use SNAPSHOT versions during development

SNAPSHOT versions take some getting used to, but they provide significant
benefits:

They reduce the usage of Forge resources. For example, they reduce the
amount of disk space used by Nexus.

They reduce the frequency of changes that dependent projects make. For
example, when project A depends on project B and both projects are under
development, project A can declare a dependency on the SNAPSHOT version of
project B. That way, project A doesn't need to change its dependency every
time there is a new build of project B.

Use the Maven Dependency Plugin's analyze goals to help identify issues in
your project's dependency management

The Maven Dependency Plugin has an analyze goal that identifies two types of
dependency issues in a project:

103
Dependencies that are directly used, but are not declared. (The project still
compiles because it gets the dependencies transitively.)

Dependencies that are declared but are unused.

You can configure a project's build to fail if it has any dependency warnings -
refer to the Maven documentation.

7. Used undeclared dependencies

Suppose the following:

Project A uses classes from projects B and C.

Project A only declares a Maven dependency on project B.

Project B uses classes from project C.

Project B declares a Maven dependency on project C.

This situation is a lurking problem because project A is relying on project B for


its dependency on project C. Project A will compile until project B removes its
definition of its dependency on project C. This problem is made even worse
when the dependency is on a SNAPSHOT version.

When project A is analyzed using mvn dependency:analyze, Maven produces


the similar output:

[WARNING] Used undeclared dependencies found:

[WARNING]
com.avaya.ace.aaft:foundation_services_client_api:jar:6.2.0
-SNAPSHOT:compile

104
To fix the problem, project A should define a direct Maven dependency on
project C.

8. Unused declared dependencies

If a project declares a dependency and then does not use that


dependency, mvn dependency:analyze produces the similar output:

[WARNING] Unused declared dependencies found:

[WARNING] com.gigaspaces:gs-openspaces:jar:7.1.1-
b4534:compile

To fix the problem, the project should remove the dependency from its POM.

Unused dependencies, sometimes occur because developers are unaware of


Maven's dependency management mechanism.

9. Use Maven for dependency management rather than writing custom code for it

For example, if one Maven project depends on a zip file created by another
Maven project, have the second project create a Maven artifact and use a
Maven dependency rather than using a relative path.

10. Use Maven for dependency management rather than using Subversion
externals

For example, if one Maven project depends on resources stored in another


project's repository, have the second project create a Maven artifact. Use a
Maven dependency to allow the first project to access the artifact.

105
11. Do not write custom Maven code to copy or unzip files. Use Maven's standard
plugins instead.

12. Don’t use deprecated references like ${artifactId} or ${pom.artifactId}. Use the
new ${project.artifactId} syntax. Note that this syntax follows the XML
document structure, which makes it easy to remember and predict the value
that the reference will result in.

13. Try to avoid using inherited properties. Developers can easily forget that a
certain property is used by a child POM and change the value breaking the
build in an unexpected place. Secondly, it’s quite annoying not to be able to
easily lookup a property without having to find and examine the parent POM.

14. Use the dependency management section of the parent pom to define all
dependency versions, but do not set a scope here so that all dependencies
have scope compile by default.

15. Use properties to define the dependency versions. This way you can get an
overview of all versions being used without having to scroll through multiple
pages of dependency sections.

16. Use the plugin management section of the parent pom to define versions for
*all* plugins that your build uses, even standard maven plugins like maven-
compile-plugin and maven-source-plugin. This way your build will not
suddenly behave differently when a new version of a plugin is released.

17. When using a parent POM that is not located in the directory directly above
the current POM define an empty relativePath element in your parent section.

106
18. Use the dependency plugin to check your project for both unnecessary
dependencies and undeclared-but-used-none-the-less dependencies. The goal
is called ‘analyze’, so run the following command on the console: “mvn
dependency:analyze”

19. Make sure the pom files contain all the repository references needed to
download all dependencies. If you want to use a local repository instead of
downloading directly from the Internet then use the maven settings file to
define mirrors for the individual repositories that are defined in the poms.

20. If you use Nexus, then do not create repository groups containing both hosted
and proxied repositories. This will dramatically reduce the responsiveness
because Nexus will check the remote locations of the proxied repositories
even if a hosted repository contains the requested artifact.

You might also like