Maven seems to have the ability to indicate a range of versions such as <version>[1.2.3,)</version>
how does maven figure out what is a newer or older version when there is no consistent versioning scheme that all open source packages follow. For example
- junit
4.10
- slf4j
1.7.2
- Hibernate
4.1.7.Final
- Spring
3.1.2.RELEASE
How does maven figure what is an older vs. newer version of a package in maven? What if package uses letters as versions numbers something along the lines of A,B,C or A2,A2,A4 ... etc.
Is there supposed to be a standard official way to version packages in maven? Are common open source packages like spring and hibernate ignoring this versioning convention?
This is a test that was written directly against the ComparableVersion class from Maven.
This test asserts that the following versions are considered to be from lowest to highest by Maven:
Your assumption about using major/minor/incremtal/ etc. is simply wrong. The comparision is done in ComparableVersion which contains the implementation. The ctor will call
parseVersion(...)
which usesComparableVersion
which is stored as instance inDefaultArtifactVersion
and it's used during thecompareTo(..)
There are parts like
getMajor..
, etc. but those are not working correctly. This is the reason why will be marked deprecated.The information by Stehpen Collony is true for Maven 2 but not for Maven 3 anymore.
According to this reference, Maven requires that version be of the form:
The reference goes onto explain that you may "face issues" (particularly with Maven version ranges) if you work with artifacts that do not follow this versioning scheme. Looking at the Maven source code that is linked from the article is quite helpful.
Of the examples you've given, the Hibernate and Spring artifacts seem to deviate in their use of "
.
" rather than "-
" to separate the qualifier.Some experimentation on my part shows that
DefaultArtifactVersion
will parse the version numbers exactly as described above. That is, the Spring example given (3.1.2.RELEASE
) will be interpreted as:0
0
0
3.1.2.RELEASE
More importantly the comparison of two version numbers (if using Maven 3.0 or newer) is much more flexible. The version numbers are split into lists of items (where either
.
or-
marks the boundary between items, note that.
has a higher priority than-
). Comparison is then accomplished by taking each item in term and performing a natural order comparison. Hence3.1.2.RELEASE
will be seen as smaller than3.1.3.RELEASE
. Strings are compared too, hence3.1.2.RELEASD
will be seen as smaller than3.1.2.RELEASE
. There are some special strings that have special equivalents, for example3.1.3.a.1
will sort the same as3.1.3.alpha.1
However, while the comparison is more flexible in newer versions of Maven. The Version Range Boundaries are still evaluated using the Major:Minor:Incremental:Qualifier scheme, so if you are using version ranges the flexibility is less useful.
Since version 3.0, Maven uses a consistent system to compare version numbers for both individual versions and version ranges. The system now makes a lot of sense, once you've understood a few gotchas.
All comparisons are now done by ComparableVersion, which says:
This means that versions come out in the following order, which I think makes perfect sense, apart from 1.0-SNAPSHOT right in the middle:
1.0-beta1-SNAPSHOT
1.0-beta1
1.0-beta2-SNAPSHOT
1.0-rc1-SNAPSHOT
1.0-rc1
1.0-SNAPSHOT
1.0
1.0-sp
1.0-whatever
1.0.1
The main gotcha I found in all this is that
snapshot
comes afterbeta
orrc
, so you can't have a development version of1.0-SNAPSHOT
, then release1.0-beta1
or1.0-rc1
and have Maven understand that those are later.Also note that
1.0-beta-1
is exactly the same as1.0beta1
, and1.0
is exactly the same as1
or1.0.0
.Version ranges now work (nearly) the way you'd expect, too. For example,
[1.0-alpha-SNAPSHOT,1.0]
will find1.0-beta1-SNAPSHOT
,1.0-beta1
,1.0-rc1-SNAPSHOT
,1.0-rc1
,1.0-SNAPSHOT
or1.0
, preferring later items over earlier ones. This is fully supported bymvn versions:resolve
, M2Eclipse and so on.