The build.gradle file of a project I'm working on contains the following line
implementation platform("com.example:fizz-buzz:0.0.1!!")
What do two exclamation marks, !!, following the version mean?
The search in https://docs.gradle.org/ does not return any useful results, nor does Google when searching for site:docs.gradle.com "!!"
Got the answer from a colleague :)
There is, however, a shorthand notation for strict versions, using the !! notation:
dependencies {
// short-hand notation with !!
implementation('com.example:fizz-buzz:0.0.1!!')
// is equivalent to
implementation('com.example:fizz-buzz') {
version {
strictly '0.0.1'
}
}
}
Simple version declaration semantics
strictly
Any version not matched by this version notation will be excluded. This is the strongest version declaration. On a declared dependency, a strictly can downgrade a version. When on a transitive dependency, it will cause dependency resolution to fail if no version acceptable by this clause can be selected. See overriding dependency version for details. This term supports dynamic versions.
When defined, overrides previous require declaration and clears previous reject.
Declaring Rich Versions
Related
Do Maven artifacts or their metadata deployed to a remote repository allow to reliably determine whether an artifact is a stable release?
Snapshots have the suffix SNAPSHOT, however there are also alphas, betas and pre-releases, and the naming is not necessarily consistent, e.g.:
5.0-alpha1
5.1-beta2
3.0.0-M5 (maybe this is actually a stable release?)
4.13-rc-2
5.7.0-RC1
https://mvnrepository.com highlights non-release versions differently, however maybe it is just looking for certain keywords?
(source)
See the POM Reference which has detailed explanations about version numbers beginning at section Dependency Version Requirement Specification:
If version strings are syntactically correct Semantic Versioning 1.0.0 version numbers, then in almost all cases version comparison follows the precedence rules outlined in that specification. [...]
[...]
When version strings do not follow semantic versioning, a more complex set of rules is required. [...] This gives a sequence of version numbers (numeric tokens) and version qualifiers (non-numeric tokens) with "." or "-" prefixes.
So, alpha1, beta2, M5, rc-2, RC1 are:
a) for „A pre-release version [...] denoted by appending an arbitrary string immediately following the patch version and a dash.“ according to point 4. of the Semantic Versioning Specification (SemVer),
b) all qualifiers for (pre-)releases, not snapshots, where M stands for milestone.
Content-wise you only can trust the artifact creator(s) that they took a proper qualifier that represents the actual status of the artifact.
I am using Maven 3.3.3 and want to express that I will accept any 2.7.x version of the jackson-core dependency (but am not willing to go to 2.8.x until I've had a chance to assess for backward compatibility, run unit / regression tests, etc.).
This would allow my project to receive bug fixes (under incremental versions), but delay the jump to the next minor version until ready.
I instinctively wrote the following into pom.xml:
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>[2.7.1,2.8)</version>
However, a mvn dependency:list says that the following version is used:
com.fasterxml.jackson.core:jackson-core:jar:2.8.0.rc2:compile
I was taken aback by that, however dug up this answer which leads to the "official" Maven Javadoc which describes the sort order of Maven dependencies.
Those helped me understand why 2.8.0.rc2 is considered "older" than 2.8.0.
So, I reasoned that the following would (albeit hack-ishly) produce the desired results:
[2.7.1,2.8.0.a)
I was wrong. The dependency:list now produces:
com.fasterxml.jackson.core:jackson-core:jar:2.8.0:compile
Same result with (or variations with -a):
[2.7.1,2.8.a)
All together, this seems to imply the following orderings:
2.8.0 < 2.8.0.a
2.8.0.rc2 < 2.8.0
So ... if everything I learned in school about transitive relationships is correct, then:
2.8.0.rc2 < 2.8.0.a
That seems to contradict the SO answer. At the same time, the Javadoc is ambiguous (i.e. is the qualifier ordering listed the actually implemented ordering) and this Apache Wiki / Confluence page is mildly confusing.
Regardless, it doesn't seem to line up with either String sorting or common sense that a "Release Candidate" (assumed meaning for rc would precede an alpha version specified as a).
Would this be handled differently if there an actual 2.8.0-alpha version had been released?
Bottom line: is there a reasonably transferable way to specify a Maven Version Range which excludes everything in the 2.8.0 version space?
Edit: Even more bottom line... is there a clearly documented and publicly available description of the Maven version ordering algorithm outside of their source code? It's hard to tell if the cwiki page is a desired spec or implemented (and certainly doesn't go to the level of detail we're exploring here) and the Javadoc seems to imply (but isn't unambiguous in stating so) the equality between . and - which comments here demonstrate is not the case.
You can simply check the ordering by using the following command:
java -jar apache-maven-3.3.3/lib/maven-artifact-3.3.3.jar 2.8.0.rc2 2.8.0.a
Display parameters as parsed by Maven (in canonical form) and comparison result:
1. 2.8.0.rc2 == 2.8.0.rc-2
2.8.0.rc2 < 2.8.0.a
2. 2.8.0.a == 2.8.0.a
You can also check the other version 2.8.0-alpha via:
java -jar apache-maven-3.3.3/lib/maven-artifact-3.3.3.jar 2.8.0.rc2 2.8.0-alpha
Display parameters as parsed by Maven (in canonical form) and comparison result:
1. 2.8.0.rc2 == 2.8.0.rc-2
2.8.0.rc2 > 2.8.0-alpha
2. 2.8.0-alpha == 2.8-alpha
Maven itself says there is no official documentation until this bug is resolved.
Further, given what is stated in comments on the original question, I am concluding that there is no 100% safe, transferable of stating version numbers in a range for a more permanent solution.
Practically, I suppose making assumptions would render either of these valid for most uses:
[2.7.0,2.8.-alpha.alpha)
[2.7.0,2.7.9999.9999]
But theoretically, there could always be a smaller (in the first case) or larger (in the second) version number of the artifact (note that 2.7.9999.9999.9 > 2.7.9999.9999).
Even with those assumptions, stating the range in either manner leaves a build accepting any 2.7.x version published which might (for example) be 2.7.1-rc2.
I know realize this was an implied premise in my original question. That is, asking to "receive bug fixes (under incremental versions), but delay the jump to the next minor version until ready" assumed that the "incremental versions" are only non-alpha, non-rc, etc. versions.
That premise is invalid. Providing "only unqualified versions (eg. maj.min.inc with no -qualifer)" does not seem to be a use case supported by Maven and is a separate question entirely.
I think I'm now firmly in the "Maven Ranges are Evil" camp... not as much for build reproducibility reasons as much as being able to control the quality / finality of the included artifacts.
My build complains about a missing dependency:
... requires bundle org.eclipse.ui [3.106.0,4.0.0)' but it could not be found
The used target platform points to a P2 location that includes the following JAR: org.eclipse.ui_3.106.0.v20140812-1751.jar
Still the build fails and raises the following two questions:
I thought 3.106.0.v20140812-1751 would be in the range [3.106.0,4.0.0), is that not true?
How does OSGi handle the fourth part of a version? If 3.106.0 is a valid version, then how is the suffix .v20140812-1751 understood by OSGi?
A link to a good explanation of OSGi versioning would also be highly appreciated.
I thought 3.106.0.v20140812-1751 would be in the range [3.106.0,4.0.0), is that not true?
Yes it is true.
How does OSGi handle the fourth part of a version? If 3.106.0 is a valid version, then how is the suffix .v20140812-1751 understood by OSGi?
The fourth part is just a segment like any other except that it is sorted alphanumerically rather than purely as a number. The specific algorithm is String.compare(), so you should read the standard JavaDocs for that method to get the full details. This segment is called the "qualifier"
In version 3.106.0.v20140812-1751, the qualifier is v20140812-1751. In the version 3.106.0, the qualifier is the empty string. As the JavaDocs for String.compare() will confirm, any non-empty string sorts after the empty string.
I am migrating from Maven3 to Gradle and I have an dependency on an internal project that includes some properties as version identifiers. When I try to compile my project, it complains about the dependency not found. The problem is these properties either use a period '.' or a dash '-' (e.g., cargo.version, supported-spring-version).
Is there a way in Groovy to declare a variable with odd characters?
def 'supported-spring-version' = '3.1.0.RELEASE'
You can't use def, but you can declare them in the current binding
this.'some-string' = '3'
println this.'some-string'
There's probably a better way round this though, but there's not enough information in your question to reliably suggest an alternative
I'm trying to figure out if what Maven's policy is on custom qualifiers. I know that there exists specific qualifiers in Version strings that maven checks for, such as:
1.0.0-SNAPSHOT
5.3.0-beta-5
etc, but I was wondering if I could write specific rules or something that could handle custom qualifiers, such as:
1.0.0-mybranch
5.3.0-myotherbranch
or how maven would deal with such version strings. I've tried them out and things seem to be ok, I'm just wondering if Maven has some custom logic that could be used.
Thanks!
These examples will work fine.
Qualifiers have no special meaning other than:
SNAPSHOT, which gets transformed into the correct timestamp / build number
solely numerical values, which are actually a build number instead of a qualifier (and considered newer than the corresponding base version)
All qualifiers are considered to be older than the associated release, i.e. 1.2-beta-1 < 1.2
Comparison of qualifiers is done as a string comparison. This behaviour can differ in Maven 2.x and Maven 3.x (in the former, 1.0-beta-10 < 1.0-beta-5, in the latter it behaves in the reverse as you'd expect).
The 2011 answer is now obsolete in many important details. See the Javadoc on https://maven.apache.org/ref/3.3.9/maven-artifact/apidocs/org/apache/maven/artifact/versioning/ComparableVersion.html and the Wiki link there for the current version processing logic.
c.f. How does maven sort version numbers? for commentary on the Javadoc for ComparableVersion.