Legit but Useless: Maven Version Ranges Explained

Michael Kutz
3 min readApr 25, 2019

--

One of the most important features of Apache Maven is its ability to retrieve dependencies from repositories. For that we need to define which version of a dependency we need for our product. For some dependencies it’s just fine to pick one exact version –e.g. 1.23– which works flawlessly.

However, for some dependencies we’d like to just pick the latest version from a range. For example I’d like the Selenium version to be just the latest 3.x but want to avoid breaking API changes that will probably happen with 4.0. And Maven does have a feature for that: version ranges.

So in order to get the latest Selenium 3.x (Selenium) version, we can define something like [3,4) (≈ anything greater or equal to 3 and lesser then 4) or [3.141.59,4.0.0) (≈ anything greater or equal to 3.141.59 and lesser then 4.0.0). Seems right? It’s not. Recently a new version of Selenium has been released: 4.0.0-alpha-1 and Maven pulled that even though we told to exclude it!

This confused me for some time until I finally took the time to read most of this discussion on Nabble.

Following the Semantic Versioning Spec and basic common sense, 4.0.0-alpha-1 is a pre-release version of 4.0.0. So it is a lesser version:3.0.0 < 3.141.59 < 4.0.0-alpha-1 < 4.0.0. So Maven resolved the dependency following our specification: anything greater then 3.141.59 and lesser then 4.0.0. This is legit basic math!

In order to reach our goal anyway, we have several options:

  • We can give up and use one exact version: 3.141.59.
  • We can make up a version that will –probably– never be reached and is lesser then any version we don’t want: [3.141.59,3.999999).
  • Since we now know the exact version of the first release we want to avoid for now, we can just put that as the upper boundary of our range: [3.141.59,4.0.0-alpha-1) or [3,4-alpha) (see Maven Version Order Specification; thanks Stefan Neuhaus for pointing that out). The point is we usually cannot know, what the version modifier of the first pre-release will be. It could also be beta or RC. So we can only apply this, once the version was published.

Even though made up versions seem ugly and also bear the risk of that version will eventually be release, it is the best way we got right now as long as we don’t know the exact version of the first release to be avoided. Once we know it, using it seems a bit less confusing to me.

Maven also provides a tool to check version ordering (as I learned form Stefan Neuhaus’ answer). On Linux or Mac you can just call

java -cp "$MAVEN_HOME/lib/*" org.apache.maven.artifact.versioning.ComparableVersion 3.141.59 4-alpha 4+test 4

And get a nice summary of how Maven will compare the given versions:

Display parameters as parsed by Maven (in canonical form) and comparison result:
1. 3.141.59 == 3.141.59
3.141.59 < 4-alpha
2. 4-alpha == 4-alpha
4-alpha < 4+test
3. 4+test == 4-+test
4+test > 4
4. 4 == 4

--

--

Michael Kutz

I've been a software engineer since 2009, worked in various agile projects & got a taste for quality assurance. Today I'm a quality engineer at REWE digital.