visit
Although Maven is considered a build tool that can be used to build artifacts from the source code by many, it is actually a project management tool that offers the build tool capabilities as a subset of its capabilities.
As indicated on the official site, //maven.apache.org,
Apache Maven is a Software project management and comprehension tool. Based on the concept of a project object model(POM), Maven can manage a project’s build, reporting, and documentation from a central piece of information.
Having the aforementioned features, Maven can give a simple project setup that uses the best practices, and with Maven, the projects can follow a consistent structure that is independent of the IDEs(Integrated Development Environments).
In addition, one of the most important usages of Maven is that it simplifies the declaration of project dependencies.
It helps you to keep track of your dependencies and their respective versions along with downloading them when they are needed to build the project.
To install Maven, you need to have JDK (Java Development Kit) installed on your machine first. You can simply download the JDK binary file, and extract it or use an installer. After that, you can go to , and click the Download link. You can either click the Download in the side panel or the Download, Install, Run Maven in the content section.
And when you scroll down, you will see the installation instructions and the downloadable files. Here, we can select the apache-maven-3.9.5-bin.tar.gz to download. After downloading the binary zip file, extract it, and set the JAVA_HOME
and MAVEN_HOME
paths in the environment settings.
cd ~/Downloads
tar -xvf apache-maven-3.9.5.bin.tar.gz
/opt/
directory. → sudo mv ~/Downloads/apache-maven-3.9.5 /opt/
~/.zshrc
or ~/.bash_profile
in your Mac (Depending on the terminal you use) → open ~/.zshrc
MAVEN_HOME="/opt/apache-maven-3.9.5"
export PATH="$MAVEN_HOME/bin:$PATH"
Finally, source the ~/.zshrc
or ~/.bash_profile
file. → source ~/.zshrc
mvn -v
mvn -version
curl -s “//get.sdkman.io” | bash
source “$HOME/.sdkman/bin/sdkman-init.sh
After that, open your ~/.zshrc
or ~/.bash_profile
to verify the following is included at the end of the file.
export SDKMAN_DIR="$HOME/.sdkman"
[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh"
After that, type the following to verify whether it is working. → sdk version
sdk list java
to list down all the Java versions that can be used with SDKMAN.
8.0.372-amzn
from Corretto).
sdk install 8.0.372-amzn
to install that version.
11.0.20-amzn
) then type and run sdk install 11.0.20-amzn
8.0.372-amzn
to 11.0.20-amzn
, type sdk use java 11.0.20-amzn
.
8.0.372-amzn
), you can simply type and run sdk uninstall java 8.0.372-amzn
sdk list maven
to list down all the Maven versions that are available.
sdk install <mvn-version>
to install it.
sdk uninstall <mvn-version>
.
java -version
mvn -v
Once you start using Maven, you will notice that Maven has created local, user-specific configuration files and a local repository in the ~/.m2
directory. Inside that ~/.m2
there are,
~/.m2/settings.xml
→ A file containing the user-specific configurations for authentication, repositories, and other information to customize the behavior of Maven.
~/.m2/repository
→ This directory contains the local Maven repository. When you download a dependency from a remote Maven repository, Maven stores a copy of that dependency in your local repository.
Remote Maven repositories have the dependencies uploaded by certain organizations, and the local repository is the ~/.m2/repository
in our local machine.
For instance, if we need, org.apache.spark.spark-sql in our project, we can mention that to Maven, and it will download it from a remote repository like Maven Central() or MVN Repository() and put it inside the ~/.m2/repository
directory.
All the Maven project POM files extend the Super POM, which defines a set of defaults shared by all projects. This file comes as a part of the installation and can be found in,
maven-<version>-uber.jar
file in ${M2_HOME}/lib
for Maven 2.
maven-model-builder-<version>.jar
file in ${M2_HOME}/lib
for Maven 3.
~/.sdkman/candidates/maven/<maven-version>/lib
Since all the Maven POMs inherit the defaults from the Super POM, if you want, you can,
src/main/java
src/test/java
mvn site
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.mavensample.project</groupId>
<artifactId>simplest</artifactId>
<version>1</version>
</project>
Since this is the simplest POM file you can have, it is normally known as the Simplest POM. If you want to create a simple program that belongs to the above criteria, you can type and run mvn package
, and it will produce a JAR file in /target/simples-1.jar
The Simplest POM brings us over to the concept called Effective POM. The Effective POM is made of a combination of super POM and parent POM files. It is notable that the default configurations can be overridden by the parent POM files and the current project’s POM when creating an effective POM.
To find a project’s Effective POM, you’ll need to run the effective-pom
goal in Maven Help plugin using, mvn help:effective-pom
This will print out an XML document showing the merges between the aforementioned POM files. To use the mvn help:effective-pom
, you need to have the Maven Help plugin help goal defined. To install the Maven Help plugin, you can use the below code, and include that in your POM file.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-help-plugin</artifactId>
<version>3.4.0</version> <!-- Use the latest version -->
</plugin>
</plugins>
</build>
<major version>.<minor version>.<incremental version>-qualifier
For example, the version 1.2.3
has a major version of 1, a minor version of 2, and an incremental version of 3. The version `1`
has a major version of 1 and no minor or incremental versions. The qualifier is used to capture the milestone builds like alpha and beta releases (1.2.3-beta-01
)
When using version build numbers like 1.1.2-beta-01
and 1.1.2-beta-10
you should always use left padding (01,02, etc.) to ensure Maven build number issues.
Maven versions also can contain a string literal to signify that a project is currently under active development by adding the string SNAPSHOT
. This string token will be expanded to a UTC(Coordinated Universal Time Value, e.g., 20-1). (e.g., 1.0-SNAPSHOT
→1.0-20-1
)
As a default setting, Maven will not check the SNAPSHOT
versions on remote repositories. To depend on SNAPSHOT
releases, you have to explicitly enable the ability to download them using a repository
or pluginRepository
element in POM.
Also, POM can include references to properties preceded by a dollar sign($
) and surrounded by two curly braces.
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.mavensample.project</groupId>
<artifactId>project-x</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<build>
<finalName>${project.groupId}-${project.artifactId}</finalName>
</build>
</project>
If you put the above in your pom.xml
file and run mvn help:effective-pom
, you will see the output contains the line, <finalName>org.mavensample.project-project-x</finalName>
env
→This exposes the environment variables defined by your operating system or shell. For example, reference to ${env.JAVA_HOME}
would be replaced by the ${JAVA_HOME}
environment variable.
project
→This exposes the POM. You can use the dot-notation path references here.
settings
→This exposes the Maven settings information. You can use dot notation to refer to the values defined in thesettings.xml
file. For example, ${settings.offline}
would reference the value of the offline
element in ~/.m2/settings.xml
.
getProperties()
defined on java.lang.System
.(e.g.,${user.name}
, ${java.home}
)
Arbitrary properties → These can be set with the <properties></properties>
element in the POM file or the settings.xml
or can be loaded from external files.
<properties>
<org.mavensample.project.version>1.0</org.mavensample.project.version>
</properties>
Maven can manage both internal and external dependencies. An external dependency for a Java project might be a library like Spring Framework or Log4j. An internal dependency for a Java project can be a web application depending on another project that contains the service class, model objects, or persistence logic.
When you define a dependency, you are using groupId
, artifactId
, version
, and classifier
to define a unique location of that dependency. This is also done when you are creating a new Maven project. These are called Maven Coordinates and they are integral when defining the dependencies.
compile
→compile
is the default scope; all the dependencies are compile
scoped if a scope is not defined. compile
dependencies are available in all classpaths, and they are packaged.
provided
→ provided
dependencies are used when you expect JDK or a container to provide them. For example, if you are developing a web application, you need the Servlet API available on the compile classpath to compile a servlet, but you don’t need to include the Servlet API in the packaged WAR file. In this case, provided
scope should be used. These dependencies are available on the compilation(not runtime) classpath. They are not transitive, nor they are packaged.
runtime
→ runtime
dependencies are required to execute and test the system, but they are not required for compilation. For example, you may need a JDBC API JAR at compile time and JDBC driver implementation only at runtime.
test
→ These dependencies are not required during the normal operation of an application and they are only needed during the test compilation and execution phases.
system
→ This scope is similar to provided
, but must specify the explicit path to the JAR on the local file system. If you declare the scope system
, you must also provide the systemPath
element. This is not a recommended scope to be used.When you need a dependency to compile a specific project but you don’t need it to be shown up as a transitive runtime dependency for the project that uses your specific project, you can use optional dependencies. You can use the <optional>true</optional>
for that.
(,)
→ exclusive quantifiers (e.g., <version>(1.0,3.0)</version>
).[,]
→ inclusive quantifiers (e.g., <version>[1.0,3.0]</version>
).<version>(1.0,3.0]</version>
).A transitive dependency is a dependency of a dependency. If project-a
depends on project-b
, which depends on project-c
, then project-c
is a transitive dependency of project-a
. If project-a
depends on project-d
, then it is also considered a transitive dependency of project-a
.
mvn dependency:tree
<dependency>
<groupId>org.mavensample.project</groupId>
<artifactId>project-x</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>org.mavensample.project</groupId>
<artifactId>project-y</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.2</version>
</dependency>
...
<dependencies>
</dependencyManagement>
clean
→ Running mvn clean
invokes this and the Clean plugin’s clean goal (clean:clean
) is bound to this.
default/build
→This is the general model of a build process for a software application. It contains several important phases like generate-resources
,test
,compile
,install
,deploy
site
→ This can be used to generate a site from the Maven project by running mvn site
.<profile>
<id>jdk16</id>
<activation>
<activeByDefault>false</activeByDefault>
<jdk>1.6</jdk>
<property>
<name>!environment.type</name>
</property>
</activation>
<modules>
<module>simple-script</module>
</modules>
</profile>
As you can notice activeByDefault
sets the default profile to be activated, and <property></property>
makes sure that the profile is activated when the environment.type
value is not present.
mvn help:active-profiles
<profiles>
<profile>
<id>development</id>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>environment.type</name>
<value>dev</value>
</property>
</activation>
<properties>
<database.driverClassName>com.mysql.jdbc.Driver</database.driverClassName>
<database.url>jdbc:mysql://localhost:3306/app_dev</database.url>
<database.user>dev_user</database.user>
<database.password>deve_password</database.password>
</properties>
</profile>
<profile>
<id>production</id>
<activation>
<property>
<name>environment.type</name>
<value>prod</value>
</property>
</activation>
<properties>
<database.driverClassName>com.mysql.jdbc.Driver</database.driverClassName>
<database.url>jdbc:mysql://master01:3306,slave01:3306/app_prod</database.url>
<database.user>prod_user</database.user>
</properties>
</profile>
</profiles>
In such cases, you can activate the dev
profile by running mvn clean install -Denvironemtn.type=dev
mvn -v
mvn --version
mvn -h
mvn --help
To build a Maven artifact → mvn clean install
mvn clean install -Dmaven.test.skip=true
mvn clean install -DskipTests
To run Maven with a profile (e.g., production
profile) → mvn clean install -Pproduction
Profile activation with variables → mvn clean install -Denvironment.type=dev
Listing the active profiles → mvn help:active-profiles
mvn clean install -X
mvn clean install --debug
To view the effective POM → mvn help:effective-pom
To view the dependency tree → mvn dependency:tree
mvn -e clean install
mvn --errors clean install
mvn -q clean install
mvn --quiet clean install
Run Maven in offline mode → mvn -o clean install
mvn --projects <project_name_1>,<project_name_2> --also-make install
mvn -pl <project_name_1>,<project_name_2> -am install
mvn --projects <project_name_1>,<project_name_2> --also-make-dependents install
mvn -pl <project_name_1>,<project_name_2> --amd install
mvn --resumt-from <project_name> install
mvn -rf <project_name> install
mvn help:describe -Dplugin=help -Dfull
mvn help:describe -Dplugin=org.apache.maven.plugins:maven-compiler-plugin
Describe the plugin with goals → mvn help:describe -Dcmd=compiler:compiler
More information on the available configuration parameters → mvn help:describe -Dcmd=compiler:compile -Ddetail
So, this is it! Check out my previous on Medium if you want to know how to use Maven with Windows! (This is the original article, this article was based upon. 🙃) If you want to know all about Maven, check out Maven: The Complete Reference by SonaType. Most of the concepts I have described here are mentioned thoroughly in this book.
I have not mentioned about plugins
in this article, since it is a heavy topic. But if you are interested in learning about Maven Plugins, check out the below link.