Master Maven pom.xml: Essential Configurations for Java Projects
This guide explains how to configure a Maven pom.xml file, covering project coordinates, dependency scopes, dependencyManagement, exclusions, conflict resolution, lifecycle phases, goals, common plugins, profile activation, repository settings, distribution management, and modular project structure for reliable Java builds.
1. Project Basic Information
Maven uses the pom.xml file to declare the coordinates of a project: groupId (organization, usually a reverse‑domain name), artifactId (project name without spaces), version (semantic version, e.g., 1.0.0 or 1.0.0‑SNAPSHOT), and packaging (default jar, also war, ear, pom, etc.). These four elements uniquely identify a Maven artifact. groupId: e.g.,
com.google.guava artifactId: e.g.,
learning-maven-day1 version: e.g., 1.0.0 or
1.0.0‑SNAPSHOT packaging: default jar, other options war, ear, pom,
maven‑plugin2. Dependency Configuration
Dependencies are listed under the dependencies element. Each <dependency> must specify groupId, artifactId, and version. The scope attribute controls where the dependency is used: compile (default): available at compile, test, and runtime; transitive. test: only for test compilation and execution; not packaged. provided: supplied by the runtime environment (e.g., servlet API); not packaged. runtime: needed at runtime but not for compilation (e.g., JDBC driver). system: taken from a local path via systemPath; not recommended.
To manage versions centrally, use dependencyManagement in a parent POM:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.20</version>
</dependency>
</dependencies>
</dependencyManagement>Child modules can then declare the dependency without a version.
Exclusions remove transitive dependencies you do not want:
<dependency>
<groupId>com.xyz</groupId>
<artifactId>common</artifactId>
<exclusions>
<exclusion>
<groupId>com.xyz</groupId>
<artifactId>components</artifactId>
</exclusion>
</exclusions>
</dependency>When multiple versions of the same transitive dependency appear, Maven selects the shortest dependency path; if paths are equal, the first declaration wins.
3. Build Configuration
Maven’s build lifecycle consists of three built‑in lifecycles ( default, clean, site) each containing ordered phases. The most common default phases are: validate: check project completeness. compile: compile source code. test: run unit tests (without packaging). package: create a distributable artifact (e.g., JAR). verify: run integration tests. install: install the artifact into the local repository. deploy: upload the artifact to a remote repository.
Each phase is bound to a plugin goal. For example, the clean phase runs org.apache.maven.plugins:maven‑clean‑plugin:2.5:clean, and the compile phase runs
org.apache.maven.plugins:maven‑compiler‑plugin:3.1:compile.
Goals are the actual methods inside a plugin. You can invoke a goal directly, e.g. mvn clean:clean, or let Maven run all goals up to a chosen phase, e.g. mvn clean install.
Custom plugin configuration is placed inside the build element. Example: skip unit‑test compilation.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven‑compiler‑plugin</artifactId>
<executions>
<execution>
<id>default‑testCompile</id>
<phase>test‑compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>Common plugins: maven‑compiler‑plugin: control Java compilation (JDK version, exclusions, test‑compile). maven‑surefire‑plugin: run unit tests. maven‑resources‑plugin: copy resources to the output directory. maven‑jar‑plugin: create a standard JAR. maven‑shade‑plugin: build a fat (executable) JAR. maven‑assembly‑plugin: custom packaging structures. spring‑boot‑maven‑plugin: add Spring Boot support.
4. Profiles
Profiles enable environment‑specific configuration (e.g., dev, test, prod). A profile contains an id, optional activation rules, and sections such as repositories and properties.
Manual activation:
System property: mvn clean install -Denv=prod Profile list: mvn clean install -Pdev,prod Automatic activation examples:
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile> <profile>
<id>dev</id>
<activation>
<name>env</name>
<value>production</value>
</activation>
</profile> <profile>
<id>dev</id>
<activation>
<file>
<exists>src/main/resources/config.prod</exists>
</file>
</activation>
</profile>Profiles can also be activated by default via the activeProfile element in the POM.
5. Repository Configuration
When an artifact is not found in the local repository, Maven downloads it from remote repositories declared in repositories. Example for snapshot and release repositories:
<repositories>
<repository>
<id>snapshot</id>
<url>https://repo.example.com/xyz‑public‑snapshot</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
<repository>
<id>release</id>
<url>https://repo.example.com/xyz‑public‑release</url>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</releases>
</repository>
</repositories>Release versions are immutable; snapshots can be overwritten and are always refreshed when snapshots.enabled is true.
6. Distribution Management
To publish built artifacts, configure distributionManagement with separate repositories for releases and snapshots:
<distributionManagement>
<repository>
<id>company‑releases</id>
<url>https://repo.example.com/releases</url>
</repository>
<snapshotRepository>
<id>company‑snapshots</id>
<url>https://repo.example.com/snapshots</url>
</snapshotRepository>
</distributionManagement>Authentication for these repositories must be defined in settings.xml.
7. Modular Projects
Large projects are split into modules with a parent POM that defines common configuration (versions, dependencyManagement, plugins). Child modules inherit these settings but can override them.
Version can be centralized using a property in the parent:
<properties>
<learning.maven.version>1.0.0</learning.maven.version>
</properties>Child modules then reference the property:
<version>${learning.maven.version}</version>Avoid defining the same property in a child module, as it would override the parent value. Use dependencyManagement in the parent to manage versions of shared dependencies, allowing children to omit the version element.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
