Maven: Defusing the transitive dependencies BOM

Proper management of dependencies in a maven project can be a tricky thing. Knowing which tools maven offers to handle project dependencies and how maven creates the project dependency tree is crucial. Let’s look at a few examples.

Direct vs Transitive Dependencies

All dependencies defined in the section of a pom.xml file are **direct** dependencies. All dependencies in the project's **dependency tree** that are not in the tree are **transitive** dependencies.

An example.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>dev.buijs.example.starwars</groupId>
    <artifactId>library-sith</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>6.1.7</version>
        </dependency>
    </dependencies>
</project>

This library has one direct dependency org.springframework spring-core version 6.1.7.

Now we’ll use dependency:tree to check the transitive dependencies:

./mvnw dependency:tree

[INFO] --- dependency:3.6.1:tree (default-cli) @ library-sith ---
[INFO] dev.buijs.example.starwars:library-sith:jar:1.0.0
[INFO] \- org.springframework:spring-core:jar:6.1.7:compile
[INFO]    \- org.springframework:spring-jcl:jar:6.1.7:compile

There is one transitive dependency org.springframework spring-jcl version 6.1.7. If we add this transitive dependency to the dependencies section of our pom.xml, then it would no longer be transitive. Let’s verify it.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>dev.buijs.example.starwars</groupId>
    <artifactId>library-sith</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>6.1.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jcl</artifactId>
            <version>6.1.7</version>
        </dependency>
    </dependencies>
</project>

Now we’ll use dependency:tree to check the transitive dependencies again:

./mvnw dependency:tree

[INFO] --- dependency:3.6.1:tree (default-cli) @ library-sith ---
[INFO] dev.buijs.example.starwars:library-sith:jar:1.0.0
[INFO] +- org.springframework:spring-core:jar:6.1.7:compile
[INFO] \- org.springframework:spring-jcl:jar:6.1.7:compile

So now there are no transitive dependencies. While we still have the same set of dependencies, they are now all explicitly added in the dependencies section and thus no longer transitive.

Dependency Mediation

As we determined in our rudiment example, we only directly control the explicitly dependencies being added. Transitive dependencies are added by maven automatically. This is not an as straightforward process as you’d might think…

An example. We’ll add two more maven projects:

  • A second maven project (library-jedi) which depends on a different spring-core version.
  • A third maven project which depends on our first (library-sith) and second (library-jedi) projects.

Our second pom for library-jedi:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>dev.buijs.example.starwars</groupId>
    <artifactId>library-jedi</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.3.35</version>
        </dependency>
    </dependencies>
</project>

Our third pom for project-battle:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>dev.buijs.example.starwars</groupId>
    <artifactId>project-battle</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-jedi</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-sith</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
</project>

Project structure now looks as follows:

  • project battle
    • library-jedi
      • spring-core 5.3.35
        • spring-jcl 5.3.35
    • library-sith
      • spring-core 6.1.7
        • spring-jcl 6.1.7

Project-battle has direct dependencies on both library-sith and library-jedi and transitively depends on spring-core and spring-jcl. As discussed, maven will automatically choose a dependency version for the transitive dependencies. The choice is between spring-core 6.1.7 and spring-core 5.3.35. Let’s check which versions maven selects:

./mvnw dependency:tree

[INFO] dev.buijs.example.starwars:project-battle:jar:1.0.0
[INFO] +- dev.buijs.example.starwars:library-jedi:jar:1.0.0:compile
[INFO] |  \- org.springframework:spring-core:jar:5.3.35:compile
[INFO] |     \- org.springframework:spring-jcl:jar:5.3.35:compile
[INFO] \- dev.buijs.example.starwars:library-sith:jar:1.0.0:compile

Maven has chosen to add spring-core 5.3.35 and spring-jcl 5.3.5. This is due to dependency mediation. As the maven documentation states, maven picks the nearest definition. Maven uses the version of the closest dependency to your project in the tree of dependencies. If two dependency versions are at the same depth in the dependency tree, the first declaration wins. The latter is the case in our example.

Let’s see what happens when we change the order of our dependencies:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>dev.buijs.example.starwars</groupId>
    <artifactId>project-battle</artifactId>
    <version>1.0.0</version>
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <!-- The old order of dependencies -->
        <!--        <dependency>-->
        <!--            <groupId>dev.buijs.example.starwars</groupId>-->
        <!--            <artifactId>library-jedi</artifactId>-->
        <!--            <version>1.0.0</version>-->
        <!--        </dependency>-->
        <!--        <dependency>-->
        <!--            <groupId>dev.buijs.example.starwars</groupId>-->
        <!--            <artifactId>library-sith</artifactId>-->
        <!--            <version>1.0.0</version>-->
        <!--        </dependency>-->
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-sith</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-jedi</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
</project>
./mvnw dependency:tree

