Alexandre Nedjari
Alexandre Nedjari

Reputation: 81

Get a complete dependency graph in maven

I have a problem with maven dependencies. I try in my maven plugin to have a full dependencies graph, but some duplicated nodes does not appear.

My maven project is made of :

here are the differents pom.xml files :

dependency_test :

    <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>com.aned.test</groupId>
    <artifactId>dependency_test</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <modules>
        <module>mod1</module>
        <module>mod2</module>
        <module>mod3</module>
    </modules>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.aned.test</groupId>
                <artifactId>mod1</artifactId>
                <version>1.0.0</version>
            </dependency>
            <dependency>
                <groupId>com.aned.test</groupId>
                <artifactId>mod2</artifactId>
                <version>1.0.0</version>
            </dependency>
            <dependency>
                <groupId>com.aned.test</groupId>
                <artifactId>mod3</artifactId>
                <version>1.0.0</version>
            </dependency>
            <dependency>
                <groupId>com.aned.test</groupId>
                <artifactId>mod4</artifactId>
                <version>1.0.0</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.aned</groupId>
            <artifactId>dependency_test_maven_plugin</artifactId>
            <version>1.0.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

mod1 :

    <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>
    <parent>
        <groupId>com.aned.test</groupId>
        <artifactId>dependency_test</artifactId>
        <version>1.0.0</version>
    </parent>
    <artifactId>mod1</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.aned.test</groupId>
            <artifactId>mod2</artifactId>
        </dependency>
        <dependency>
            <groupId>com.aned.test</groupId>
            <artifactId>mod3</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>com.aned</groupId>
                <artifactId>dependency_test_maven_plugin</artifactId>
                <version>1.0.0</version>
                <executions>
                    <execution>
                        <phase>install</phase>
                        <goals>
                            <goal>dependency-test-goal</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

mod2 :

<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>
    <parent>
        <groupId>com.aned.test</groupId>
        <artifactId>dependency_test</artifactId>
        <version>1.0.0</version>
    </parent>
    <artifactId>mod2</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.aned.test</groupId>
            <artifactId>mod3</artifactId>
        </dependency>
        <dependency>
            <groupId>com.aned.test</groupId>
            <artifactId>mod4</artifactId>
        </dependency>
    </dependencies>
</project>

mod3 :

    <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>
  <parent>
    <groupId>com.aned.test</groupId>
    <artifactId>dependency_test</artifactId>
    <version>1.0.0</version>
  </parent>
  <artifactId>mod3</artifactId>
</project>

mod4 :

    <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>
  <parent>
    <groupId>com.aned.test</groupId>
    <artifactId>dependency_test</artifactId>
    <version>1.0.0</version>
  </parent>
  <artifactId>mod4</artifactId>
</project>

My dependency graph is so like :

mod1
--mod2
----mod3
----mod4
--mod3

I need to have this complete graph in my "dependency_test_maven_plugin" plugin. For now, it look like :

pom.xml

<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>com.aned</groupId>
    <artifactId>dependency_test_maven_plugin</artifactId>
    <version>1.0.0</version>
    <packaging>maven-plugin</packaging>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>3.6.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>3.6.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-project</artifactId>
            <version>2.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-core</artifactId>
            <version>3.6.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.shared</groupId>
            <artifactId>maven-dependency-tree</artifactId>
            <version>3.0.1</version>
        </dependency>
    </dependencies>
</project>

Mojo class :

package dependency_test_maven_plugin;

import java.util.Arrays;

import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.DefaultProjectBuildingRequest;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
import org.apache.maven.shared.dependency.graph.DependencyNode;
import org.apache.maven.shared.dependency.graph.traversal.CollectingDependencyNodeVisitor;

@Mojo(name = "dependency-test-goal", defaultPhase = LifecyclePhase.PROCESS_RESOURCES, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME)
public class JLinkMojo extends AbstractMojo {

    @Parameter(defaultValue = "${project}", readonly = true, required = true)
    MavenProject project;

    @Parameter(defaultValue = "${session}", readonly = true, required = true)
    private MavenSession session;

    @Component(hint = "default")
    private DependencyGraphBuilder dependencyGraphBuilder;

    ArtifactFilter artifactFilter;
    ProjectBuildingRequest buildingRequest;

