In my plugin I need to process the dependency hierarchy and get information (groupId, artifactId, version etc) about each dependency and if it was excluded. What is the best way to do this?

- 18,541
- 27
- 119
- 168

- 1,821
- 4
- 20
- 21
-
If you happen to need to do this for an *arbitrary artifact* while honoring parent POMs, exclusions etc, [check this approach](https://stackoverflow.com/questions/13200497/how-to-programmatically-list-all-transitive-dependencies-including-overridden-o#70823705) – Janaka Bandara Jan 23 '22 at 16:20
7 Answers
The dependency plugin has the tree goal that does most of this work. It processes a MavenProject
using the DependencyTreeBuilder
, this returns a DependencyNode
with hierarchical information about the resolved dependencies (and their transitive dependencies).
You can copy much of the code directly from the TreeMojo. It uses the CollectingDependencyNodeVisitor
to traverse the tree and produce a List
of all the nodes.
You can access the Artifact
for the node by calling getArtifact()
, then get the artifact information as needed. To get the exclusion reason, DependencyNode
has a getState()
method that returns an int indicating if the dependency has been included, or if not what the reason for omitting it was (there are constants in the DependencyNode class to check the return value against)
//All components need this annotation, omitted for brevity
/**
* @component
* @required
* @readonly
*/
private ArtifactFactory artifactFactory;
private ArtifactMetadataSource artifactMetadataSource;
private ArtifactCollector artifactCollector;
private DependencyTreeBuilder treeBuilder;
private ArtifactRepository localRepository;
private MavenProject project;
public void execute() throws MojoExecutionException, MojoFailureException {
try {
ArtifactFilter artifactFilter = new ScopeArtifactFilter(null);
DependencyNode rootNode = treeBuilder.buildDependencyTree(project,
localRepository, artifactFactory, artifactMetadataSource,
artifactFilter, artifactCollector);
CollectingDependencyNodeVisitor visitor =
new CollectingDependencyNodeVisitor();
rootNode.accept(visitor);
List<DependencyNode> nodes = visitor.getNodes();
for (DependencyNode dependencyNode : nodes) {
int state = dependencyNode.getState();
Artifact artifact = dependencyNode.getArtifact();
if(state == DependencyNode.INCLUDED) {
//...
}
}
} catch (DependencyTreeBuilderException e) {
// TODO handle exception
e.printStackTrace();
}
}

- 43,979
- 12
- 156
- 150

- 83,208
- 23
- 172
- 177
-
3+1 Very nice, thanks! However, the snippet contains a small error: List< DependencyNode > nodes = visitor.getNodes(); Above the for loop. – javamonkey79 Dec 11 '09 at 18:44
-
9Much of that is deprecated in Maven3. Anyone care to update with a Maven3 (non-deprecated) solution? – Ben Aug 24 '12 at 17:57
-
1
You could use MavenProject#getDependencyArtifacts() or MavenProject#getDependencies() (the later one returns also transitive dependencies).
/**
* Test Mojo
*
* @goal test
* @requiresDependencyResolution compile
*/
public class TestMojo extends AbstractMojo {
/**
* The Maven Project.
*
* @parameter expression="${project}"
* @required
* @readonly
*/
private MavenProject project = null;
/**
* Execute Mojo.
*
* @throws MojoExecutionException If an error occurs.
* @throws MojoFailureException If an error occurs.
*/
public void execute() throws MojoExecutionException,
MojoFailureException {
...
Set dependencies = project.getDependencies();
...
}
}
I'm not totally sure but I think both methods return a collection of Artifact implementations that expose getters for groupId, artifactId, version, etc.

- 43,979
- 12
- 156
- 150

- 562,542
- 136
- 1,062
- 1,124
-
3+1 This is a simpler solution than mine if you need to get all *resolved* dependencies, but if you want to find out information about excluded dependencies you need more than this – Rich Seller Sep 29 '09 at 12:02
-
Damn, you are right, I missed the point about excluded dependencies. So this doesn't answer the OP question. – Pascal Thivent Sep 29 '09 at 12:13
-
yes I'm after all dependencies so I can report why they weren't included, thanks for the information though – talk to frank Sep 29 '09 at 14:43
-
18
-
1in Maven 3.x, there is a [setResolvedArtifacts][1] method, but its field private... [1] http://maven.apache.org/ref/3.0.3/maven-core/apidocs/org/apache/maven/project/MavenProject.html#setResolvedArtifacts%28java.util.Set%29 – Renaud Jan 31 '12 at 16:41
-
The @Parameter must be outside comments and capitalised. Teach me to cut'n'paste. – TimP Nov 11 '13 at 16:30
-
how to get transitive dependencies in maven 3? getDependencies doesnt reolve trans dependencies. – gabber12 Feb 11 '15 at 06:47
-
This is the easiest and simplest way to resolve and get dependencies from within a mojo. This is the better answer. – Nambi Feb 26 '15 at 02:22
-
You probably meant `getArtifacts` method which will retrieve all dependency artefacts including transitive ones. The `getDependencyArtifacts` method is deprecated. – scrutari Dec 27 '16 at 17:17
Here is an up to date, Maven3 example on how to get all dependencies (including transitive) as well as have access to the files themselves (if you for instance need to add the paths to a classpath).
// Default phase is not necessarily important.
// Both requiresDependencyCollection and requiresDependencyResolution are extremely important however!
@Mojo(name = "simple", defaultPhase = LifecyclePhase.PROCESS_RESOURCES, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME)
public class SimpleMojo extends AbstractMojo {
@Parameter(defaultValue = "${project}", readonly = true)
private MavenProject mavenProject;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
for (final Artifact artifact : mavenProject.getArtifacts()) {
// Do whatever you need here.
// If having the actual file (artifact.getFile()) is not important, you do not need requiresDependencyResolution.
}
}
}
Changing the parameters in the Mojo is a very important piece that I was missing. Without it, lines like the following:
@Parameter(defaultValue = "${project.compileClasspathElements}", readonly = true, required = true)
private List<String> compilePath;
Will only return the classes directory, not the path you expect.
Changing the requiresDependencyCollection and requiresDependencyResolution to different values will allow you to change the scope of what you want to grab. The maven documentation can provide more detail.

