Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[rdf4j-dev] Source and binary compatiblity checks (was: Re: Broken build)


On Mon, 16 May 2022, at 23:24, Håvard Ottestad wrote:
Hi,

Our japicmp settings are stricter then they used to be and that is why the build is broken.

Japicmp is complaining about a new public static method on an interface from this PR: https://github.com/eclipse/rdf4j/pull/3800

I've intended to update the japicmp settings to allow for new methods to interfaces that have a default (or static) implementation. https://github.com/eclipse/rdf4j/blob/7db975d5e686bbd1a8d7b8d60c650966adbaea81/pom.xml#L904


Thanks for fixing this Håvard, and apologies that my original response was a bit cranky (I blame insufficient caffeine).

Let's talk about compatibility a little, more generally - it might be good to revisit some of the thinking behind this, also for people newer to the project.

Japicmp is a tool that helps us guard against putting in any changes that are backward incompatible in patch or minor releases (in accordance with the definitions of SemVer). Before we go into the specific settings of the japicmp, let's discuss what we actually want to achieve, guarantee-wise.

Backward compatibility in Java typically breaks down in two types: source compatibility, and binary compatibility.

Binary compatibility is the strongest kind of guarantee. Put simply, it guarantees that the new version is a drop-in replacement for the older version, and the client application can immediately use it, without the need to be recompiled.

Source compatibility means that the new version can be used by existing applications without having to  make code changes - but the application will need to be recompiled.

For RDF4J patch releases, binary compatibility is a very desirable trait: we want our users able to drop jar file 4.0.2 over the top of 4.0.1 and not have to recompile their app. We've previously also made this guarantee for minor releases. However, we allow a few exceptions:
  1.  we make classes/methods annotated with @InternalUseOnly or @Experimental exempt from the compatibility checks. This is true for either patch or minor releases - though the advice is not to use this as part of a patch fix;
  2. the japicmp tool by default considers adding a new default method in an interface not binary (or even source!) compatible, and only allows it as part of a major new release. We previously put a config override in place to mark this as source+binary compatible and allowed in minor releases (this is what Håvard just restored).
I'm not entirely sure why japicmp considers new default methods incompatible, though I suspect it has to do with erring on the side of caution and there being corner cases such as described in these articles:
What it comes down to is that we make a judgment call to use new default methods with due care. While a new default method does not necessarily break binary compatibility, if done unwisely (e.g. interfering with an existing method) it can lead to runtime-errors. 

The thing to keep in mind, of course, is that all that japicmp does is just guide-rails, and not a complete guarantee of compatibility. There are loads of changes that we could put in that would satisfy the japicmp checks but would completely break an existing application.


Cheers,

Jeen

Back to the top