Maven Tutorial for Java Developers
Introduction to Maven
Maven is a widely-used build automation tool primarily for Java projects. It simplifies and
standardizes the build process by providing a uniform build system, dependency management,
and a central repository for libraries and plugins. Maven’s declarative approach, centered around
the Project Object Model (POM) file, reduces manual configuration and ensures consistency
across projects.
Why Use Maven?
Dependency Management: Automatically downloads and manages libraries from
repositories like Maven Central.
Standardized Build Process: Defines a consistent build lifecycle (e.g., compile, test,
package).
Extensibility: Supports plugins for tasks like testing, packaging, and deployment.
Reproducibility: Ensures builds are consistent across different environments.
Core Concepts
1. POM File (pom.xml):
o The Project Object Model (POM) is an XML file that defines the project’s
configuration, dependencies, and build process.
o Key elements: groupId, artifactId, version, dependencies, plugins.
2. Dependency Management:
o Maven resolves dependencies from repositories (e.g., Maven Central) and
manages transitive dependencies (dependencies of dependencies).
o Scopes (e.g., compile, test, provided) control when dependencies are available.
3. Build Lifecycle:
o Maven defines a standard lifecycle: validate, compile, test, package,
install, deploy.
o Each phase executes specific goals (tasks) defined by plugins.
4. Plugins and Goals:
o Plugins extend Maven’s functionality (e.g., maven-compiler-plugin for
compilation).
o Goals are specific tasks within a plugin (e.g., compile:compile).
5. Repositories:
o Local Repository: Stores downloaded artifacts in ~/.m2/repository.
o Remote Repositories: Maven Central, Nexus, or custom repositories for
downloading dependencies.
Setting Up Maven
1. Install Maven:
o Download Maven from apache.org.
o Set M2_HOME environment variable and add mvn to your PATH.
o Verify installation: mvn -version.
2. Create a Maven Project:
Use the Maven archetype to generate a project:
3. mvn archetype:generate -DgroupId=com.example -DartifactId=maven-demo -
DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
This creates a directory structure:
maven-demo/
├── pom.xml
└── src
├── main
│ └── java
│ └── com/example/App.java
└── test
└── java
└── com/example/AppTest.java
Configuring the POM File
The pom.xml is the heart of a Maven project. Below is a sample configuration for a Java project
with JUnit for testing.
<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>
<groupId>com.example</groupId>
<artifactId>maven-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Maven Demo Project</name>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- JUnit for testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Compiler plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Explanation
groupId: Unique identifier for your organization (e.g., com.example).
artifactId: Name of the project (e.g., maven-demo).
version: Project version (e.g., 1.0-SNAPSHOT for development).
dependencies: Lists libraries like JUnit, with scope=test limiting it to the test phase.
build: Configures plugins like maven-compiler-plugin for Java compilation.
Common Maven Commands
mvn clean: Removes the target directory (compiled output).
mvn compile: Compiles the source code in src/main/java.
mvn test: Runs unit tests in src/test/java.
mvn package: Builds the project and packages it (e.g., JAR file) in the target directory.
mvn install: Installs the artifact to the local repository (~/.m2/repository).
mvn deploy: Deploys the artifact to a remote repository.
Example: Building a Simple Java Application
Let’s create a Java application with a main class and a test case.
Main Class
Create src/main/java/com/example/App.java:
package com.example;
public class App {
public static String greet(String name) {
return "Hello, " + name + "!";
}
public static void main(String[] args) {
System.out.println(greet("Maven User"));
}
}
Test Class
Create src/test/java/com/example/AppTest.java:
package com.example;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class AppTest {
@Test
public void testGreet() {
assertEquals("Hello, Maven User!", App.greet("Maven User"));
}
}
Running the Project
1. Compile and test: mvn test
2. Package the application: mvn package
o This creates target/maven-demo-1.0-SNAPSHOT.jar.
3. Run the JAR: java -cp target/maven-demo-1.0-SNAPSHOT.jar com.example.App
Output:
Hello, Maven User!
Scenario 1: Adding a Dependency (e.g., Apache Commons
Lang)
Suppose you want to use Apache Commons Lang for string utilities.
1. Add the dependency to pom.xml:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
2. Update the main class to use StringUtils:
package com.example;
import org.apache.commons.lang3.StringUtils;
public class App {
public static String greet(String name) {
return "Hello, " + StringUtils.capitalize(name) + "!";
}
public static void main(String[] args) {
System.out.println(greet("maven user"));
}
}
3. Run mvn clean package and execute the JAR:
4. Hello, Maven User!
Maven automatically downloads commons-lang3 and includes it in the build.
Scenario 2: Integrating with a Database (JDBC with
MySQL)
For a Java application interacting with MySQL, add the MySQL Connector/J dependency.
1. Update pom.xml:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
2. Create a class to connect to MySQL
(src/main/java/com/example/DatabaseExample.java):
package com.example;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DatabaseExample {
private static final String URL = "jdbc:mysql://localhost:3306/demo_db?
useSSL=false&serverTimezone=UTC";
private static final String USER = "root";
private static final String PASSWORD = "your_password";
public static void main(String[] args) {
try (Connection conn = DriverManager.getConnection(URL, USER,
PASSWORD);
PreparedStatement pstmt = conn.prepareStatement("SELECT name FROM
users WHERE id = ?")) {
pstmt.setInt(1, 1);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
System.out.println("User: " + rs.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
3. Run mvn package and execute the application, assuming a demo_db database with a
users table exists.
Scenario 3: Using Plugins for Code Quality
Add the maven-checkstyle-plugin to enforce coding standards.
1. Add to pom.xml under <build><plugins>:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<configLocation>google_checks.xml</configLocation>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
2. Run mvn checkstyle:check to verify code against Google’s style guidelines.
Scenario 4: Multi-Module Projects
For large projects, Maven supports multi-module setups. Suppose you have a project with a core
module and a web module.
1. Create a parent pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>core</module>
<module>web</module>
</modules>
</project>
2. Create submodules (core and web) with their own pom.xml files, inheriting from the
parent.
3. Build all modules: mvn clean install.
Best Practices
Use Meaningful Coordinates: Choose clear groupId, artifactId, and version for
easy identification.
Centralize Dependencies: Use <dependencyManagement> in parent POM for multi-
module projects to manage versions.
Leverage Plugins: Use plugins like maven-surefire-plugin for tests or maven-shade-
plugin for executable JARs.
Keep POM Clean: Avoid unnecessary dependencies and configurations.
Use Repositories: Configure remote repositories (e.g., Nexus) for internal artifacts.
Automate with CI/CD: Integrate Maven with Jenkins or GitLab for automated builds
and deployments.
DevOps Integration
Maven is integral to DevOps pipelines for Java developers:
CI/CD: Use Maven in Jenkins or GitLab CI/CD to automate builds and tests.
Artifact Repositories: Deploy artifacts to Nexus or Artifactory for sharing across teams.
Docker: Package Maven artifacts into Docker images using docker-maven-plugin.
Example Jenkins pipeline:
pipeline {
agent any
tools {
maven 'Maven'
}
stages {
stage('Build') {
steps {
sh 'mvn clean package'
}
}
}
}
Conclusion
Maven simplifies Java development by automating builds, managing dependencies, and
providing a standardized project structure. This tutorial covered setting up a Maven project,
configuring the POM file, writing and testing Java code, and applying Maven in real-world
scenarios like database integration and multi-module projects. By mastering Maven, Java
developers can streamline their workflows and integrate effectively with DevOps practices.