API Compatibility
Maven Resolver exposes three modules for client applications and extensions. Client applications invoke methods in these modules. Extensions inherit from classes and implement interfaces.
maven-resolver-api(API) - Client applications and extensions use this module.maven-resolver-spi(SPI) - Extensions use this module.maven-resolver-util(Util) - Client applications and extensions use this module.
If you obey specific rules, these modules will be source and binary compatible across minor releases. If you break these rules, your code can break when you update these modules.
Interface And (Abstract) Class Level Contracts
We use two Javadoc tags in the source code to mark intent:
@noextend- You must not extend classes or interfaces with this tag.@noimplement- You must not implement interfaces with this tag directly or indirectly.
If the Javadoc points to an abstract support class, you can implement the @noimplement interface indirectly.
Examples:
The RepositorySystem interface has the @noextend tag and the @noimplement tag. You must not extend or implement this interface. The RepositorySystem interface is a component interface. Client applications usually receive this interface through dependency injection.
The TransferListener interface has the @noextend tag and the @noimplement tag. The Javadoc points to the AbstractTransferListener abstract class. You must not extend or implement the TransferListener interface directly. If you need a custom listener, extend the AbstractTransferListener abstract class. This abstract class protects your code from future breakages.
Package Level Contracts
Maven Resolver identifies internal Java packages with the words impl and internal. These internal packages do not guarantee compatibility between releases. If you use classes from these packages, you must fix source breakages and binary breakages yourself. You can request to move a class to the API or the SPI through a ticket on GitHub.
Version Level Contracts
Maven Resolver does not use “semantic versioning”. However, Maven Resolver uses a “major.minor.patch” version format to indicate changes. Major version changes do not provide backward compatibility. The API, SPI, and Util modules should be backwards compatible across minor version changes. However, we have violated this rule in the past, usually to support new features.
Maven Resolver does not guarantee compatibility for internal modules. Internal modules can change in any version update.
Outside of Maven
Applications can use Maven Resolver outside of Maven. These applications must use the same version for all Maven Resolver modules. For example, the API, SPI, Util, impl, basic-connector, and transports must share the same version. If the versions match, the applications can rely on the compatibility guarantees.
Inside of Maven
In the past, Maven 3.1 provided the API, SPI, and impl modules from an embedded resolver. Plugins resolved the Util and Connector modules separately. Therefore, plugins used different versions of these modules. The static API prevented major problems.
Maven 3.9.0 provides the API, SPI, impl, Util, and Connector modules. The bundled impl and Connector modules implement the API and the SPI. A binary incompatibility occurred between Maven Resolver 1.8.0 and previous versions. Because of this incompatibility, Maven 3.9.0 bundles all modules to ensure stability.
This change does not affect most Maven Resolver users.
The binary incompatibility occurred in the RepositoryLayout SPI class for MRESOLVER-230. This incompatibility affects the Connector module and the impl module.
Backward Compatibility Checks
Maven Resolver uses JApiCmp to verify backward compatibility. Starting with version 1.9.0, Maven Resolver runs this plugin twice to verify source compatibility and binary compatibility. The plugin runs on the API, SPI, and Util modules. The compatibility baseline is version 1.8.0.