- 211,314
- 129
- 689
- 1,509

- 553
- 7
- 17
-
1This is the best answer (up to date & comprehensive). I created an account & answered some questions just so I can get enough karma to have the right to upvote this. Thanks. – Hugues M. Apr 29 '17 at 15:22
-
Despite i voted for that answer it seems that second level transitive dependencies are not resolved using this method. – Abbadon Jun 08 '18 at 16:16
-
Hi, how can I get this to work in my custom extension? Can someone please look at this question? greatly appreciate your help https://stackoverflow.com/questions/51888672/maven3-how-to-get-all-the-project-dependencies-in-a-custom-maven-extension – h-kach Aug 19 '18 at 16:21
-
If you want to make this slightly more awesome, please include the project dependencies. I am getting java.lang.NoClassDefFoundError: org/eclipse/aether/RepositorySystemSession and i can't quite figure out what is wrong. If i add the eclipse aether dependencies, i instead end up with org.apache.maven.artifact.versioning.DefaultArtifactVersion.compareTo(Lorg/apache/maven/artifact/versioning/ArtifactVersion;)I java.lang.NoSuchMethodError – Martin Nielsen Jun 06 '19 at 16:24
-
Try to use Aether
utility class from jcabi-aether to get a list of all dependencies of any artifact:
File repo = this.session.getLocalRepository().getBasedir();
Collection<Artifact> deps = new Aether(this.getProject(), repo).resolve(
new DefaultArtifact("junit", "junit-dep", "", "jar", "4.10"),
JavaScopes.RUNTIME
);
-
Hi, can I do this in this scenario as well ? Appreciate your help https://stackoverflow.com/questions/51888672/maven3-how-to-get-all-the-project-dependencies-in-a-custom-maven-extension – h-kach Aug 19 '18 at 16:22
Why not just get back all the dependencies (both direct and transitive ones) and check for exclusion?
@Parameter(property = "project", required = true, readonly = true)
private MavenProject project;
public void execute() throws MojoExecutionException
{
for (Artifact a : project.getArtifacts()) {
if( a.getScope().equals(Artifact.SCOPE_TEST) ) { ... }
if( a.getScope().equals(Artifact.SCOPE_PROVIDED) ) { ... }
if( a.getScope().equals(Artifact.SCOPE_RUNTIME) ) { ... }
}
}

- 5,465
- 6
- 44
- 72
Maven 3 use aether, there is sample here : https://docs.sonatype.org/display/AETHER/Home

- 612
- 6
- 16
-
3Sorry, down voting for not including content in stackoverflow in case of broken links - link is now broken. – Greg Domjan Jun 16 '15 at 16:52
-
Aether [was disowned by Eclipse](https://projects.eclipse.org/projects/technology.aether/reviews/termination-review), but subsequently [adopted by Apache](https://maven.apache.org/resolver/)! – earcam Oct 06 '18 at 14:46
-
... it's a trivial update from Eclipse Aether 1.1.0 to Apache Aether 1.1.1; just GIDs for the most part. [org.apache.maven.resolver](https://search.maven.org/search?q=g:org.apache.maven.resolver) and [maven-resolver-provider](https://search.maven.org/search?q=g:org.apache.maven%20AND%20a:maven-resolver-provider&core=gav) – earcam Oct 06 '18 at 14:56
For Maven 3 you can use DependencyGraphBuilder. It does pretty much the same thing as DependencyTreeBuilder.
Here is the example
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.resolver.filter.IncludesArtifactFilter;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
import org.apache.maven.shared.dependency.graph.DependencyNode;
import org.apache.maven.shared.dependency.graph.traversal.CollectingDependencyNodeVisitor;
public class AnanlyzeTransitiveDependencyMojo extends AbstractMojo{
@Parameter(defaultValue = "${project}", readonly = true, required = true)
private MavenProject project;
@Parameter(defaultValue = "${session}", readonly = true, required = true)
private MavenSession session;
@Component(hint="maven3")
private DependencyGraphBuilder dependencyGraphBuilder;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
// If you want to filter out certain dependencies.
ArtifactFilter artifactFilter = new IncludesArtifactFilter("groupId:artifactId:version");
ProjectBuildingRequest buildingRequest = new DefaultProjectBuildingRequest(session.getProjectBuildingRequest());
buildingRequest.setProject(project);
try{
DependencyNode depenGraphRootNode = dependencyGraphBuilder.buildDependencyGraph(buildingRequest, artifactFilter);
CollectingDependencyNodeVisitor visitor = new CollectingDependencyNodeVisitor();
depenGraphRootNode.accept(visitor);
List<DependencyNode> children = visitor.getNodes();
getLog().info("CHILDREN ARE :");
for(DependencyNode node : children) {
Artifact atf = node.getArtifact();
}
}catch(Exception e) {
e.printStackTrace();
}

- 211,314
- 129
- 689
- 1,509

- 61
- 2
-
What does the pom look like. Whatever I do, I get `NoClassDefFoundError`s for `org/sonatype/aether` when running my plugin – mibutec Jun 07 '20 at 08:37
-
Try:
org.apache.maven.shared maven-dependency-tree 3.2.1 org.eclipse.aether *