Skip to content

Maven

**Maven** is a *project management tool* that is based on *POM* (*project object model*). It is used for **projects build**, **dependency** and **documentation**.

4 min read

Maven is a project management tool that is based on POM (project object model). It is used for projects build, dependency and documentation.

This blog is built on Windows 10 (x64-based):

  • Maven: 3.8.7
  • JDK 1.8

In C:\Program Files\Java\apache-maven-3.8.7\conf\settings.xml:

  1. to make C:\maven-repo a local Maven Repository, add the following to C:\Program Files\Java\apache-maven-3.8.7\conf\settings.xml:
<localRepository>C:\maven-repo</localRepository>
  1. JDK Version C:\Program Files\Java\apache-maven-3.8.7\conf\settings.xml:
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>

First, check the version of current Java compiler by:

Terminal window
$ java -version

Second, add JDK-related environment variables:

  • set/new JAVA_HOME to C:\Program Files\Java\jdk1.8.0_231
  • append %JAVA_HONE%\bin to %PATH%
  • set/new JAVA_TOOL_OPTIONS to -Dfile.encoding=UTF-8

Third, add Maven-related environment variables:

  • set/new MAVEN_HOME to C:\Program Files\Java\apache-maven-3.8.7
  • set/new M2_HOME to %MAVEN_HOME%
  • append %MAVEN_HOME%\bin to %PATH%
  • set/new MAVEN_OPTS to -Xms256m -Xmx512m -Dfile.encoding=UTF-8

Fourth, open a new termianal and test Maven with command:

Terminal window
$ mvn --version

Maven uses 3 vectors to locate a *.jar package:

  • groupId: company/organization domain name in reverse order
  • artifactId: project name, or module name in a project
  • version: SNAPSHOT or RELEASE

In this section, I will create a quick and simple Maven Java project, which will serve as a template in the late project.

Considering my Blog address is https://mighten.github.io, and this is a learning practice for Maven, so my group id will be io.github.mighten.learn-maven, and artifact id will be maven-java.

Terminal window
$ mkdir C:\maven-workspace\learn-maven
$ cd C:\maven-workspace\learn-maven
$ mvn archetype:generate

Note:

  • Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 7: (Press Enter to confirm default value)
  • Define value for property 'groupId': io.github.mighten.learn-maven
  • Define value for property 'artifactId': maven-java
  • Define value for property 'version' 1.0-SNAPSHOT: : (Press Enter to confirm default value)
  • Define value for property 'package' io.github.mighten.learn-maven: : (Press Enter to confirm default value)
  • Y: : (Press Enter to confirm default value)

And the BUILD SUCCESS is shown.

First, in path learn-maven/maven-jave/src, delete the default Java files:

  • src/main/java/io/github/mighten/learn-maven/App.java
  • src/test/java/io/github/mighten/learn-maven/AppTest.java

Second, modify the version of JUnit (in learn-maven/maven-jave/pom.xml) from 3.8.1 to 4.12

change working directory to the directory of the current pom.xml.

  1. clean
Terminal window
$ mvn clean

delete the target folder

  1. compile the main
Terminal window
$ mvn compile

target file in target/classes

  1. test
Terminal window
$ mvn test-compile
$ mvn test

target file in target/test-classes

  1. pack to *.jar
Terminal window
$ mvn package
  1. install into local Maven Repository
Terminal window
$ mvn install

Trick:

Terminal window
$ mvn clean install

Dependency management is a core feature of Maven.

Scope is used to define the dependencies of a project, e.g., JUnit in pom.xml has <scope>test</scope>:

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

And we should notice:

  • compile (default scope): used for both the compilation and the runtime of the project. But the Compile Scope does not use the classes in Test Scope
  • test: used for testing, but not required for the runtime
  • provided: used for dependencies that are part of the Java EE or other container environments. But the Provided Scope will not be packed into *.jar.
Scope Name/main/testDevelopDeploy
compilevalidvalidvalidvalid
testN/AvalidvalidN/A
providedvalidvalidvalidN/A

These scopes help manage the classpath and control which dependencies are included at different stages of the build process.

In the Maven tree, if the dependency of a child is compile-scope, then it can propagate to the parent; otherwise, if dependency of a child is test-scope or provided-scope, then it can not propagate to the parent.

For example, if I write a project_1.jar, which adds a dependency to JUnit with test scope. Then I create project_2 which uses a dependency to project_1.jar. The JUnit dependency will not be available for project_2 because JUnit is in test scope; if I want to use JUnit in project_2, I have to explicitly declare JUnit in pom.xml of project_2.

In addition, Maven can create an ASCII-styled dependency-tree graph, with the following command:

Terminal window
$ mvn dependency:tree

Dependency Exclusions are used to fix *.jar confrontations.

For example, if I create a project_3 will add dependencies on project_1.jar (uses package A version 1.1) and project_2.jar (uses package A version 1.6), then certainly the package A will have confrontation with two version. To fix this issue, we usually choose the higher version (1.6) and exclude the lower version 1.1. So I will exclude package A in dependency of project_1.jar (in pom.xml of project_3):

<dependency>
<groupId>io.github.mighten.learn_maven</groupId>
<artifactId>project_1</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
<exclusions>
<!--
to exclude package `A`,
(no need to specify version)
-->
<exclusion>
<groupId>A</groupId>
<artifactId>A</artifactId>
</exclusion>
<!--
to exclude other packages
<exclusion>
<groupId></groupId>
<artifactId></artifactId>
</exclusion>
-->
</exclusions>
</dependency>

Dependency Inheritance allows child POM to inherit dependency from a parent POM. It is typically used to prevent version confrontations. In pom.xml of parent project:

  1. set parent project parent to pack into POM file <packaging>pom</packaging>, which will allow the parent to manage all the child projects.

  2. add tag <dependencyManagement> in pom.xml of parent, to manage all the dependencies:

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<!-- other dependencies -->
</dependencies>
</dependencyManagement>

Note: the packages are not really import into the parent project

  1. add tag <parent> to pom.xml of every children:
<parent>
<groupId>com.atguigu.maven</groupId>
<artifactId>pro03-maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
  1. add dependencies into children pom.xml, and since the version is declared in parental pom.xml, the version in the children pom.xml can be omitted.

If we want to aggregate all of the children projects into one, we can config in parent.xml (similar to inheritance):

<modules>
<module>child_1</module>
<module>child_2</module>
<module>child_3</module>
</modules>

Note: DO NOT use cyclic reference.