Skip to main content

Apache Maven for Spring Boot Development

Table of Contents​

  1. Maven Overview
  2. Project Structure
  3. POM.xml Deep Dive
  4. Essential Maven Commands
  5. Spring Boot Maven Integration
  6. Dependency Management
  7. Maven Profiles
  8. Build Lifecycle
  9. Common Plugins
  10. Best Practices

Maven Overview​

Apache Maven is a build automation and project management tool primarily used for Java projects. It uses a declarative approach based on the Project Object Model (POM).

Key Concepts​

  • POM (Project Object Model): XML file containing project information and configuration
  • Coordinates: Unique identifier for artifacts (groupId, artifactId, version)
  • Repository: Storage location for project artifacts
  • Dependency: External JAR files required by your project
  • Plugin: Tools that perform specific tasks during the build process

Maven Coordinates​

<groupId>com.company.app</groupId>
<artifactId>my-spring-app</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>

Project Structure​

Maven follows a standard directory layout:

my-spring-app/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/company/app/
│ │ │ ├── MySpringAppApplication.java
│ │ │ ├── controller/
│ │ │ ├── service/
│ │ │ ├── repository/
│ │ │ └── model/
│ │ └── resources/
│ │ ├── application.properties
│ │ ├── application.yml
│ │ ├── static/
│ │ └── templates/
│ └── test/
│ ├── java/
│ │ └── com/company/app/
│ └── resources/
├── target/
└── .mvn/

Key Directories​

  • src/main/java: Main application source code
  • src/main/resources: Configuration files, static resources
  • src/test/java: Test source code
  • target/: Compiled classes and built artifacts
  • .mvn/: Maven wrapper configuration

POM.xml Deep Dive​

The pom.xml is the heart of any Maven project. Here's a comprehensive Spring Boot 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 POM for Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath/>
</parent>

<!-- Project Coordinates -->
<groupId>com.company.app</groupId>
<artifactId>my-spring-app</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>

<!-- Project Information -->
<name>My Spring Application</name>
<description>Demo project for Spring Boot</description>

<!-- Properties -->
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<spring-cloud.version>2023.0.0</spring-cloud.version>
</properties>

<!-- Dependencies -->
<dependencies>
<!-- Spring Boot Starters -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- Database -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>

<!-- Development Tools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

<!-- Testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<!-- Dependency Management -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<!-- Build Configuration -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

<!-- Profiles -->
<profiles>
<profile>
<id>dev</id>
<properties>
<spring.profiles.active>dev</spring.profiles.active>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<spring.profiles.active>prod</spring.profiles.active>
</properties>
</profile>
</profiles>
</project>

Essential Maven Commands​

Basic Commands​

# Clean the project (remove target directory)
mvn clean

# Compile the project
mvn compile

# Run tests
mvn test

# Package the project (create JAR/WAR)
mvn package

# Install artifact to local repository
mvn install

# Deploy artifact to remote repository
mvn deploy

# Clean and package
mvn clean package

# Skip tests during packaging
mvn package -DskipTests

# Run specific test class
mvn test -Dtest=MyTestClass

# Run specific test method
mvn test -Dtest=MyTestClass#testMethod

Spring Boot Specific Commands​

# Run Spring Boot application
mvn spring-boot:run

# Run with specific profile
mvn spring-boot:run -Dspring-boot.run.profiles=dev

# Run with JVM arguments
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Xmx512m"

# Build executable JAR
mvn clean package spring-boot:repackage

# Generate build info
mvn spring-boot:build-info

Dependency Commands​

# Display dependency tree
mvn dependency:tree

# Analyze dependencies
mvn dependency:analyze

# Download sources
mvn dependency:sources

# Copy dependencies
mvn dependency:copy-dependencies

# Purge local repository
mvn dependency:purge-local-repository

Information Commands​

# Display effective POM
mvn help:effective-pom

# Display effective settings
mvn help:effective-settings

# List active profiles
mvn help:active-profiles

# Describe plugin goals
mvn help:describe -Dplugin=spring-boot

Spring Boot Maven Integration​

Spring Boot Parent POM​

The Spring Boot parent POM provides:

  • Default configurations for plugins
  • Dependency version management
  • Sensible resource filtering
  • Plugin configuration

Spring Boot Maven Plugin​