[INFO] --- dependency:3.6.1:tree (default-cli) @ project-battle ---
[INFO] dev.buijs.example.starwars:project-battle:jar:1.0.0
[INFO] +- dev.buijs.example.starwars:library-sith:jar:1.0.0:compile
[INFO] |  \- org.springframework:spring-core:jar:6.1.7:compile
[INFO] |     \- org.springframework:spring-jcl:jar:6.1.7:compile
[INFO] \- dev.buijs.example.starwars:library-jedi:jar:1.0.0:compile

Maven has now chosen to depend on spring-core 6.1.7 and spring-jcl 6.1.7, simply because the dependency adding it transitively is now higher up in the dependencies section:

  • project battle
    • library-sith
      • spring-core 6.1.7
        • spring-jcl 6.1.7
    • library-jedi
      • spring-core 5.3.35
        • spring-jcl 5.3.35

But wait… there’s more. Let’s add another maven project.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>dev.buijs.example.starwars</groupId>
    <artifactId>library-force</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jcl</artifactId>
            <version>6.0.9</version>
        </dependency>
    </dependencies>
</project>

We’ll add this as dependency to battle-project maven project.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>dev.buijs.example.starwars</groupId>
    <artifactId>project-battle</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-sith</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-jedi</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-force</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
</project>

Maven now has 3 versions to choose from for the spring-jcl dependency: 6.1.7, 5.3.5 and now also 6.0.9. Let’s check the dependency tree.

./mvnw dependency:tree

[INFO] dev.buijs.example.starwars:project-battle:jar:1.0.0
[INFO] +- dev.buijs.example.starwars:library-sith:jar:1.0.0:compile
[INFO] |  \- org.springframework:spring-core:jar:6.1.7:compile
[INFO] +- dev.buijs.example.starwars:library-jedi:jar:1.0.0:compile
[INFO] \- dev.buijs.example.starwars:library-force:jar:1.0.0:compile
[INFO]    \- org.springframework:spring-jcl:jar:6.0.9:compile

Version 6.0.9 of spring-jcl is chosen because it is nearer than the other versions.

Direct Transitive (1) Transitive (2)
library-sith spring-core spring-jcl
library-jedi spring-core spring-jcl
library-force spring-jcl  

Our project structure:

  • project battle
    • library-sith
      • spring-core 6.1.7
        • spring-jcl 6.1.7
    • library-jedi
      • spring-core 5.3.35
        • spring-jcl 5.3.35
    • library-force
      • spring-jcl 6.0.9

Dependency Management

Dependency versions can also be configured using the dependencyManagement section. A dependency added in the dependencyManagement section will override any transitive version of the same dependency.

An example. Add spring-core version 6.0.9 to the dependencyManagement of project-battle.


<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>dev.buijs.example.starwars</groupId>
    <artifactId>project-battle</artifactId>
    <version>1.0.0</version>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>6.1.4</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-sith</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-jedi</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-force</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
</project>

Now check the dependency tree.

./mvnw dependency:tree

[INFO] dev.buijs.example.starwars:project-battle:jar:1.0.0
[INFO] +- dev.buijs.example.starwars:library-sith:jar:1.0.0:compile
[INFO] |  \- org.springframework:spring-core:jar:6.1.4:compile
[INFO] +- dev.buijs.example.starwars:library-jedi:jar:1.0.0:compile
[INFO] \- dev.buijs.example.starwars:library-force:jar:1.0.0:compile
[INFO]    \- org.springframework:spring-jcl:jar:6.0.9:compile

Version 6.1.4 from dependencyManagement is now used for spring-core, ignoring any transitive version. Our project structure:

  • project battle
    • spring-core 6.1.4
    • library-sith
      • spring-core 6.1.7
        • spring-jcl 6.1.7
    • library-jedi
      • spring-core 5.3.35
        • spring-jcl 5.3.35
    • library-force
      • spring-jcl 6.0.9

Interestingly spring-jcl version 6.0.9 is still being used, even though spring-core 6.1.4 depends on spring-jcl 6.1.4. This is because dependencyManagement does not lock in all transitive dependency versions of the managed dependency. In our case this means spring-core version 6.1.4 is used everywhere, but any transitive dependency of spring-core can still be overridden. This is crucial to remember when working with maven BOM projects.

Bill of Materials

A bill of materials, or BOM for short, is used to keep track of compatible dependency versions in a project.

An example.

We’ll add a new project which will be our BOM. In the dependencyManagement section we’ll add the spring-core version.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>dev.buijs.example.starwars</groupId>
    <artifactId>bom-deathstar</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <name>Bill of Materials</name>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>6.1.4</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

A BOM project needs to be imported to be used. We’ll import it in project-battle.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>dev.buijs.example.starwars</groupId>
    <artifactId>project-battle</artifactId>
    <version>1.0.0</version>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>dev.buijs.example.starwars</groupId>
                <artifactId>bom-deathstar</artifactId>
                <version>1.0.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-sith</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-jedi</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-force</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
</project>

Now check the dependency tree.

./mvnw dependency:tree

