API Compatibility

Maven Resolver exposes three modules for clients and those extending Maven Resolver:

  • maven-resolver-api (in short API) – for clients and those extending it
  • maven-resolver-spi (in short SPI) – for those extending it
  • maven-resolver-util (in short Util) – for client and those extending it

Each module guarantees non-breaking (source and binary) compatibility, as long clients and extenders obey some rules. If you break any of these rules, you are prone to breakage, and you are on your own.

Interface And (Abstract) Class Level Contracts

In source, we use two important Javadoc tags to mark intent:

  • @noextend – classes (or interfaces) carrying this tag MUST NOT be extended
  • @noimplement – interfaces carrying this tag MUST NOT be directly or indirectly implemented, UNLESS the Javadoc of given interface points to an abstract support class that makes indirect implementation possible.

Examples:

  • RepositorySystem interface. It carries both @noextend and @noimplement tags. This interface MUST NOT be extended nor implemented. This is a component interface, that is usually injected into client application.
  • TransferListener interface. It carries both @noextend and @noimplement tags, but Javadoc points at AbstractTransferListener as extension point. Hence, clients are NOT allowed to extend this interface, nor to directly implement it, but, if custom listener is needed, it is warmly advised to extend the given abstract class. This way we can protect you from future breakage.

Package Level Contracts

Maven Resolver implements customary habit to name packages NOT meant to be accessed by clients. If a Java package contains following names:

  • impl
  • internal

That Java package is meant as “internal” and does NOT offer guarantees of compatibility as API is. You may use classes from these packages, but again, you are on your own to deal with (binary or source) breakages. If you think a class from such package should be “pulled out” and made part of SPI or maybe API, better inform us via JIRA: create a ticket and let's discuss.

As a side note, the count of those names in Java package is directly proportional to possibility of breaking changes: the more, the larger the possibility of breakage even in minor releases.

Version Level Contracts

Maven Resolver does NOT use “semantic versioning”, but still tries at best to reflect contained changes using version number. We use “major.minor.patch” versioning on resolver with following semantics:

  • On major version change, one should NOT expect any backward compatibility.
  • On minor version change, we TRY to keep backward compatibility for those “exposed” 3 modules: API, SPI and Util. Still, there are examples when we failed to do so, usually driven by new features.
  • On minor version change, we ENSURE backward compatibility for those “exposed” 3 modules: API, SPI and Util.

In any of three version changes above, in areas where we do not offer guarantees, everything can happen.

Outside of Maven

Applications integrating Maven Resolver outside of Maven has really simple job: all they have to ensure is that API, SPI, Util and the rest of resolver (impl, basic-connector and transports) have all same versions, and they can rely on these backward compatibility contracts as explained above.

Inside of Maven

Historically, Maven 3.1 (as Maven 3.0 used resolver from different package) provided API, SPI and Impl from its own embedded resolver, while Util, Connector, if some plugin or extension depended on those, was resolved. This caused that a plugin may work with different versions of API, SPI, Impl or Connector. Given Resolver had API “frozen” for too long time, this was essentially not a problem, but still weird.

This changes in Maven 3.9+: Maven starting with version 3.9.0 will provide API, SPI, Impl and Util and Connector. Reason for this change is that Impl and Connector bundled in Maven implements things from both, API and SPI, and there was a binary incompatible change between Resolver 1.8.0 and previous versions.

Most Resolver users should not be affected by this change.

The binary incompatible change happened in SPI class RepositoryLayout as part of work done for MRESOLVER-230, and affects both, Connector and Impl.

Backward Compatibility Checks

To ensure backward compatibility, starting from 1.9.0 version Maven Resolver uses JApiCmp, with two executions (for source and binary level checks). The plugin is enabled on 3 modules of Resolver mentioned at page top: API, SPI and Util. For “baseline” we use version 1.8.0.