Introduction to Apache Maven

Getting started with 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:

  • Group Id/Artifact Id/Version (GAV) – These elements help to uniquely identify a project
  • Packaging – This specifies the type of the output file like jar, war, etc.
  • Dependencies – This specifies the external dependencies or jar files that an application requires. Maven automatically downloads the jar files specified here from a central repository
  • Build – This specifies information like the goal to run by default if one is not explicitly specified, the directory where to place the output artifact, plugin information, etc.

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.

Tushar Sharma
Tushar Sharmahttps://www.automationdojos.com
Hi! This is Tushar, the author of 'Automation Dojos'. A passionate IT professional with a big appetite for learning, I enjoy technical content creation and curation. Hope you are having a good time! Don't forget to subscribe and stay in touch. Wishing you happy learning!

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Recent Posts

RELATED POSTS

Java Tutorial #6 – Jump Statements

Introduction The break statement is used to stop further execution. It can be used either in a loop or within a switch statement. Break Statement The break...

How To Add SSH Private Keys to Eclipse

One of the common use cases for accessing Git repositories on Github is authentication via SSH keys. This offers a secure way of working...

Remove Duplicates from List Using HashSet

The Set is also an interface in the 'Java Collection' framework. Unlike a List, a Set does not allow duplicates. Hence you can...

Remove Duplicates from List Using For-Loop

The simplest way to remove duplicates from a 'List' is to use a for-loop. The following code snippet demonstrates this method. First, the code creates...

Â

RECENT 'HOW-TO'

How To Install Oh-My-Posh On Windows PowerShell

Oh-My-Posh is a powerful custom prompt engine for any shell that has the ability to adjust the prompt string with a function or variable. It does not...

MORE ON CODEX

MORE IN THIS CATEGORY

Java Tutorial #6 – Jump Statements

Introduction The break statement is used to stop further execution. It can be used either in a loop or within a switch statement. Break Statement The break...

Remove Duplicates from List Using LinkedHashSet

Another implementation of the Set interface is LinkedHashSet. LinkedHashSet maintains the order of elements and helps to overcome the HashSet limitation. The following code...

Format Decimal Numbers Using Format Symbols

You can customize which symbols are used as decimal separator, grouping separator, currency seperator etc. using a DecimalFormatSymbols instance together with java.text.DecimalFormat class. The...

Concatenate Strings Using StringBuffer.append()

In addition to String, Java has the java.lang.StringBuffer and java.lang.StringBuilder classes. These can also be used to concatenate Strings. The advantage of these...

CHECKOUT TUTORIALS

Java Tutorial #3 – Java Arrays

Table of Contents One Dimensional Array Declaring Array Allocting Memory to Array Accessing Array Elements Initializing Array Length of Array Multi Dimensional Array Creating 3...
- Advertisement -spot_img