[INFO] dev.buijs.example.starwars:project-battle:jar:1.0.0
[INFO] +- dev.buijs.example.starwars:library-sith:jar:1.0.0:compile
[INFO] |  \- org.springframework:spring-core:jar:6.1.4:compile
[INFO] +- dev.buijs.example.starwars:library-jedi:jar:1.0.0:compile
[INFO] \- dev.buijs.example.starwars:library-force:jar:1.0.0:compile
[INFO]    \- org.springframework:spring-jcl:jar:6.0.9:compile

Our project structure:

  • project battle
    • bom-deathstar:
      • spring-core 6.1.4
    • library-sith
      • spring-core 6.1.7
        • spring-jcl 6.1.7
    • library-jedi
      • spring-core 5.3.35
        • spring-jcl 5.3.35
    • library-force
      • spring-jcl 6.0.9

So using a separate BOM project or dependencyManagement directly inside a maven project does not matter for the end result. Using a BOM however it is possible to reuse the same set of dependencies in multiple projects. If you do, remember to make all dependencies explicit in the BOM pom file. Let’s do that in our final example.

Add spring-jcl 6.1.4 to the bom project.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>dev.buijs.example.starwars</groupId>
    <artifactId>bom-deathstar</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <name>Bill of Materials</name>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>6.1.4</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jcl</artifactId>
                <version>6.1.4</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

Now check the dependency tree.

./mvnw dependency:tree

[INFO] dev.buijs.example.starwars:project-battle:jar:1.0.0
[INFO] +- dev.buijs.example.starwars:library-sith:jar:1.0.0:compile
[INFO] |  \- org.springframework:spring-core:jar:6.1.4:compile
[INFO] +- dev.buijs.example.starwars:library-jedi:jar:1.0.0:compile
[INFO] \- dev.buijs.example.starwars:library-force:jar:1.0.0:compile
[INFO]    \- org.springframework:spring-jcl:jar:6.1.4:compile

Maven Explicit Dependencies Plugin

For large projects it can be cumbersome to keep track of all dependencies. Have a look at the maven-explicit-dependencies plugin which can make the process a bit easier. This plugin will output dependency information and (optionally) fail your build if not all dependencies are explicitly add.

Add the plugin.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>dev.buijs.example.starwars</groupId>
<artifactId>project-battle</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
    <dependencies>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-sith</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-jedi</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-force</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>dev.buijs.maven</groupId>
                <artifactId>explicit-dependencies-maven-plugin</artifactId>
                <version>1.0.0</version>
            </plugin>
        </plugins>
    </build>
</project>

Run the plugin compile goal.

[INFO] --- explicit-dependencies:1.0.0:compile (default-cli) @ project-battle ---
[WARNING] missing explicit dependencies: [{
"groupId": "org.springframework",
"artifactId": "spring-core",
"version": "6.1.7"
}, {
"groupId": "org.springframework",
"artifactId": "spring-jcl",
"version": "6.0.9"
}]

Compare with the dependency-tree.

[INFO] --- dependency:3.6.1:tree (default-cli) @ project-battle ---
[INFO] dev.buijs.example.starwars:project-battle:jar:1.0.0
[INFO] +- dev.buijs.example.starwars:library-sith:jar:1.0.0:compile
[INFO] |  \- org.springframework:spring-core:jar:6.1.7:compile
[INFO] +- dev.buijs.example.starwars:library-jedi:jar:1.0.0:compile
[INFO] \- dev.buijs.example.starwars:library-force:jar:1.0.0:compile
[INFO]    \- org.springframework:spring-jcl:jar:6.0.9:compile

The explicit-dependencies plugin recognizes spring-jcl 6.0.9 and spring-core 6.1.7 are used by the project but both are not direct dependencies. Now we’ll add the BOM to fix this.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>dev.buijs.example.starwars</groupId>
<artifactId>project-battle</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>dev.buijs.example.starwars</groupId>
                <artifactId>bom-deathstar</artifactId>
                <version>1.0.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-sith</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-jedi</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>dev.buijs.example.starwars</groupId>
            <artifactId>library-force</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>dev.buijs.maven</groupId>
                <artifactId>explicit-dependencies-maven-plugin</artifactId>
                <version>1.0.0</version>
            </plugin>
        </plugins>
    </build>
</project>

Run the compile goal.

[INFO] --- explicit-dependencies:1.0.0:compile (default-cli) @ project-battle ---
[INFO] dependency-tree is fully explicit

Compare with the dependency-tree.

[INFO] --- dependency:3.6.1:tree (default-cli) @ project-battle ---
[INFO] dev.buijs.example.starwars:project-battle:jar:1.0.0
[INFO] +- dev.buijs.example.starwars:library-sith:jar:1.0.0:compile
[INFO] |  \- org.springframework:spring-core:jar:6.1.4:compile
[INFO] +- dev.buijs.example.starwars:library-jedi:jar:1.0.0:compile
[INFO] \- dev.buijs.example.starwars:library-force:jar:1.0.0:compile
[INFO]    \- org.springframework:spring-jcl:jar:6.1.4:compile
Written on April 27, 2024