    public void execute() throws MojoExecutionException {
        artifactFilter = new ExcludesArtifactFilter(Arrays.asList("com.aned:dependency_test_maven_plugin"));
        buildingRequest = new DefaultProjectBuildingRequest(session.getProjectBuildingRequest());

        buildingRequest.setProject(project);

        try {
            DependencyNode rootNode = dependencyGraphBuilder.buildDependencyGraph(buildingRequest, artifactFilter);
            getLog().info("Start depdendency graph");
            int level = 0;
            displayNode(rootNode, level);
            getLog().info("End depdendency graph");

            CollectingDependencyNodeVisitor visitor = new CollectingDependencyNodeVisitor();
            rootNode.accept(visitor);

            for (DependencyNode dependencyNode : visitor.getNodes()) {
                getLog().info("Start depdendency graph for node " + dependencyNode.getArtifact().getArtifactId());
                displayNode(dependencyNode, level);
                getLog().info("End depdendency graph for node " + dependencyNode.getArtifact().getArtifactId());
            }

        } catch (DependencyGraphBuilderException e) {
            throw new MojoExecutionException("Error", e);
        }
    }

    private void displayNode(DependencyNode rootNode, int level) {
        String indentation = "";
        for (int i = 0; i < level; i++) {
            indentation += "--";
        }
        getLog().info(indentation + rootNode.getArtifact().getArtifactId());

        for (DependencyNode childrenNode : rootNode.getChildren()) {
            displayNode(childrenNode, level + 1);
        }
    }
}

On execution, the mojo traces are :

[INFO] --- dependency_test_maven_plugin:1.0.0:dependency-test-goal (default) @ mod1 ---
[INFO] Start depdendency graph
[INFO] mod1
[INFO] --mod2
[INFO] ----mod4
[INFO] --mod3
[INFO] End depdendency graph
[INFO] Start depdendency graph for node mod1
[INFO] mod1
[INFO] --mod2
[INFO] ----mod4
[INFO] --mod3
[INFO] End depdendency graph for node mod1
[INFO] Start depdendency graph for node mod2
[INFO] mod2
[INFO] --mod4
[INFO] End depdendency graph for node mod2
[INFO] Start depdendency graph for node mod4
[INFO] mod4
[INFO] End depdendency graph for node mod4
[INFO] Start depdendency graph for node mod3
[INFO] mod3
[INFO] End depdendency graph for node mod3

So, in the dependency graph traces like in visitor.getNodes traces, the dependency from mod2 to mod3 is not visible (I think it's because it's a duplicate of the link from mod1 to mod3). Is there a way to have the complete trace :

mod1
--mod2
----mod3
----mod4
--mod3

