Show List
Maven
Maven is open source tool that is used to build, publish and deploy the applications. It provides simple dependency management. Maven is very helpful downloading and linking dependencies on compilation, as well as on other goals that require them. In addition Maven also brings the dependencies of those dependencies. Maven can handle lifecycle of the project including code generation, compilation, testing, validation and packaging.
Creating Maven Project
In most of the Java IDEs, Maven project can be created by by going to File => New => Project => Maven Project
While creating the Maven project, you can also select an archetype applicable for the requirement.
Below is sample project structure. Maven projects contain pom.xml file which has the list of project dependencies, plugins to be used during the build process.
Sample POM File
Here is a sample POM file and different fields and properties in the file. The explanation of the fields and properties is provided below:
<?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>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<scm>
<connection>scm:svn:http://somerepository.com/svn_repo/trunk</connection>
<developerConnection>scm:svn:https://somerepository.com/svn_repo/trunk</developerConnection>
<url>http://somerepository.com/view.cvs</url>
</scm>
<!-- required so maven release plugin knows where to publish artifact -->
<distributionManagement>
<repository>
<id>devtools-nexus-releases</id>
<url>{some url}</url>
</repository>
<snapshotRepository>
<id>devtools-nexus-snapshots</id>
<url>{some url}</url>
</snapshotRepository>
</distributionManagement>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>7.1</version>
</dependency>
<dependency>
<groupId>org.apache.santuario</groupId>
<artifactId>xmlsec</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>stax2-api</artifactId>
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
<version>6.2.1</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.15</version>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-core</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.neethi</groupId>
<artifactId>neethi</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<type>jar</type>
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
<repositories>
<repository>
<id>all</id>
<url>{some.url}</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>all</id>
<url>{some.url}</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<!-- local-build generates coverage report, without needing to check Sonar. -->
<id>local-build</id>
<build>
<finalName>carbon-emission</finalName>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${maven-jacoco-plugin.version}</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>
</plugins>
</build>
</profile>
</profiles>
</project>
- xmlns specifies namespace for a document. It is used to avoid namespace conflict between different xml documents in an application.
- parent : Maven refers to to parent POM from the provided repository and then creates effective POM by merging the information from the parent and child. relativePath indicates to maven to first search the given path before searching local and then remote repositories.
- groupId.artifactId.version act like an address for the project. groupId and version will be inherited from parent if not defined explicitely.
- groupId is a unique identifier for an organization or a project
- artifactId is the name of the project
- version is used to separate the versions from one another
- packaging identifies the what package is to be generated as a result of build. When no packaging is declared, default is taken as jar
- properties are value place holders. Their values can be used with notation ${}. For example in the code snippet above ${java.version} can be used in the file to access the value.
- scm plugin is primarily used commit the changes to remote repository or to update the local working copy with the one from the remote repository. Maven command to invoke commit goal: mvn -Dmessage="<commit_message>" scm:checkin. Maven command to invoke update goal: mvn scm:update
- distributionManagement specifies where it will deploy the artifacts at the time of deployment. It will come into picture only while mvn deploy i.e deployment time not during mvn install i.e build time.
- dependencyManagement is used to consolidate and centralize the management of dependency versions without adding dependencies which are inherited by all children. This is useful when there are many projects that inherit a common parent. Artifacts specified in the <dependencies> section will always be included as a dependency of the child module. Artifacts specified in the <dependencyManagement> section, will only be included in the child module if they were also specified in the <dependencies> section of the child module itself. You specify the version and/or scope in the parent, and you can leave them out when specifying the dependencies in the child POM.
- repository element under repositories element specifies from where dependencies needs to be picked up. It will come into picture only while mvn install not during mvn deploy.
- pluginRepositories is similar to repositories but is used for plugins.
- dependencies are used to identify the jars that are need for the application.
- groupId.artifactId.version act as address of the dependency.
- type: represents extension of dependency file name. Default value is jar
- scope identifies for which tasks the dependency will be available and how to limit the transitivity of the dependency.
- compile: This is the default if not provided. These dependencies are available in all tasks and are propagated to the dependent projects.
- provided: Means these dependencies are provided by JDK or container at run time. So these are available only for compilation and test tasks. These are not transitive.
- runtime: Means these dependencies are not required for compilation but for running the application. These will be available for run and test tasks.
- test: Only available for test compilation and run. These are not transitive.
- system: You have to provide the jar. The dependency is not looked up in the repository.
- optional: Makes the dependency as optional when the project itself is optional.
- plugins: Maven provides project processing capabilities, build process management and plugins that are used to execute the build tasks. Plugins are used to create jar files, war files, compile code, unit test code, create project documentation etc.
- profiles: Provides alternative set of configuration that sets or overrides default values. Every profile as an id. Profile specific maven command can be executed with -P flag. (Example: mvn -Plocal-build install)
Maven Lifecycle, Phases and Goals
Every maven build follows a life cycle. There are three life cycles:
- default: Main lifecycle, as it's responsible for project build and deployment (e.g. mvn compile, mvn test, mvn install)
- clean: To clean the project and remove all files generated by the previous build (mvn clean)
- site: To create the project's documentation (mvn site)
Each life cycle contains a sequence phases. Default lifecycle contains 23 phases, clean life cycle contains 3 phases, site life cycle contains 4 phases.
Key phases under default life cycle:
- validate: check if all information necessary for the build is available
- compile: compile the code
- test-compile: compile the test source code
- test: execute unit tests
- package: package compiled source code into jar, war etc.
- install: install the package to the local repository
- deploy: copy the package to the remote repository
Phases are executed in sequence. So if we call mvn install, it will also execute previous phases by default. Some phases can be skipped if required. e.g. mvn clean install -Dmaven.test.skip=true would skip compiling the tests.
Each phase can contain one or more plugin goals. When we run a phase, all the goals bound to that phase are executed. Plugin goals can also be executed using the command mvn [plugin-name]:[goal-name]. For example mvn compiler:compile. This command will also execute the previous goals in the sequence by default.
Leave a Comment