Maven Build Customization

5 (1 reviews total)
By Lorenzo Anardu , Roberto Baldi , Umberto Antonio Cicero and 2 more
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies

About this book

Maven is one of the most popular tools used to control the dependencies and to administer a Java project. Maven can be used by newbies without the need to learn complex mechanisms, but it is also a powerful tool for big projects developed by different teams and organized over different modules and repositories.

This book will provide you with all the information you need, right from managing dependencies to improving the build process of your organization. Starting with a simple project, you will create your development environment step-by-step, automatically build your code from resources (XML, DB), and package your JAR, WAR, and EAR files for different environments. Furthermore, you will learn about the complex hereditary features of Maven.

Finally, this book will benefit you by teaching Maven-Gradle and Maven-Eclipse integration using the m2e plugin, managing the Maven repository from Gradle, and building a working Maven environment from Gradle.

Publication date:
October 2014
Publisher
Packt
Pages
270
ISBN
9781783987221

 

Chapter 1. Maven and Its Philosophy

If we ask software developers what Maven is, the majority will probably respond that Maven is a build tool. We can't say they are wrong, but this definition is not complete. If we want to be more precise, we should say that Maven is a project management tool that provides build and distribution functionalities, code generation, and communication features. Above all, Maven provides an advanced dependency management system that is able to retrieve transitive dependencies and download them from both local and remote repositories.

Maven is built with a plugin-based architecture; the core architecture provides a set of features that can be extended through a set of official or custom plugins downloadable from repositories.

Maven comes with the convention over configuration philosophy. The origin of this philosophy resides in the idea that accepting conventions resulting from a set of past experiences leads to advantages such as saving time, reuse, and maintenance simplification. Maven pursues this philosophy through the use of defaults, which means that unnecessary configurations should be avoided; a project should just work.

While the use of defaults is a powerful concept, users might want to customize some behavior. Maven meets the users' needs by allowing the customization of almost all defaults.

In this chapter, we will:

  • Introduce Maven and explain its basic concepts

  • Present the example project used to show the concepts that we will treat

  • Start structuring the project, deepening some of the concepts introduced

 

Core concepts of Maven


In this paragraph, we will explore some of Maven's core concepts through a simple example. Maven defines project configurations through a Project Object Model (POM), which is stored in a file named pom.xml.

The following example of pom.xml defines a simple project. Such a simple POM file is capable of compiling and building the project without the need to specify any additional information:

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

    <!-- Project coordinates -->
    <groupId>com.mycompany.projects</groupId>
    <artifactId>my-first-maven-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>My First Maven Project!</name>
</project>

Reading the example POM file, the following concepts emerge:

  • Inheritance: This concept simply means that everything that is not specified in a POM file is inherited from the upper-level POM. At the top level, Maven provides a parent POM defining all default values, which were mentioned earlier. According to this principle, multimodular projects are often structured with a root POM file defining common settings and a pom.xml file related to each submodule to manage each module's peculiarities.

  • Overriding: This concept derives from the preceding one. All the values defined in the lower levels of the POM hierarchy override the definitions in the upper layers. As we can see in the preceding example POM file, only the project's coordinates have been defined, any other value is inherited from the parent POM. A project is uniquely identified into Maven repositories by its coordinates, which is composed of groupId, artifactId, and version. Project coordinates are fundamental since they allow Maven to correctly manage modules and plugins.

  • Modularity: When we install Maven, we formally install only its core functionalities. Whenever we need some extra features, we can find it in some plugin. Plugins as well as software dependencies are downloaded from a set of configurable repositories.

  • Repository: Maven downloads a project's dependencies and plugins through repositories. Maven only distinguishes between two types of repositories: local and remote. The local repository is a folder inside the machine in which a project is being developed, acting as a cache with respect to the remote repositories. For what concerns remote repositories, Apache provides a central repository containing thousands of common dependencies, which is the default one. Maven does not rely on this specific repository, thus allowing users to define their own custom repositories.

 

Introduction to the transportation project


We briefly explored some of Maven's core concepts. Before we start diving into details, we will introduce the project that will guide us across this book: transportation project.

This project aims to develop an application to track vehicles moving around the world and provides an integrated GUI for visualization and statistic calculations.

The example project that we will describe in this book is a complex multimodule J2EE application. Its functional architecture is shown in the following figure:

As we can see in the preceding figure, the project is composed of several modules that interact with each other and store their data in a shared database. All the modules composing the project follow a common naming convention. The first part of the name indicates the project. The second part is a descriptive name indicating the main functionality of the module. The final part indicates the packaging of each module. All the parts composing the name are separated by a dash.

