Maven pom.xml for a Java Project

Maven's pom.xml (Project Object Model) is the build configuration, dependency management, and metadata declaration for Java and JVM projects. When you run mvn build, test, or package, Maven reads the pom.xml to determine what to compile, which dependencies to download, which plugins to run, and in what order. Understanding pom.xml structure is essential for any Java developer working with Spring Boot, Quarkus, or other Maven-based frameworks. This example uses Spring Boot's parent POM, which is the key to Maven's power in Spring Boot projects. The parent block pulls in the spring-boot-starter-parent POM as the parent project. This parent POM provides dependency management (pre-configured versions for hundreds of Spring ecosystem libraries), plugin configuration (Maven Compiler, Surefire, Failsafe), resource filtering, and sensible defaults. Because of this inheritance, you can declare spring-boot-starter-web as a dependency without specifying a version — the parent POM's dependencyManagement section provides the correct version that's tested to work with this Spring Boot release. The properties block with java.version = 21 configures the Maven Compiler plugin (inherited from the parent) to compile for Java 21. This ensures your project uses Java 21 features and won't accidentally compile to an older bytecode version. Spring Boot Starter dependencies: spring-boot-starter-web includes the full web stack — an embedded Tomcat server, Spring MVC, Spring Web, Jackson for JSON serialization. A single dependency line replaces dozens of individual dependency declarations. spring-boot-starter-test (with scope=test) includes JUnit 5, Mockito, AssertJ, and Spring's test utilities for testing. The scope element controls when a dependency is available: default (compile scope) means the dependency is on the compile and runtime classpath. test scope means the dependency is only on the test classpath — it's not packaged into the final JAR. runtime scope means available at runtime but not compile time (useful for JDBC drivers). provided scope means the container provides it (used for servlet-api in non-embedded deployments). XML validity matters: Maven is strict about the pom.xml namespace declarations (xmlns, xmlns:xsi, xsi:schemaLocation) and element nesting. A missing closing tag, wrong namespace, or element in the wrong position causes Maven to fail with a confusing parsing error. The XML formatter catches these issues before you run mvn. Real-world project structures: multi-module Maven projects use a parent pom.xml with packaging=pom and a list of module elements pointing to submodule directories, each with their own pom.xml inheriting from the parent. This structure is common in microservices where multiple services share common dependencies and configurations. Tips: use mvn dependency:tree to see your full transitive dependency graph and identify version conflicts. Use mvn versions:display-dependency-updates to see which of your dependencies have newer versions available.

Example
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.4</version>
  </parent>
  <groupId>com.example</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0.0</version>
  <properties>
    <java.version>21</java.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>
[ open in XML Formatter → ]

FAQ

What is the difference between Maven and Gradle?
Maven uses XML configuration and a fixed build lifecycle. Gradle uses Groovy or Kotlin DSL with a flexible task graph. Gradle is generally faster due to incremental builds and build caching; Maven is more predictable for enterprise settings.
What does a BOM import do in Maven?
A Bill of Materials import (scope=import, type=pom) pulls in a set of pre-validated dependency versions from a parent project. Spring Boot's starter-parent includes a BOM that pins compatible library versions so you do not specify versions individually.
How do I add a local JAR as a Maven dependency?
Use system scope with the systemPath pointing to the JAR file. This is a workaround; the recommended approach is to install the JAR into your local Maven repository with mvn install:install-file.

Related Examples