Key features:

  • Executable JARs: Creates fat JARs with embedded server
  • Run Goal: Run application directly from Maven
  • Repackage Goal: Repackage existing JAR/WAR as executable
  • Build Info: Generate build information
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.company.app.Application</mainClass>
<layout>JAR</layout>
<excludeDevtools>false</excludeDevtools>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>

Dependency Management​

Scopes​

  • compile: Default scope, available in all phases
  • provided: Available during compilation, not packaged
  • runtime: Not needed for compilation, required for execution
  • test: Only available during test compilation and execution
  • system: Similar to provided, but JAR is explicitly provided
  • import: Only used in dependencyManagement for importing POMs
<dependencies>
<!-- Compile scope (default) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Runtime scope -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>

<!-- Test scope -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<!-- Optional dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

Version Management​

<properties>
<mysql.version>8.0.33</mysql.version>
<jackson.version>2.15.2</jackson.version>
</properties>

<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>

Maven Profiles​

Profiles allow you to customize builds for different environments:

<profiles>
<!-- Development Profile -->
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<spring.profiles.active>dev</spring.profiles.active>
<database.url>jdbc:h2:mem:devdb</database.url>
</properties>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</profile>

<!-- Production Profile -->
<profile>
<id>prod</id>
<properties>
<spring.profiles.active>prod</spring.profiles.active>
<database.url>jdbc:mysql://localhost:3306/proddb</database.url>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludeDevtools>true</excludeDevtools>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

Activating Profiles​

# Activate specific profile
mvn clean package -Pprod

# Activate multiple profiles
mvn clean package -Ptest,integration

# List active profiles
mvn help:active-profiles -Pprod

Build Lifecycle​

Maven has three built-in build lifecycles:

Default Lifecycle (Main Phases)​

  1. validate: Validate project structure
  2. compile: Compile source code
  3. test: Run unit tests
  4. package: Create JAR/WAR
  5. verify: Run integration tests
  6. install: Install to local repository
  7. deploy: Deploy to remote repository

Clean Lifecycle​

  • pre-clean: Execute processes before cleaning
  • clean: Remove all files generated by the build
  • post-clean: Execute processes after cleaning

Site Lifecycle​

  • pre-site: Execute processes before site generation
  • site: Generate project site documentation
  • post-site: Execute processes after site generation
  • site-deploy: Deploy generated site to web server

Common Plugins​

Spring Boot Maven Plugin​

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>

Maven Compiler Plugin​

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>

Maven Surefire Plugin (Unit Tests)​

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<includes>
<include>**/*Test.java</include>
<include>**/*Tests.java</include>
</includes>
</configuration>
</plugin>

Maven Failsafe Plugin (Integration Tests)​

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<includes>
<include>**/*IT.java</include>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>

JaCoCo Plugin (Code Coverage)​

<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.8</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>

Best Practices​

1. Project Structure​

  • Follow Maven's standard directory layout
  • Keep source code organized in logical packages
  • Separate test code from main code

2. Dependency Management​

  • Use Spring Boot's dependency management
  • Avoid version conflicts by using BOMs
  • Regularly update dependencies for security patches
  • Use appropriate scopes for dependencies
<!-- Good: Using managed version -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Avoid: Hardcoding versions when parent manages them -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.2.0</version>
</dependency>

3. Properties Management​

  • Use properties for version management
  • Keep environment-specific configurations in profiles
  • Use meaningful property names

4. Build Configuration​

  • Configure plugins explicitly with versions
  • Use profiles for environment-specific builds
  • Keep build configuration minimal and focused

5. Testing​

  • Separate unit tests from integration tests
  • Use appropriate test scopes
  • Configure test plugins properly

6. Security​

  • Regularly scan for vulnerabilities
  • Use HTTPS for repository connections
  • Avoid storing credentials in POM files

Common Issues and Solutions​

1. Version Conflicts​

# Check for conflicts
mvn dependency:tree -Dverbose

# Exclude transitive dependencies
<dependency>
<groupId>some.group</groupId>
<artifactId>some-artifact</artifactId>
<exclusions>
<exclusion>
<groupId>conflicting.group</groupId>
<artifactId>conflicting-artifact</artifactId>
</exclusion>
</exclusions>
</dependency>

2. Memory Issues​

# Set Maven memory options
export MAVEN_OPTS="-Xmx2048m -XX:MaxPermSize=256m"

3. Encoding Issues​

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

This guide covers the essential Maven concepts and practices for Spring Boot development. Remember to keep your Maven knowledge updated as new versions introduce new features and improvements.