You have just tried creating a simple project in maven, you will now learn the maven core concepts. As you have seen in the previous page, pom.xml is the heart and soul of a maven project. Pom.xml – project object model file has all the information about a given project.

1. Maven repositories

When you run maven generate, mvn compile or any other command, maven downloads a lot of files from maven central repo. These files are plugins and transitive dependencies that your project needs.

i. Maven central repository

All artifacts in a project get downloaded from maven central repository. Unless you specify a custom repo in ~/.m2/settings.xml.

ii. Custom maven remote repository

Quite often you will need to use libraries that are not hosted in the maven central repository, but hosted in a different repo. You need to specify these remote repositories in the pom.xml. You can also specify them in ~/.m2/settings.xml as well, but this will not be covered here.

<project ....>
...    
    <repositories>
        <repository>
            <id>jcenter-snapshots</id>
            <name>jcenter</name>
            <url>https://jcenter.bintray.com/</url>
        </repository>
    </repositories>
...

iii. Maven local repository (.m2)

Maven downloads dependencies (jar, war, pom files, and plugins) from remote or central repositories and caches them in the local machine. The place where it shows is .m2/repository. I don’t recommend customizing the default location of the local repo.

The exact location of .m2 in your system is
Unix/Mac OS X – ~/.m2/repository
Windows – C:\Users\{your-username}.m2\repository

You can use the command below to find the exact location of .m2.

mvn help:evaluate -Dexpression=settings.localRepository
mvn help:evaluate -Dexpression=settings.localRepository
[INFO] Scanning for projects...
Downloading: https://repo.backbase.com/repo/org/codehaus/mojo/maven-metadata.xml
Downloading: https://repo.backbase.com/repo/org/apache/maven/plugins/maven-metadata.xml
Downloaded: https://repo.backbase.com/repo/org/apache/maven/plugins/maven-metadata.xml (10 KB at 1.7 KB/sec)
Downloaded: https://repo.backbase.com/repo/org/codehaus/mojo/maven-metadata.xml (27 KB at 3.6 KB/sec)
Downloading: https://repo.backbase.com/repo/org/apache/maven/plugins/maven-help-plugin/maven-metadata.xml
Downloaded: https://repo.backbase.com/repo/org/apache/maven/plugins/maven-help-plugin/maven-metadata.xml (679 B at 0.2 KB/sec)
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-help-plugin:3.2.0:evaluate (default-cli) @ standalone-pom ---
[INFO] No artifact parameter specified, using 'org.apache.maven:standalone-pom:pom:1' as project.
[INFO]
/Users/bikramkundu/.m2/repository
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11.416 s
[INFO] Finished at: 2019-07-26T15:56:03+05:30
[INFO] Final Memory: 13M/184M

2. Dependency Management in Maven

Dependency management is a core feature of maven. It is powerful enough to manage dependencies from a simple single project to a complex multi-module project. There are basically 2 types of dependencies that maven manages, direct and transitive dependencies.

What are direct dependencies?

Dependencies that are directly declared in pom.xml are known as direct dependencies. For example, to use undertow, I need to add it’s dependencies in pom.xml.

<dependencies>
    <dependency>
        <groupId>io.undertow</groupId>
        <artifactId>undertow-core</artifactId>
        <version>${undertow.version}</version>
    </dependency>
...

What are transitive dependencies?

Even though you only added undertow-core in the pom.xml, but the undertow-core has dependencies on several other dependencies. Maven resolves dependencies of dependencies, this is known as transitive dependencies.

...
<dependencies>
    <dependency>
        <groupId>io.undertow</groupId>
        <artifactId>undertow-parser-generator</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.logging</groupId>
        <artifactId>jboss-logging</artifactId>
    </dependency>
    <dependency>
        <groupId>org.jboss.logging</groupId>
        <artifactId>jboss-logging-processor</artifactId>
        <scope>provided</scope>
    </dependency>
...

3. Dependency scope in maven

Dependency scope is used to limit the transitivity of a dependency, and also to affect the classpath used for various build tasks. This is an important maven core concept. There are 6 scopes available:

<dependency>
    <groupId>org.jboss.xnio</groupId>
    <artifactId>xnio-api</artifactId>
    <!-- <scope>compile</scope> -->
</dependency>

<dependency>
    <groupId>org.jboss.xnio</groupId>
    <artifactId>xnio-nio</artifactId>
    <scope>runtime</scope>
</dependency>

<dependency>
    <groupId>org.eclipse.jetty.alpn</groupId>
    <artifactId>alpn-api</artifactId>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <scope>test</scope>
