Maven Transitive Dependency Filtering

2 minute read Published:

The other day I wrote a post about examining dependencies in maven plugins. Today I was working on a similar project, and I discovered some non-intuitive behavior with the Maven ArtifactResolver. Several of the resolveTransitively methods accept an ArtifactFilter, but the filter gets applied in an odd way.

The bulk of the resolution process takes place in the DefaultArtifactCollector and ResolutionNode classes. The collector basically does a breadth first search of the dependency tree, but it filters the entire path from the project to the node, as opposed to just filtering the final results. This means that depending on how your filter is defined, there could be dependencies that meet its criteria, but are not included in the ArtifactResolutionResult. Consider a project with the following dependency tree.

[INFO] [dependency:tree {execution: default-cli}]
[INFO] com.mydomain:module:jar:0.0.1-SNAPSHOT
[INFO] +- com.mydomain:dependency:jar:0.0.1-SNAPSHOT:compile
[INFO] |  \- com.mydomain:transitive-dependency:jar:0.0.1-SNAPSHOT:compile

You can filter on a groupId of “com.mydomain”, and you’ll get all of the artifacts. However if you were to try to filter on an artifactId or a type other than jar, you’d get zero results. I’m sure there’s a good reason for the filtering to work this way, but it can take you a while to figure it out if it’s not what you’re expecting. If what you really want to do is filter the final results of the transitive resolution, you need to do that yourself.