POM.xml Structure

Understanding Maven's Project Object Model

← Back to Index

What is POM.xml?

POM (Project Object Model) is Maven's configuration file that describes:

Every Maven project has exactly one pom.xml file in the project root directory.

Complete POM Structure

<?xml version="1.0" encoding="UTF-8"?>
<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">

    <!-- POM version (always 4.0.0) -->
    <modelVersion>4.0.0</modelVersion>

    <!-- ==================== PROJECT COORDINATES ==================== -->
    <groupId>com.example</groupId>
    <artifactId>my-application</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <!-- ==================== PROJECT INFO ==================== -->
    <name>My Application</name>
    <description>A sample Maven project</description>
    <url>https://github.com/example/my-application</url>
    <inceptionYear>2024</inceptionYear>

    <!-- ==================== PARENT POM ==================== -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
        <relativePath/>
    </parent>

    <!-- ==================== PROPERTIES ==================== -->
    <properties>
        <java.version>21</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <lombok.version>1.18.30</lombok.version>
    </properties>

    <!-- ==================== DEPENDENCIES ==================== -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <!-- ==================== DEPENDENCY MANAGEMENT ==================== -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <!-- ==================== BUILD ==================== -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <!-- ==================== PROFILES ==================== -->
    <profiles>
        <profile>
            <id>prod</id>
            <properties>
                <env>production</env>
            </properties>
        </profile>
    </profiles>

</project>

Project Coordinates (GAV)

<!-- The unique identifier for your project -->
<groupId>com.example</groupId>       <!-- Organization (reverse domain) -->
<artifactId>my-app</artifactId>     <!-- Project/module name -->
<version>1.0.0-SNAPSHOT</version>  <!-- Version -->

<!-- Version conventions: -->
<!-- 1.0.0-SNAPSHOT  = Development version (can change) -->
<!-- 1.0.0           = Release version (immutable) -->
<!-- 1.0.0-RC1       = Release candidate -->
<!-- 1.0.0-M1        = Milestone release -->

<!-- Packaging types: -->
<packaging>jar</packaging>   <!-- Default: Java library/app -->
<packaging>war</packaging>   <!-- Web application -->
<packaging>pom</packaging>   <!-- Parent/BOM (no code) -->
<packaging>ear</packaging>   <!-- Enterprise archive -->

Properties

<properties>
    <!-- Java version -->
    <java.version>21</java.version>
    <maven.compiler.source>${java.version}</maven.compiler.source>
    <maven.compiler.target>${java.version}</maven.compiler.target>

    <!-- Encoding -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

    <!-- Dependency versions (single place to manage) -->
    <spring.version>6.1.0</spring.version>
    <junit.version>5.10.0</junit.version>
    <lombok.version>1.18.30</lombok.version>
</properties>

<!-- Using properties: -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>${junit.version}</version>  <!-- References property -->
</dependency>

<!-- Built-in properties: -->
<!-- ${project.basedir}     - Project root directory -->
<!-- ${project.version}     - Project version -->
<!-- ${project.artifactId}  - Artifact ID -->
<!-- ${env.JAVA_HOME}       - Environment variable -->

Parent POM

<!-- Inherit configuration from a parent POM -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.0</version>
    <relativePath/>  <!-- Empty = look in repository, not filesystem -->
</parent>

<!-- What parent provides: -->
<!-- - Managed dependency versions -->
<!-- - Plugin configurations -->
<!-- - Default properties -->
<!-- - Resource filtering -->

<!-- You can then omit versions: -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!-- No version needed - inherited from parent! -->
</dependency>

Build Section

<build>
    <!-- Final artifact name -->
    <finalName>my-app</finalName>

    <!-- Source directories (usually not needed - conventions) -->
    <sourceDirectory>src/main/java</sourceDirectory>
    <testSourceDirectory>src/test/java</testSourceDirectory>

    <!-- Resources (non-Java files to include) -->
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>  <!-- Replace ${} placeholders -->
        </resource>
    </resources>

    <!-- Plugins -->
    <plugins>
        <!-- Compiler plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.11.0</version>
            <configuration>
                <source>21</source>
                <target>21</target>
            </configuration>
        </plugin>

        <!-- Surefire plugin (runs tests) -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.1.2</version>
        </plugin>

        <!-- JAR plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.3.0</version>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>com.example.Main</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

Profiles

<profiles>
    <!-- Development profile -->
    <profile>
        <id>dev</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <spring.profiles.active>dev</spring.profiles.active>
        </properties>
    </profile>

    <!-- Production profile -->
    <profile>
        <id>prod</id>
        <properties>
            <spring.profiles.active>prod</spring.profiles.active>
        </properties>
        <dependencies>
            <dependency>
                <groupId>com.example</groupId>
                <artifactId>prod-logging</artifactId>
            </dependency>
        </dependencies>
    </profile>
</profiles>

<!-- Activate profile: mvn package -Pprod -->

Multi-Module Projects

<!-- Parent pom.xml -->
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>parent-project</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>  <!-- Must be 'pom' for parent -->

    <modules>
        <module>core</module>
        <module>api</module>
        <module>web</module>
    </modules>

    <dependencyManagement>
        <dependencies>
            <!-- Manage versions for all modules -->
        </dependencies>
    </dependencyManagement>
</project>

<!-- Child module pom.xml (e.g., core/pom.xml) -->
<project>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>parent-project</artifactId>
        <version>1.0.0</version>
    </parent>

    <artifactId>core</artifactId>
    <!-- groupId and version inherited from parent -->
</project>

Summary

  • GAV: groupId:artifactId:version uniquely identifies artifacts
  • Properties: Variables for versions and settings
  • Parent: Inherit configuration from another POM
  • Dependencies: Libraries your project needs
  • DependencyManagement: Manage versions without adding dependencies
  • Build: Plugins and build configuration
  • Profiles: Environment-specific configuration
  • Modules: Multi-module project structure