</dependency>
  • compile – Default scope, used if none is specified. Compile dependencies are available in all classpaths of a project and propagated to dependent projects.
  • provided – Similar to compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For web-app you use Servlet API and scope to provided because the web container like tomcat will provide it in runtime. This scope is not transitive.
  • runtime – Indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.
  • test – This scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and test execution phases. This scope is not transitive.
  • systemThis scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository. I don’t encourage using this.
  • import – This scope is only supported on a dependency of type pom in the <dependencyManagement> section. It indicates the dependency to be replaced with the effective list of dependencies in the specified POM’s <dependencyManagement> section. import do not actually participate in limiting the transitivity of a dependency.

4. Maven dependency tree

Use mvn dependency:tree command to view the list of all dependencies in your project – transitively. Transitive dependency means that if project-A depends on project-B and project-B depends on project-C, then project-A depends on both B and C.

mvn dependency:tree
[INFO] --- maven-dependency-plugin:3.0.0:tree (default-cli) @ resource ---
[INFO] com.jstobigdata.web.api:resource:jar:b0
[INFO] +- com.jstobigdata.commons:configuration:jar:b0:compile
[INFO] |  +- org.apache.activemq:activemq-client:jar:5.14.5:compile
[INFO] |  |  +- org.apache.geronimo.specs:geronimo-jms_1.1_spec:jar:1.1.1:compile
[INFO] |  |  +- org.fusesource.hawtbuf:hawtbuf:jar:1.11:compile
[INFO] |  |  \- org.apache.geronimo.specs:geronimo-j2ee-management_1.1_spec:jar:1.0.1:compile
[INFO] |  +- org.hibernate:hibernate-core:jar:5.1.0.Final:compile
[INFO] |  |  +- org.jboss.logging:jboss-logging:jar:3.3.1.Final:compile
[INFO] |  |  +- org.hibernate.javax.persistence:hibernate-jpa-2.1-api:jar:1.0.0.Final:compile
[INFO] |  |  +- org.javassist:javassist:jar:3.20.0-GA:compile
[INFO] |  |  +- antlr:antlr:jar:2.7.7:compile
[INFO] |  |  +- org.apache.geronimo.specs:geronimo-jta_1.1_spec:jar:1.1.1:compile
[INFO] |  |  +- org.jboss:jandex:jar:2.0.0.Final:compile
[INFO] |  |  +- com.fasterxml:classmate:jar:1.4.0:compile
[INFO] |  |  +- dom4j:dom4j:jar:1.6.1:compile
[INFO] |  |  |  \- xml-apis:xml-apis:jar:1.4.01:compile
[INFO] |  |  \- org.hibernate.common:hibernate-commons-annotations:jar:5.0.1.Final:compile
[INFO] |  +- com.zaxxer:HikariCP:jar:2.7.4:compile
[INFO] |  +- javax.jms:javax.jms-api:jar:2.0.1:compile
[INFO] |  +- com.jstobigdata.cxp.portal.commons:portal-commons:jar:b0:compile
[INFO] |  +- org.yaml:snakeyaml:jar:1.23:compile
[INFO] |  +- com.jstobigdata.bb:spring-boot-configuration-adapter:jar:0.0.1:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-actuator:jar:2.1.4.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-actuator-autoconfigure:jar:2.1.4.RELEASE:compile
[INFO] |  |  |  \- org.springframework.boot:spring-boot-actuator:jar:2.1.4.RELEASE:compile
[INFO] |  |  \- io.micrometer:micrometer-core:jar:1.1.4:compile

That is how a real-world example may look like, as shown in the above example.

Transitivity brings a serious problem when different versions of the same artifacts are included by different dependencies. It often causes version mismatch issue in runtime, dependency:tree works as a swiss-knife in such case.

5. Maven dependency exclusion

There are several possible reasons why you may like to exclude a specific dependency (artifacts) from the transitive dependencies list. One obvious reason is version mismatch, another one is the choice of artifacts, etc.

I will explain a practical use case. Spring-boot comes with tomcat as the default embedded servlet container, but I want to use jboss-undertow. Therefore, I have to exclude tomcat from the spring-boot dependency list and include undertow related artifacts.

<dependencies>
    <!-- Use Undertow instead of tomcat -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-undertow</artifactId>
    </dependency>

    ....
</dependencies>

You have understood the maven core concepts and dependency management. In the next part of the tutorial, will be focusing on the lifecycle of the maven project, and will understand maven plugins.

By |Last Updated: July 27th, 2019|Categories: Java™, Maven|