The following list describes what these modules are in charge of:

  • transportation-android-apk: This is an Android application in charge of collecting GNSS coordinates and periodically sending them to the backend.

  • transportation-acq-ear: This is an archive module containing all the functionalities of the backend interface.

  • transportation-acq-war: This is a web application module exposing the backend functionalities to an app across the world using the REST technology. This module receives the application requests, validates them, and invokes the transportation-acq-ejb functionalities in order to perform its tasks.

  • transportation-acq-ejb: This is an Enterprise Java Bean containing all the data acquisition APIs. This module is in charge of persisting the collected coordinates into the database.

  • transportation-reporting-ear: This is an archive module containing all the reporting functionalities.

  • transportation-reporting-war: This is a web application containing the reporting GUI.

  • transportation-reporting-ejb: This is an enterprise Java Bean containing all of the business logic related to the statistics visualization.

  • transportation-common-jar: This is a JAR file containing common utility classes.

  • transportation-statistics-batch-jar: This is a scheduled standalone application in charge of statistical computations on the collected coordinates.

In order to explain some advanced Maven features, we assume that the project is developed in an integrated environment. This environment consists of several entities, managing different phases of the software's lifecycle:

  • Source code repository: We assume that the code is available in an SVN repository, even though the kind of repository is not binding.

  • Bug-tracking tool: In order to avoid dependencies from specific products such as MantisBT or Jira, we assume to have a custom database to track bugs.

  • Custom-dependencies repository: This is proprietary software stored in the repository.

  • Integrated-build and versioning environment: This environment relies on Maven features to perform most of its work. Since, in this case, we must target a specific tool, we will assume to work with Hudson.

In the following figure, we can see the overall picture of the development and build environment:

Life cycle of the software

In spite of the fact that Maven is agnostic with respect to operating systems and IDE, in the course of this book, we assume to develop the software using Eclipse IDE with the M2E-Maven Integration for Eclipse plugin, m2e.

Tip

You can download Eclipse from https://www.eclipse.org/downloads/.

You can find all details about m2e at https://www.eclipse.org/m2e/.

Creating the project

Now that we have a clear view of the project's structure and context, we can start getting our hands dirty.

In Maven, a multimodule project simply consists of a folder containing all submodule projects and a central POM file referencing these modules. This file is usually referred to as parent POM or aggregate POM. In this book, we will comply with this naming.

To start working, we simply need to open our IDE and create the project. Through the m2e plugin, Eclipse provides a wizard specific for Maven project creation.

The project creation starts as any other project. Open the new project window by navigating to File | New | Project….

When the window opens, select the Maven Project option from the Maven folder. As we can see in the following screenshot, the last two steps consist of creating a simple project and filling in the form with the project's coordinates and packaging:

We finally have our Maven project. Our pom.xml file will look a bit desolate, but it will soon grow up. In the following sections, we will start structuring this POM 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/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.packt.examples</groupId>
  <artifactId>transportation-project</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
  <name>transportation-project</name>
  <description>The Transportation Project</description>
</project>

Tip

A project packaging pom does not produce any software package; it simply defines a POM file referencing a set of specified modules, and provides the common settings such as repositories, dependencies, and plugins.

This is the case of an aggregate POM, but it is possible to create POM projects with only specific settings; such projects might be used as a dependencies of other projects or modules that inherit the specified settings.

Structuring the project

Actually, we created an empty project. In order to start structuring our project, we will start adding the project modules that we saw in the earlier sections. The easiest way to add a module is to exploit the m2e functionalities. Just right-click on the pom.xml file and navigate to Maven | New Maven Module Project from the context menu. After this, we can fill in the modules, as shown in the following screenshot:

New Maven module creation

Now, our project will have the first module. We can iterate the same operation for the remaining modules, taking care to choose the right packaging for each module.

Tip

Remember that EJBs don't have proper packaging. They are often included in JAR packages.

Once we stop adding modules, we will see that m2e created all the submodules. Each module that is stored as a folder into the project has its own pom.xml file, which will specify its specific coordinates and settings. In order to distinguish between the POM file of the project and the POM files of its modules, we will call the aggregate POM that we created earlier. The following screenshot shows the added modules and submodules:

As we might notice, this multimodular project follows the standard that we discussed in the Core concepts section.

While terminating the structuration of our project, we take the chance to deepen two more concepts, plugins and dependencies.

As we mentioned earlier, Maven's core functionalities do not cover all needs; most of them are implemented in external plugins. We can add plugins to our project by right-clicking on our pom.xml file and navigating to Maven | Add Plugin from the context menu, as shown in the following screenshot. We can see that the Version field is not mandatory; if we don't specify its value, Maven will download the latest version.