Edit 1 : If I try to use dependency:tree on my parent project, I got the same result :

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ mod1 ---
[INFO] com.aned.test:mod1:jar:1.0.0
[INFO] +- com.aned.test:mod2:jar:1.0.0:compile
[INFO] |  \- com.aned.test:mod4:jar:1.0.0:compile
[INFO] +- com.aned.test:mod3:jar:1.0.0:compile
[INFO] \- com.aned:dependency_test_maven_plugin:jar:1.0.0:provided
[INFO]    +- org.apache.maven:maven-plugin-api:jar:3.6.0:provided
[INFO]    |  +- org.apache.maven:maven-model:jar:3.6.0:provided
[INFO]    |  +- org.apache.maven:maven-artifact:jar:3.6.0:provided
[INFO]    |  +- org.eclipse.sisu:org.eclipse.sisu.plexus:jar:0.3.3:provided
[INFO]    |  |  \- javax.enterprise:cdi-api:jar:1.0:provided
[INFO]    |  |     \- javax.annotation:jsr250-api:jar:1.0:provided
[INFO]    |  +- org.codehaus.plexus:plexus-utils:jar:3.1.0:provided
[INFO]    |  \- org.codehaus.plexus:plexus-classworlds:jar:2.5.2:provided
[INFO]    +- org.apache.maven:maven-project:jar:2.2.1:provided
[INFO]    |  +- org.apache.maven:maven-settings:jar:2.2.1:provided
[INFO]    |  +- org.apache.maven:maven-profile:jar:2.2.1:provided
[INFO]    |  +- org.apache.maven:maven-artifact-manager:jar:2.2.1:provided
[INFO]    |  |  +- org.apache.maven.wagon:wagon-provider-api:jar:1.0-beta-6:provided
[INFO]    |  |  \- backport-util-concurrent:backport-util-concurrent:jar:3.1:provided
[INFO]    |  +- org.apache.maven:maven-plugin-registry:jar:2.2.1:provided
[INFO]    |  +- org.codehaus.plexus:plexus-interpolation:jar:1.11:provided
[INFO]    |  \- org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9-stable-1:provided
[INFO]    |     +- junit:junit:jar:3.8.1:provided
[INFO]    |     \- classworlds:classworlds:jar:1.1-alpha-2:provided
[INFO]    +- org.apache.maven:maven-core:jar:3.6.0:provided
[INFO]    |  +- org.apache.maven:maven-settings-builder:jar:3.6.0:provided
[INFO]    |  |  \- org.sonatype.plexus:plexus-sec-dispatcher:jar:1.4:provided
[INFO]    |  |     \- org.sonatype.plexus:plexus-cipher:jar:1.4:provided
[INFO]    |  +- org.apache.maven:maven-builder-support:jar:3.6.0:provided
[INFO]    |  +- org.apache.maven:maven-repository-metadata:jar:3.6.0:provided
[INFO]    |  +- org.apache.maven:maven-model-builder:jar:3.6.0:provided
[INFO]    |  +- org.apache.maven:maven-resolver-provider:jar:3.6.0:provided
[INFO]    |  |  \- org.slf4j:slf4j-api:jar:1.7.25:provided
[INFO]    |  +- org.apache.maven.resolver:maven-resolver-impl:jar:1.3.1:provided
[INFO]    |  +- org.apache.maven.resolver:maven-resolver-api:jar:1.3.1:provided
[INFO]    |  +- org.apache.maven.resolver:maven-resolver-spi:jar:1.3.1:provided
[INFO]    |  +- org.apache.maven.resolver:maven-resolver-util:jar:1.3.1:provided
[INFO]    |  +- org.apache.maven.shared:maven-shared-utils:jar:3.2.1:provided
[INFO]    |  |  \- commons-io:commons-io:jar:2.5:provided
[INFO]    |  +- org.eclipse.sisu:org.eclipse.sisu.inject:jar:0.3.3:provided
[INFO]    |  +- com.google.inject:guice:jar:no_aop:4.2.1:provided
[INFO]    |  |  +- aopalliance:aopalliance:jar:1.0:provided
[INFO]    |  |  \- com.google.guava:guava:jar:25.1-android:provided
[INFO]    |  |     +- com.google.code.findbugs:jsr305:jar:3.0.2:provided
[INFO]    |  |     +- org.checkerframework:checker-compat-qual:jar:2.0.0:provided
[INFO]    |  |     +- com.google.errorprone:error_prone_annotations:jar:2.1.3:provided
[INFO]    |  |     +- com.google.j2objc:j2objc-annotations:jar:1.1:provided
[INFO]    |  |     \- org.codehaus.mojo:animal-sniffer-annotations:jar:1.14:provided
[INFO]    |  +- javax.inject:javax.inject:jar:1:provided
[INFO]    |  +- org.codehaus.plexus:plexus-component-annotations:jar:1.7.1:provided
[INFO]    |  \- org.apache.commons:commons-lang3:jar:3.8.1:provided
[INFO]    \- org.apache.maven.shared:maven-dependency-tree:jar:3.0.1:provided
[INFO]       \- org.eclipse.aether:aether-util:jar:0.9.0.M2:provided
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] dependency_test 1.0.0 .............................. SUCCESS [  3.769 s]
[INFO] mod3 ............................................... SUCCESS [  0.153 s]
[INFO] mod2 ............................................... SUCCESS [  0.110 s]
[INFO] mod1 1.0.0 ......................................... SUCCESS [  0.097 s]
[INFO] ------------------------------------------------------------------------

Thank you,

Upvotes: 2

Views: 3311

Answers (2)

drkicknrush
drkicknrush

Reputation: 143

Not sure if this is what you're looking for, but you can see all dependencies (including duplicated) using:

mvn dependency:tree -Dverbose

Upvotes: 1

solbs
solbs

Reputation: 1068

What's happening: "mod3" resolves to the nearest parent.

I believe this falls under "dependency mediation" although that is more for version resolution.

To get the tree you expect you would have to buildDependencyGraph with the children as the root.

Upvotes: 0

Related Questions