Site icon Automation Dojos

Introduction to Apache Maven

Table of Contents

1. What is Maven

When you write a software application, there are many steps in it like adding the necessary JAR files, compiling the source code, running unit tests, creating the output jar/war file, etc.

This is where Maven comes into play, it automates the build process, dependency management, testing, packaging, and much more. It allows executing all these steps via simple pre-defined Maven commands thereby reducing human intervention and making the code less error-prone.

On a high-level Maven caters for following aspects of dev project:

  • Build Tool
  • Dependency Management
  • Artefact Repository System
  • Additional features via Plugins

2. How Maven Works

The central concept in a Maven project is the POM file. In the POM file, developers need to specify how to configure, build and run an application. In addition, Maven provides build life cycles which consist of build phases and goals.  

Developers need to specify the phase or goal that needs to be executed. Maven then uses these instructions specified in the POM file to execute the specified phase or goal.

3. Convention over Configuration

Maven is based on the principle of ‘Convention over Configuration’ that keeps various project aspects and features standardized and systematic across all Maven projects. Thus, you can achieve consistent project aspects with little or even no configuration.

These so-called ‘Conventions’ are based on best practices and backed up by reasonable defaults. An example of such a ‘convention’ in Maven would be the project directory structure. By default, Maven expects to find all main Java source code under “src/main/java” folder of your project and always looks at this path. Of course, you can override such defaults by customizing your configuration in POM file.

4. Maven Coordinates

Maven coordinates are a set of identifiers that can be used to uniquely identify a project, a dependency, or a plugin in a Maven POM.  All Maven project uses the groupId, artifactId, version, and the packaging property to uniquely identify every Maven component.

The full Maven coordinates are often written in the following format:

groupId:artifactId:packaging:version

5. POM File

The POM stands for Project Object Model. It is a declarative style, XML-based configuration file containing all the information required to build a project or even multiple projects.

Hence every project has its own POM file which is generally located in the root of the source code directory. In the case of multiple projects, a pom file is placed in the root of the source code directory and lists the individual projects as modules.

The following are the main elements in the POM file:

Here is an example of a very simple 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.abc.xyz</groupId>
  <artifactId>HibernateApp</artifactId>
  <version>1</version>
  <dependencies>
  	<dependency>
  		<groupId>org.hibernate</groupId>
  		<artifactId>hibernate-core</artifactId>
  		<version>5.3.4.Final</version>
  	</dependency>
  	<dependency>
  		<groupId>mysql</groupId>
  		<artifactId>mysql-connector-java</artifactId>
  		<version>8.0.12</version>
  	</dependency>
  </dependencies>
</project>

The POM file above specifies the group id as com.abc.xyz, artifact id as HibernateApp and version as 1. In the dependencies section, it specifies the dependencies for Hibernate and the MySQL JDBC driver.

5.1. Super POM

All POMs inherit from a parent or default POM whether explicitly defined or not. In cases where no explicit parent POM is defined, it inherits from the default or base pom of Maven.

In relation to POM, Maven has the concept of ‘Super POM’ which is considered as Maven’s default POM or base POM. This ‘Super POM’ defines all default settings, which are automatically inherited by all Maven projects by ‘Inheritance’. This is one of the strategies by which ‘Convention over Configuration’ manifests in Maven.

Under the inherited Super POM, each individual project implements its own local project POM (also Known as Simplest POM) providing its own unique information specific to that project including any overrides in that project’s POM file thereby achieving a project-specific and customized project POM.

5.2. Effective POM

Maven always executes against an effective pom. This is an amalgamation or combination of settings from this project’s pom.xml, all parent pom (if declared), a super-pom, user-defined settings, and active profiles settings.

This helps developers to specify minimum configuration detail in their Project POM while re-using the inherited default POM. You can see your effective POM by using the following command:

mvn help:effective-pom

6. Maven Directory Structure

