Maven’s dependency management automatically resolves transitive dependencies and ensures consistent versions across a project.

Declaring Dependencies

  <dependencies>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.10.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>33.0.0-jre</version>
    </dependency>
</dependencies>
  

Dependency Scopes

Scope Compile Test Runtime Example
compile (default) ✓ ✓ ✓ Guava, Spring
test ✓ JUnit, Mockito
runtime ✓ ✓ JDBC driver
provided ✓ ✓ Servlet API (container provides)
system ✓ ✓ Local JAR (avoid)
import BOM import only

Transitive Dependencies

Maven resolves dependencies recursively. If A depends on B, and B depends on C, your project gets C automatically:

  my-app → spring-boot-starter-web → spring-web → spring-core
  

View the tree:

  mvn dependency:tree
mvn dependency:tree -Dincludes=com.google.guava
  

Exclusions

Remove unwanted transitive dependencies:

  <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 Management (BOM)

Centralize version control without adding dependencies:

  <dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>3.2.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<!-- Now declare without version -->
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
  

Version Conflicts

When two dependencies require different versions of the same artifact, Maven uses nearest definition (shortest path in the tree).

Force a specific version:

  <dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>33.0.0-jre</version>
        </dependency>
    </dependencies>
</dependencyManagement>
  

Best Practices

  • Use BOM/dependencyManagement to control versions centrally
  • Prefer test scope for test-only libraries
  • Run mvn dependency:tree to diagnose conflicts
  • Avoid system scope — use a proper repository instead
  • Keep dependencies minimal — remove unused ones regularly