java4 min read

Maven Tutorial: Learn Build Tool from Scratch (2026)

Maven Tutorial: Learn Build Tool from Scratch (2026)

Published:  |  Category: Java  |  Reading time: ~15 min
Maven Tutorial: Learn Build Tool from Scratch (2026)

Maven is the most widely used build tool in the Java ecosystem. Its convention-over-configuration approach, declarative POM files, and dependency management via Maven Central make it the default choice for enterprise Java projects. After maintaining multi-module Maven builds with hundreds of dependencies, I have learned that understanding the build lifecycle and dependency resolution mechanics is essential for avoiding the dreaded "jar hell".

This tutorial covers the POM structure, build lifecycle, dependency management, plugins, profiles, and best practices for multi-module projects.

POM Structure and Coordinates

The Project Object Model (POM) is an XML file describing your project. GroupId, artifactId, and version form the Maven coordinates that uniquely identify your artifact. The packaging element determines the output format — jar, war, pom, or ear. The parent element establishes inheritance from a parent POM for shared configuration.

Maven enforces a standard directory layout: src/main/java for sources, src/main/resources for resources, src/test/java for tests, and target/ for build output. Sticking to this convention lets new developers understand any Maven project immediately.


    4.0.0
    com.example
    order-service
    2.3.1
    jar

Build Lifecycle and Phases

Maven has three built-in lifecycles: default (main build), clean (cleanup), and site (documentation). The default lifecycle phases execute in order: validate, compile, test, package, verify, install, deploy. Plugins bind goals to these phases; for example, the compiler plugin runs during compile and the surefire plugin during test.

Run mvn clean install to clean, compile, test, package, and install the artifact in your local repository. Use mvn verify to run integration tests without installing. Understanding phase ordering helps you diagnose why certain tasks execute — or do not execute.

# Typical commands
mvn clean                    # Delete target/
mvn compile                  # Compile sources
mvn test                     # Run unit tests (surefire)
mvn package -DskipTests      # Create JAR without tests
mvn install                  # Install to local repository
mvn deploy                   # Deploy to remote repository

# Check effective POM
mvn help:effective-pom

Dependency Management

Dependencies are declared in the dependencies section with groupId, artifactId, and version. Maven resolves transitive dependencies automatically and uses a nearest-wins strategy for version conflicts. Use the dependencyManagement section in a parent POM to centralize version declarations for all child modules.

Exclude transitive dependencies that conflict with other libraries. Use provided scope for dependencies available at runtime (Servlet API), test scope for test-only libraries, and optional to prevent transitive propagation. Run mvn dependency:tree to visualize the full dependency graph.


    
        
            com.fasterxml.jackson
            jackson-bom
            2.17.0
            pom
            import
        
    



    
        org.springframework.boot
        spring-boot-starter-web
        
            
                org.springframework.boot
                spring-boot-starter-tomcat
            
        
    

Plugins and Goals

Maven functionality is plugin-based. The compiler plugin compiles Java code, surefire runs unit tests, failsafe runs integration tests, javadoc generates documentation, and shade creates fat JARs. Plugin configurations belong in the build.plugins section with parameters passed via configuration elements.

Complex builds may involve code generation — the jaxb2-maven-plugin generates Java classes from XSD schemas, protobuf-maven-plugin compiles .proto files. These plugins typically bind goals to the generate-sources phase to run before compilation.


    
            org.apache.maven.plugins
            maven-compiler-plugin
            3.13.0
            
                21
                true
            
        
        
            org.apache.maven.plugins
            maven-shade-plugin
            
                
                    package
                    shade
                
            
        
    

Profiles for Environment-Specific Builds

Maven profiles activate different build configurations based on environment, JDK version, or explicit flags. A common pattern: a dev profile with relaxed checks and fast builds, a ci profile with strict linting, and a release profile that signs jars and deploys to Maven Central.

Activate profiles with -PprofileName, by setting the activeProfiles in settings.xml, or by detecting system properties. Profile-specific configuration overrides the base POM values. Keep profiles minimal to avoid an explosion of build paths.


        production
        
            true
            false
        
        
            
                    org.apache.maven.plugins
                    maven-failsafe-plugin
                    
                        **/*IT.java
                    
                
            
        
    


# mvn clean verify -Pproduction

Multi-Module Projects

Multi-module projects let you build related artifacts (api, core, persistence, web) in a single reactor build. The parent POM with packaging pom lists child modules. Modules inherit from the parent and can reference each other as inter-module dependencies, which Maven resolves from the reactor before looking at the local repository.

Use the reactor to enforce build order: Maven sorts modules by dependency graph. Run specific modules with -pl (project list) and resume from a failing module with -rf. The -am flag also-makes dependencies of the listed modules.


com.example
my-app
1.0.0
pom

    my-app-api
    my-app-core
    my-app-web


# Build all modules
mvn clean install

# Build only specific modules and their deps
mvn -pl my-app-web -am clean package

Frequently Asked Questions

How do I fix a version conflict in transitive dependencies?

Use mvn dependency:tree to find the conflict. Add an explicit dependency in your POM with the desired version (nearest-wins). Alternatively, use the tag to exclude the unwanted transitive dependency from its parent.

What is the difference between dependencyManagement and dependencies?

dependencies declares actual dependencies used by the project. dependencyManagement declares versions and scopes that child modules inherit — it does not add the dependency itself. Use dependencyManagement in a parent POM to enforce consistent versions.

How do I skip tests in Maven?

Use -DskipTests to skip unit tests but still compile them. Use -Dmaven.test.skip=true to skip both compilation and execution of tests. The first is useful for quick builds, the second when tests cannot compile.

What is the Maven local repository and where is it?

The local repository is a cache of downloaded artifacts located at ~/.m2/repository. Maven checks it first before downloading from remote repositories. Clear specific artifacts or the entire repository with rm -rf ~/.m2/repository to force fresh downloads.

Originally published on Ayodhyyya. Last updated June 1, 2026.