Search code examples
mavenversioningmaven-central

How does the Central Repository sort version numbers?


I maintain an open source project and publish its releases to The Central Repository. I just published oshi-core-2.6. The versioning in my pom.xml for that release reads:

<groupId>com.github.dblock</groupId>
<artifactId>oshi-core</artifactId>
<version>2.6</version>

My code requires Java 8 due to the Date/Time functions. To support a user's request, just prior to this release, I released a Java 7 compatible version using the threeten backport, with the following in its pom.xml:

<groupId>com.github.dblock</groupId>
<artifactId>oshi-core</artifactId>
<version>2.6-m-java7</version>

How Version Numbers Work in Maven states that "All versions with a qualifier are older than the same version without a qualifier (release version)." Another StackOverflow question, How does maven sort version numbers?, has an answer citing the ComparableVersion class which lists several well-known qualifiers (alpha, beta, milestone, rc, and snapshot) which are supposed to sort "earlier" than the ga/final (empty string) release.

Having been bit by having a custom qualifier in an earlier version, I tried to use the milestone qualifier (-m-) in my java7 version to indicate to Maven that it should be an "earlier" release than 2.6. However, searching the Central Repository shows that the -m- version is the "Latest Version".

Questions I have:

  • Why does the Central Repository sorting not match the documented sorting I've linked above?
    • Is it using an earlier version (pre-3.2) of Maven's sorting? If so, what consistent "Latest Version" sorting can I expect?
    • Does the hyphen in my artifact name have any impact?
  • Is there a better way of releasing the same version number in two formats than the way I have (obviously poorly) chosen?

Solution

  • This is a job for a classifier and not for that kind of weird version.

    • 2.6 with classifier: "jdk8" for JDK 8
    • 2.6 with classifier: "jdk7" etc.

    Furthermore the referenced document of Oracle was valid for Maven 2 but not for Maven 3.

    Apart from that I would suggest to increase the major version for such incombatible change based on semver.

    Furthermore you are referencing the ComparableVersion with alpha etc. is how Maven internally handles the versions. This can looked at the Unit test for that class.

    But you can check the behaviour of Maven via a little command line tool:

    java -jar apache-maven-3.3.9\lib\maven-artifact-3.3.9.jar 1.0.0 2.0.0
    Display parameters as parsed by Maven (in canonical form) and comparison result:
    1. 1.0.0 == 1
       1.0.0 < 2.0.0
    2. 2.0.0 == 2
    

    By using this you can see that Maven 3+ handles 2.6-m-java7 as greater than 2.6.

    java -jar apache-maven-3.3.9\lib\maven-artifact-3.3.9.jar 2.6-m-java7 2.6
    Display parameters as parsed by Maven (in canonical form) and comparison result:
    1. 2.6-m-java7 == 2.6-m-java-7
       2.6-m-java7 > 2.6
    2. 2.6 == 2.6
    

    So this is the reason why central also handles it as greater.

    So if you use things like rc or alpha you will see the result:

    java -jar apache-maven-3.3.9\lib\maven-artifact-3.3.9.jar 2.6-alpha 2.6
    Display parameters as parsed by Maven (in canonical form) and comparison result:
    1. 2.6-alpha == 2.6-alpha
       2.6-alpha < 2.6
    2. 2.6 == 2.6
    
    java -jar apache-maven-3.3.9\lib\maven-artifact-3.3.9.jar 2.6-rc1 2.6
    Display parameters as parsed by Maven (in canonical form) and comparison result:
    1. 2.6-rc1 == 2.6-rc-1
       2.6-rc1 < 2.6
    2. 2.6 == 2.6
    

    (The above CLI tool is available since Maven 3.2.5).

    The best solution is to have a module which produces your usual artifact. Making a supplemental module which contains the configuration for JDK 7 and there you can use "threeten backport" and create an other artifact. Those artifacts should have classifiers for such purposes.