In the following example, we add the maven-surefire-plugin to transportation project. This plugin is used during the test phase to execute the unit tests of the applications. It supports different unit-test frameworks such as JUnit and TestNG.

Since we want to use JUnit, we can simply add JUnit as a dependency of our project. We can add a new dependency the same way as we added a plugin before.

Of course, it is possible to add more plugins and dependencies by manually editing the POM file of each project. In order to add the Maven compiler plugin in our parent POM, we simply add the following tags as a child of the <plugins> tag:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <source>1.7</source>
    <target>1.7</target>
  </configuration >
</plugin>

After we add all the modules and plugins described earlier, our pom.xml file will look like this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.packt.examples</groupId>
  <artifactId>transportation-project</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
  <name>transportation-project</name>
  <description>The Transportation Project</description>

  <modules>
    <module>transportation-acq-ear</module>
    <module>transportation-acq-war</module>
    <module>transportation-acq-ejb</module>
    <module>transportation-reporting-ear</module>
    <module>transportation-reporting-war</module>
    <module>transportation-reporting-ejb</module>
    <module>transportation-common-jar</module>
    <module>transportation-statistics-batch-jar</module>
  </modules>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.17</version>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.5.1</version>
        <configuration>
          <source>1.7</source>
          <target>1.7</target>
        </configuration >
      </plugin>
    </plugins>
  </build>
</project>

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

We have finally structured our project. Actually, it contains all of its modules, a single plugin, and one dependency.

Before exploring the concepts we introduced in this chapter in more detail, it is important to focus on the best practice described in the following snippet. This practice concerns dependency management and will allow us to avoid some common problems related to this topic.

Tip

The aggregate POM should be the only one defining the dependency version. The modules composing the project should use the dependencies in an anonymous way (that is, without specifying their versions).

Archive modules such as EARs should be the only way to physically contain the libraries; all the submodules should consider their dependencies as provided.

 

Summary


In this chapter, we explored Maven's core concepts and described the structure of the sample project that we will follow across this book.

We also discussed the concepts of dependency and plugins in detail, and explained how to practically manage them.

In the following chapter, we will dive into our project and discuss the advanced use and customization of Maven plugins in detail.

About the Authors

  • Lorenzo Anardu

    Lorenzo Anardu graduated in Computer Science from the University of Pisa with a thesis in Parallel Computing. He was born in Sardinia and currently lives in Tuscany where, since 2011, he started working at Autostrade Tech SPA. His main fields of interest are J2EE technology and Android development. He is an expert in optimization and high-performance computing. He has been working with Maven for 5 years, applying it in small and big projects for building and integration purposes. He loves to run.

    Browse publications by this author
  • Roberto Baldi

    Roberto Baldi graduated in Information Technology from the University of Florence. He is a senior Java developer with 10 years of experience developing backend and frontend applications. He also has experience as a software analyst, Android developer, and Linux system administrator. He has been working at Softec SPA since 2011. He is interested in programming languages, operating systems, and developer tools. He lives in Pistoia (Italy) with his wife, Chiara, and his son, Alessandro.

    Browse publications by this author
  • Umberto Antonio Cicero

    Umberto Antonio Cicero is a computer engineer; he received his degree from the University of Calabria. He was born, raised, and educated in Calabria (Italy) and currently lives in Tuscany. He works as a software developer, specialist in web environments and mobile applications. He has been involved in a large number of projects based on Java and Maven. In 2012, he started collaborating with Engineering SPA and started developing apps for Android. He loves Arduino and rock music.

    Browse publications by this author
  • Riccardo Giomi

    Riccardo Giomi is a senior analyst and developer at Autostrade Tech SPA. He received the Laurea degree in Electronic Engineering in 1996 at the University of Florence. He usually works on large Java EE projects, all managed with Maven. He loves Java programming, mathematics, and playing the piano. He lives in Florence with his girlfriend Barbara.

    Browse publications by this author
  • Giacomo Veneri

    Giacomo Veneri graduated in computer science from the University of Siena. He holds a PhD in neuroscience context with various scientific publications. He is Predix Cloud certified and an influencer, as well as SCRUM and Oracle Java certified. He has 18 years' experience as an IT architect and team leader. He has been an expert on IoT in the fields of oil and gas and transportation since 2013. He lives in Tuscany, where he loves cycling.

    Browse publications by this author

Latest Reviews

(1 reviews total)
Excellent
Book Title
Access this book, plus 7,500 other titles for FREE
Access now