How Maven Uses pom.xml for Dependencies and Builds
This article provides a comprehensive overview of how Apache Maven
utilizes the pom.xml (Project Object Model) file as the
central configuration hub for Java applications. It explores the
mechanisms Maven uses to declare and resolve project dependencies,
handle transitive libraries, and orchestrate automated build lifecycles
from source code compilation to final artifact deployment.
The Role of the pom.xml File
The pom.xml file is the fundamental unit of work in
Apache Maven. It is an XML file located in the root directory of a
project that contains essential information about the project, including
its configuration details, default values, and build settings.
At the minimum, every pom.xml defines the project’s
unique coordinates, known as the “GAV” coordinates: *
groupId: Identifies the organization or group creating
the project (e.g., com.example). *
artifactId: Identifies the unique name of the project
or module (e.g., user-service). * version:
Specifies the current version of the artifact (e.g.,
1.0.0-SNAPSHOT).
Dependency Management in Maven
Maven uses the pom.xml file to automate the discovery,
download, and classpath configuration of external libraries.
Declaring Dependencies
Dependencies are defined inside the <dependencies>
block. Each library is specified using its GAV coordinates:
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
<scope>compile</scope>
</dependency>
</dependencies>Dependency Resolution and Transitivity
When Maven reads the pom.xml, it queries configured
repositories (such as Maven Central or internal repositories) to locate
and download the required JAR files to a local cache (usually
~/.m2/repository).
Maven automatically handles transitive dependencies.
If Library A depends on Library B, adding Library A to the
pom.xml causes Maven to automatically fetch Library B as
well. In the event of version conflicts within the dependency tree,
Maven uses a “nearest definition” dependency mediation algorithm to
determine which version to include.
Dependency Scopes
The <scope> tag defines when a dependency is added
to the classpath: * compile: Available on all
classpaths; default scope. * provided: Required for
compilation but provided by the runtime environment (e.g., Servlet API).
* runtime: Required for execution but not compilation
(e.g., JDBC driver implementations). * test: Only
available during test compilation and execution (e.g., JUnit,
Mockito).
Build Lifecycle Management
Maven organizes the build process into predefined build
lifecycles. Instead of requiring developers to write explicit
tasks for compiling or packaging, Maven uses convention over
configuration defined within the pom.xml.
Standard Lifecycles
Maven includes three built-in lifecycles: 1. default: Handles project building and deployment. 2. clean: Handles project directory cleanup. 3. site: Generates project documentation and reports.
Lifecycle Phases
Each lifecycle consists of an ordered sequence of phases. In the
default lifecycle, executing a later phase automatically
triggers all preceding phases: * validate: Checks if
the project is correct and all necessary information is available. *
compile: Compiles the source code of the project. *
test: Tests the compiled source code using a unit
testing framework. * package: Packages the compiled
code into its distributable format (e.g., JAR, WAR) specified by the
<packaging> tag in pom.xml. *
verify: Runs checks on the package to ensure quality
criteria are met. * install: Installs the package into
the local repository for use as a dependency in other local projects. *
deploy: Copies the final package to a remote repository
for sharing with other developers.
Binding Plugins to the Lifecycle
The pom.xml uses the <build> section
to configure plugins that execute specific tasks (plugin goals) during
lifecycle phases:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>Maven maps standard plugins to standard phases by default. For
example, the compile phase automatically runs the
compile goal of the maven-compiler-plugin, and
the test phase runs the test goal of the
maven-surefire-plugin. Through the pom.xml,
developers can alter plugin versions, change target Java versions, or
bind custom plugins to any standard lifecycle phase.