Build Tools: Maven & Gradle¶
Build automation tools for Java projects: dependency management, compilation, testing, packaging, and deployment.
Maven¶
Maven is a declarative, XML-based build tool that follows a standard project structure and lifecycle.
Project Structure¶
my-app/
├── pom.xml # Project configuration (Model Object)
├── src/
│ ├── main/
│ │ ├── java/ # Source code
│ │ └── resources/ # Config files, properties
│ └── test/
│ ├── java/ # Test code
│ └── resources/ # Test config
└── target/ # Build output (compiled classes, JARs)
POM (Project Object Model)¶
<?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">
<modelVersion>4.0.0</modelVersion>
<!-- Project identification -->
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>My Application</name>
<!-- Parent POM (inherit properties, plugins, dependencies) -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version>
</parent>
<!-- Properties for reuse -->
<properties>
<java.version>21</java.version>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
<!-- Dependencies -->
<dependencies>
<!-- Compile scope (included in final JAR) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Test scope (only for testing) -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<!-- Runtime scope (not needed at compile time) -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Provided scope (container provides it) -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- Build plugins -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Surefire: Run tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</build>
</project>
Maven Lifecycle & Phases¶
Build Lifecycle: Sequence of phases that Maven executes
Common Phases:
- clean: Delete target directory
- validate: Validate project structure
- compile: Compile source code → target/classes/
- test: Run unit tests (JUnit, TestNG)
- package: Create JAR/WAR → target/my-app-1.0.0.jar
- verify: Run integration tests
- install: Install JAR to local repository (~/.m2/repository/)
- deploy: Upload to remote repository (Nexus, Artifactory)
Commands:
mvn clean # Delete target
mvn compile # Compile only
mvn test # Compile + run tests
mvn package # Compile + test + package JAR
mvn install # Compile + test + package + install locally
mvn deploy # Push to remote repo
mvn clean install # Clean + compile + test + install
mvn clean install -DskipTests # Skip tests (faster for CI/CD)
Dependency Management¶
<!-- Dependency with version override -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2022.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- Exclude transitive dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
Gradle¶
Gradle is a declarative-imperative build tool using Groovy/Kotlin DSL with faster incremental builds.
Project Structure¶
my-app/
├── build.gradle or build.gradle.kts # Build configuration
├── settings.gradle # Multi-module projects
├── gradle.properties # Version definitions
├── src/
│ ├── main/
│ │ ├── java/ # Source code
│ │ └── resources/ # Config
│ └── test/
│ ├── java/ # Tests
│ └── resources/ # Test config
└── build/ # Output
Build Configuration (Groovy DSL)¶
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.0'
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'com.example'
version = '1.0.0'
sourceCompatibility = '21'
// Properties for reuse
ext {
springCloudVersion = '2022.0.1'
}
// Dependency repositories
repositories {
mavenCentral() // Maven Central (public)
maven {
url 'https://repo.example.com/nexus/repository/releases/'
credentials {
username 'user'
password 'pass'
}
}
}
// Dependencies
dependencies {
// Compile scope (default)
implementation 'org.springframework.boot:spring-boot-starter-web'
// Test scope
testImplementation 'org.junit.jupiter:junit-jupiter'
// Runtime only
runtimeOnly 'com.mysql:mysql-connector-java'
// Annotation processor (compile time)
annotationProcessor 'org.projectlombok:lombok'
}
// Dependency management
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
// Tasks
tasks.named('test') {
useJUnitPlatform()
}
// Custom task
task hello {
doLast {
println 'Hello from Gradle!'
}
}
Gradle Build Lifecycle¶
Task Execution: Directed acyclic graph (DAG) of task dependencies
build (default task)
├── compileJava
├── compileTestJava
├── processResources
├── test
└── jar
$ gradle build # Compile + test + package
$ gradle clean # Delete build directory
$ gradle test # Run tests only
$ gradle jar # Create JAR
$ gradle compileJava # Compile only
$ gradle --info build # Verbose output
$ gradle build -x test # Build excluding tests
$ gradle tasks # List all tasks
Gradle vs Maven Commands¶
| Task | Maven | Gradle |
|---|---|---|
| Compile | mvn compile |
gradle compileJava |
| Test | mvn test |
gradle test |
| Package | mvn package |
gradle jar |
| Build | mvn clean install |
gradle build |
| Skip tests | mvn install -DskipTests |
gradle build -x test |
| List dependencies | mvn dependency:tree |
gradle dependencies |
| Update dependencies | mvn versions:display-dependency-updates |
gradle dependencyUpdates |
Maven vs Gradle Comparison¶
| Aspect | Maven | Gradle |
|---|---|---|
| Configuration | XML (declarative) | Groovy/Kotlin DSL (flexible) |
| Learning Curve | Moderate (structured) | Steep (flexible = complex) |
| Build Speed | Slower (no caching) | Faster (incremental builds, caching) |
| Customization | Limited (fixed lifecycle) | Highly customizable (custom tasks) |
| Dependency Management | Transitive (works well) | Transitive (same) |
| Multi-module | Complex XML nesting | Cleaner with settings.gradle |
| IDE Support | Excellent (all IDEs) | Good (IntelliJ, Gradle native) |
| Industry Adoption | ⭐⭐⭐ (ubiquitous) | ⭐⭐ (growing, Android default) |
| When to Use | Standard enterprise projects | Complex builds, Android, performance-critical |
| Spring Boot Projects | Common | Increasingly popular |
Plugins & Extensions¶
Maven Plugins¶
<build>
<plugins>
<!-- Compiler: Set Java version -->
<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: Run tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<!-- Jar: Create executable JAR -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.example.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!-- Assembly: Package with dependencies -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
</plugins>
</build>
Gradle Plugins¶
plugins {
id 'java' // Java compilation
id 'org.springframework.boot' version '3.1.0' // Spring Boot
id 'io.spring.dependency-management' // Dependency management
id 'com.google.protobuf' version '0.9.0' // Protocol Buffers
}
// Apply plugin
apply plugin: 'jacoco' // Code coverage
// Configure plugin
jacoco {
toolVersion = "0.8.8"
}
Dependency Scopes¶
Maven Scopes¶
| Scope | Included in JAR | Used for |
|---|---|---|
compile |
✅ Yes | Source code compilation |
test |
❌ No | Test code only |
runtime |
✅ Yes | Runtime execution (not compile) |
provided |
❌ No | Container provides (servlet-api) |
import |
❌ No | Import another POM's dependencies |
Gradle Configurations¶
| Config | Included in JAR | Used for |
|---|---|---|
implementation |
✅ Yes | Source code (hides from consumers) |
testImplementation |
❌ No | Test code only |
runtimeOnly |
✅ Yes | Runtime (not compile) |
compileOnly |
❌ No | Compile only (container provides) |
annotationProcessor |
❌ No | Annotation processing (@Data, @Builder) |
Practical Examples¶
Maven: Spring Boot Application¶
mvn archetype:generate -DgroupId=com.example -DartifactId=my-app \
-DarchetypeArtifactId=maven-archetype-quickstart
cd my-app
mvn spring-boot:run # Run Spring Boot
mvn clean install # Build and install
mvn deploy # Deploy to Nexus/Artifactory
Gradle: Spring Boot Application¶
gradle init --type java-application --test-framework junit-jupiter
cd my-app
gradle bootRun # Run Spring Boot
gradle build # Build
gradle publish # Publish to repository
Common Issues & Solutions¶
| Issue | Maven | Gradle |
|---|---|---|
| Dependency conflict | Use <exclusion> or <version> in POM |
Use force or constraint in build.gradle |
| Slow builds | Use -o offline flag |
Enable build cache: org.gradle.caching=true |
| Test failures | mvn test -DskipFailingTests |
gradle test --continue |
| Clean build | mvn clean install |
gradle clean build |
| Check updates | mvn versions:display-updates |
gradle dependencyUpdates |
Interview Talking Points¶
- Maven vs Gradle? Maven is declarative (XML), stable, standard; Gradle is flexible (DSL), faster builds, custom tasks
- When to use Maven? Enterprise projects, team requires standardization, simple builds
- When to use Gradle? Performance-critical builds, complex customization, Android development
- Dependency management? Transitive dependencies; Maven has more conservative approach; Gradle allows override
- Build lifecycle? Maven: fixed phases (clean → validate → compile → test → package); Gradle: task DAG (directed acyclic graph)
- Plugin usage? Maven: compiler, surefire, assembly; Gradle: spring-boot, protobuf, custom task definitions
- Incremental builds? Maven: full rebuilds; Gradle: only affected tasks (faster)
- Multi-module projects? Maven: complex XML; Gradle: cleaner with settings.gradle
See also: CI/CD, DevOps Overview