News and Notes from the Makers of Nexus | Sonatype Blog

How to Use Aether in Maven Plugins

Written by Benjamin Bentmann | January 07, 2011

When developing plugins for Maven 3.0 plugin developers that need to perform dependency resolution have a choice: they can continue to use the Maven 2.x API, or they can use the new Maven 3 API which makes use of Aether. In this post, I'm going to walk through some of the API features that are now available to plugin developers in Aether.

If your plugin needs to be compatible with Maven 2.x, take a look at the sources of Maven Dependency Plugin. This example provides a sophisticated example of using the Maven 2.x dependency resolution API. But if legacy Maven support is of no concern to you, read on and see how the Maven 3.x API handles the job.

Aether Plugin Dependencies

To make use of the new Maven 3.x Plugin API add the following dependencies to your plugin project's POM:

The dependency on maven-plugin-api shouldn't be surprising - the more interesting bits are aether-api and aether-util. Depending on your use case, the latter dependency might not be required for your plugin given aether-util is just a collection of utility classes. For our example however, it will be handy to have org.sonatype.aether.util.artifact.DefaultArtifact around.

Mojo Parameters

Now that the plugin build path is set up, we can continue to add some parameters to our plugin that will grab the repository system:

In contrast to Maven 2.x, a single component of type RepositorySystem is sufficient for all resolution work. This repository system generally takes a request bean as input and hands back a result bean. When performing multiple repository operations, some inputs tend to be the same like the local repository, the offline mode, proxies etc. These configuration values are represented by the RepositorySystemSession.

The remote repositories to resolve from are always specific to a certain operation. For our example, we're going to use the remote plugin repositories of the current project. Alternatively, the expression $\{project.remoteProjectRepositories\} is available to grab the project dependency repositories. Which set of remote repositories to use depends on the kind of artifacts the plugin is going to resolve. Artifacts that are compile/runtime/test dependencies of a project need to be resolved from $\{project.remoteProjectRepositories\}. Plugins or other artifacts that merely support the build need to be resolved from $\{project.remotePluginRepositories\}.

Mojo Execution

Equipped with the plugin parameters shown in the previous section, we can start to do some real work with project dependencies:

This code snippet resolves a single artifact that is hard-coded here for the sake of conciseness. By employing other methods of the repoSystem transitive resolution or version query can be performed as well.

Tip: To help with the common task of transitively resolving project dependencies, the maven-core artifact provides the component org.apache.maven.project.ProjectDependenciesResolver.

A complete plugin project ready to run and play with can be found in our Git repo at https://github.com/sonatype/aether-demo-maven-plugin.

A final note to avoid confusion when experimenting with the new API: Unlike the Maven 2.x API, Artifact instances in Aether are immutable. As such the result of a resolution operation returns new Artifact instances. That is why it is essential that the log statement above uses result.getArtifact().getFile() and not artifact.getFile().