Maven: Unveiling the Power of Build Automation

What is Maven

Maven is a tool to build source code and produce an artifact/output from an application.

Dependency management is the foremost reason for using Maven.

Why is it needed

  1. Repeatable builds - Recreate our build for any environment

  2. Transitive dependencies - Downloading dependencies will also pull all the other items it needs

Works with local repository - historically we had to download the same jar which could be used in multiple projects. What happens if i have 25 projects and the same jar is required ? Maven helps to reduce the disk-space and overhead involved

Maven Vs Ant

MavenAnt
Black box - don't see where everything is definedClear and straight forward - can see the steps
A build toolA scripting tool
Steeper learning curveQuicker to learn
Convention over ConfigurationIssues occur if we forget to change a variable or something inherited

A simple maven Structure

If you head over to start.spring.io and then create a project with just the web dependency then you would get a pom.xml file like the below

groupId - Package Name (business/application name)

artifactId - Name of our application

version - Release

packaging - Distribution (war/jar/ear etc. )

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<groupId>com.learning</groupId>
<artifactId>spring-security</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
</project>

Project Structure using Maven

  • By default, Maven looks for src/main/java directory in any project.

It compiles all our code into a target directory and gets the required information from the pom.xml file.

Maven Goals

  1. clean - deletes the target directory and any of its generated source code

  2. compile - compile all the source code, generate source code based on the dependencies present in the project (Lombok for example)

  3. package - runs the compile goal first, run any unit test inside the pom and bundle into the desired packaging type (jar/war/ear)

  4. install - runs the package command first and then copy it in the local repository. It copies jar/war file or however its packaged & placed inside of your local repository. The default local repository -> home_directory/.m2

  5. deploy - doesn't mean to deploy into an app server. It runs the install command and then deploy into a remote repository.

Maven Dependencies

To add a dependency into our application, we simply need 3 things as seen in the Maven structure section.

  1. groupId

  2. artifactId

  3. version

A note about transitive dependency - If we add a dependency then all the required dependencies would be downloaded along with that one.

Example : - if we're working with spring-boot-starter-test then junit and mockito dependencies come as transitive dependencies (i.e.) there is no need to download them separately.

Tip - Never deploy a release to production if it has SNAPSHOT in it as its not possible to reproduce/recreate the code. It is just for development purpose.

If we do something as type "pom" then all of the dependencies present inside the pom are downloaded into our application and they are referred as "Depedency Pom" or Bill of Materials.

Scopes

  1. compile - default scope & all of my resources are available everywhere inside my application

  2. provided - dependency is not needed at compile time & provided by the runtime environment (say a container)

  3. runtime - needed for execution, libraries like JDBC jars to connect to a database.

  4. test - not included in the final package, junit jars is a good example.

  5. system - hardcode a physical path to a jar which is brittle and better to avoid

  6. import - deals with dependency management (i.e.) sharing resources across multiple pom files.

Dependency Repository

It is where the dependencies are downloaded

Can contain releases/snapshots or both

Goals

Goals are actually just plugins configured in the maven install

Super pom has all the goals defined - clean, compile, test, package, install, deploy

Inherently added to the effective pom (project pom)

Create a multi module project

Right Click on IDE's project Window -> Select Module -> Enter the required details

Module window doesn't come up if we right click on a file

The pom.xml file inside the multi-module project would refer the existing project's parent pom file.

In case of a multi-module project, Maven takes care of which one to build and the required dependencies.

BOM

Can be used to specify the type of BOM

Explicitly define specified versions for your sub-projects or your imported pom's

Can use as an independent file and utilise for dependency management part.

The 2 differences with POM file are

  • packaging type set to BOM

  • dependencyManagement tag is used

    • inherited classes can just use the version specified in the parent pom without specifying the version)

    • For example, if a parent pom has specified the version for hibernate then the child pom file don't need to specify the version and can just inherit from the parent pom which is what we call as "BOM" or bill of materials.

Like Java, Maven also supports Single Inheritance (i.e.) a child can inherit from only one parent. If there is a need to use another dependency from a different parent, then can make use of type & scope inside dependency tag

<type>pom</type>

<scope>import</scope>

Real world example: Also, in most of the spring boot projects we need to have a spring-boot-starter-parent individually but if the starter is available in the parent pom then using BOM, it can be used in all the child pom files instead of downloading.