Maven 101
This was a internal talk given by Maven Legends - me, Keshav Garg and Diwakar Moturu in Uni Cards.
Special Thanks to Abhra Dasgupta and Abhishek Gupta for helping us out in the preparation for the talk and during the talk as well. :)
Getting Started
Maven, In a nutshell, is an attempt to apply patterns to a project’s build infrastructure in order to promote comprehension and productivity by providing a clear path in the use of best practices. Maven is essentially a project management and comprehension tool and as such provides a way to help with managing:
- Builds
- Documentation
- Reporting
- Dependencies
- SCMs
- Releases
- Distribution
Introduction to POM
A simple pom.xml
for reference
<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>club.uni</groupId>
<artifactId>offer-engine</artifactId>
<version>1.0.0</version>
<name>offer-engine</name>
<properties>
<java.version>11</java.version>
<uni-commons.version>1.0.54</uni-commons.version>
</properties>
<dependencies>
<dependency>
<groupId>club.uni</groupId>
<artifactId>http</artifactId>
<version>${uni-commons.version}</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
...
</pluginManagement>
</build>
</project>
pom.xml
contains the Project Object Model (POM) for this project. The POM is the basic unit of work in Maven. In short, the POM contains every important piece of information about your project and is essentially a one-stop-shopping for finding anything related to your project.
Explanation of Key Elements in the POM
project - This is the top-level element in all Maven pom.xml files.
modelVersion - This element indicates what version of the object model this POM is using. Current Version being used - 4.0.0
.
groupId - This element indicates the unique identifier of the organization or group that created the project. The groupId is one of the key identifiers of a project and is typically based on the fully qualified domain name of your organization. For example club.uni
is the designated groupId for all projects/plugins at Uni.
artifactId - This element indicates the unique base name of the primary artifact being generated by this project. The primary artifact for a project is typically a JAR file. A typical artifact produced by Maven would have the form <artifactId>-<version>.<extension>
like offer-engine-server-1.0.0.jar
version - This element indicates the version of the artifact generated by the project. This is where Maven helps with version management. Best practices will on the versioning be covered in the guide.
name - This element indicates the display name used for the project. This is often used in Maven’s generated documentation.
url - This element indicates where the project’s site can be found.
properties - This element contains value placeholders accessible anywhere within a POM.
dependencyManagement - Dependency Management allows consolidation and centralizes the management of dependency versions without adding dependencies which are inherited by all children. This is especially useful when you have a set of projects (i.e. more than one) that inherits a common parent. This also helps in controlling the version of the artifacts used.
dependencies - This element’s children list dependencies which will be used in the project.
build - This element handles things like declaring your project’s directory structure and managing plugins.
distributionManagement - Responsible for distribution of artifacts. This also specifies how a project will be added to a remote artifactory when it is deployed. The username-password authentication required by the distribution management will be taken from settings.xml present in /Users/{userName}/.m2
Best Practices -
Any platform/service in Uni will have the following items.
- Parent Maven Project
- Supporting Maven Modules
Parent Maven Project
The parent should contain all the common set of dependencies to be used across the child modules. Things which this can include are modules, version properties for dependencies, dependency management for child modules, and distribution management configurations.
Naming Conventions
Group Id - club.uni
Artifact Id - <Your Service Name>
Versioning - x.y.z
No version should have SNAPSHOT at the end. Release versions can be handled with RELEASE tag in the end.
<groupId>club.uni</groupId>
<artifactId>offer-processor</artifactId>
<packaging>pom</packaging>
<version>1.0.0</version>
Keep the common properties that can be used across the modules in the parent pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<java.version>11</java.version>
<spring.boot.version>2.3.5.RELEASE</spring.boot.version>
<jackson.version>2.11.3</jackson.version>
<springfox.version>3.0.0</springfox.version>
<junit-jupiter.version>5.3.2</junit-jupiter.version>
<mockito.version>3.3.3</mockito.version>
<junit.platform.version>1.5.2</junit.platform.version>
<uni-commons.version>1.0.40</uni-commons.version>
<docker.version>1.2.2</docker.version>
<transaction-platform.version>1.0.9</transaction-platform.version>
<javax.validation.version>2.0.1.Final</javax.validation.version>
</properties>
Supporting Maven Modules
Group Id - club.uni
(Same as Parent Project) Artifact Id - <Parent Service Name>
Versioning - <Same as Parent Version>
<parent>
<artifactId>offer-processor</artifactId>
<groupId>club.uni</groupId>
<version>1.0.0</version>
</parent>
<artifactId>offer-processor-model</artifactId>
Third Party Dependency Management
Use Dependency Management to control the dependency versions in the project. Define the versions required in the parent pom.xml properties and define all the dependencies which call be used in the plugin/child pom.xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>${javax.validation.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependencyManagement>
Dependencies in the child pom.xml
will not require any versioning if it’s already defined in the main pom.xml
<dependencies>
<dependency>
<groupId>club.uni</groupId>
<artifactId>helper</artifactId>
</dependency>
</dependencies>
Other Pieces
- Add only the dependencies you need for your project. Use Maven Helper Plugin to identify conflicting dependencies.
- The dependency your project needs would have been sometimes be fulfilled by an existing one itself. This is where the Dependency Analyser provided by Maven Helper plugin helps.
- Add your dependencies with care so that you don’t have to spend your time fixing crashing builds.
- Don’t add any dependency in module pom, only declare them in dependency management of parent pom and then use them in whichever module you require.
log4j-to-slf4j
andlog4j-slf4j-impl
may conflict and your test cases may not run. Exclude one of the packages and refresh the dependencies again.