Maven defines a standard directory structure and always looks for these directories by default. Although you can certainly override or customize this directory structure via your POM configuration but by default Maven expects developers to follow this directory structure:

  • pom.xml – The pom.xml should be in the root directory of your project
  • src/main/java – Should contain Java source code
  • src/main/resources – Should contain resources like configuration files, etc
  • src/test/java – Should contain source code for unit tests
  • src/test/resources – Should contain resources like configuration files for unit tests
  • target – Maven places the .class files, output artifacts in this directory

7. Maven Build Life Cycle

A build life cycle refers to a set of steps that are executed sequentially as part of a Maven build. Maven has 3 built in build lifecycles as follows:

  • clean
  • default
  • site

Each build lifecycle consists of a number of phases.

Build Phase

A build phase represents a stage in the build life cycle and is responsible for a specific task. The following are some of the phases associated with the default lifecycle:

  • validate
  • compile
  • test
  • package
  • verify
  • install
  • deploy

These phases are executed sequentially. When you specify a phase that you want to be executed as part of a Maven build, Maven executes all the phases up to the specified phase sequentially. So, for example, if you specify that you want to run the install phase, all the phases starting with validate and up to install will get executed sequentially. Each phase consists of one or more plugin goals.

Plugin Goal

A plugin goal represents a specific task that contributes to building a project. For example, the compile goal is responsible for compiling code.  A goal may be associated with zero or more phases. When a phase is executed, it runs all the goals within that phase.

Plugin

A Maven plugin is a container of goals. So, goals exist within plugins. Maven provides some built-in plugins that contain some goals. Developers can also define their own plugins. Plugins are not associated with phases and can be run independently.

8. Dependency Management

In Maven, you just declare the external dependency in the dependencies section of the POM file.  These dependencies could be a library, package, or plugin (mostly in the form of ‘.jars’) that is needed for your project. Then, Maven will automatically download these dependencies and any transitive dependencies along with them. Maven will recursively resolve any required dependencies for your project.

All dependencies are downloaded from Maven repositories defined. But dependencies downloaded from the internet are stored locally as well in a local Maven repository like a local dependency cache. Hence Maven looks at the local repository first, for any dependencies, before going out to the internet for download.

This local Maven repository is a folder called .m2/repository in the home directory. When a Maven build is run, it first checks if the jar files corresponding to the dependencies in the POM file are present in the local repository. If so, it uses them. If not, it downloads the JAR files from the Maven Central repository. 

Maven Central repository is a repository of a large number of JAR files that is maintained by the Maven community. Developers can also configure an alternate repository in the POM file. Downloaded JAR files are placed in the local repository.

(8.1) Transitive Dependencies

A transitive dependency is basically the dependency of your dependency, for example, you could be using a java library or package which could be dependent on another package which in turn could be dependent on another one, and so on. Such indirect dependencies are called ‘Transitive Dependencies’.

One of the best features of Maven is automatically taking care of transitive dependencies which in some cases could prove very painful especially when there is a chain of transitive dependencies for a project.

(8.2) Dependencies and Scope

Finally, dependencies can be bound to a specific scope, which defines when and where the dependencies are needed in your project. For example, the TestNG, JUint jars are needed for Testing, but they are not needed for deployment to an application server. Hence they will be bound to ‘Test’ phase rather then build or other phases.

You can use the following command to print ‘dependencies’ for your project:

mvn dependency:tree

The above command will first of all download Maven plugin called ‘maven-dependency-plugin’ and then print dependencies for your project.

9. Running Maven

In order to run Maven, developers need to specify the Maven command (mvn).  Along with the mvn command, the build phase/goal can also be specified.

First of all, Maven resolves the dependencies specified in the dependencies section. After that, Maven runs the specified goals/phase. If a phase is specified, Maven sequentially executes all the phases before the specified phase.

If developers do not specify a phase or goal along with the mvn command, the value specified under build/defaultGoal will be used. If this value is not specified, an error will occur. Also, the type of output artifact to be produced (specified in the packaging element), determines which goals will be executed as part of a phase.

10. Conclusion

So, to summarise, Maven is a dependency management tool that helps to configure, build and run an application. It uses an XML configuration file known as the POM file. It also follows a certain life cycle that consists of phases and goals. It executes the specified phases and goals as part of the build process.

Exit mobile version