The Source for Java Technology Collaboration
User: Password:



Stanley Ho

Stanley Ho's Blog

Versioning in the Java Module System (Part 2)

Posted by stanleyh on May 29, 2008 at 04:13 PM | Comments (5)

This is the second of two articles about versioning in the Java Module System. The first article was about version format and policies.

Version ranges

In the Java Module System, modules describe their dependencies on other modules, and on particular versions of those other modules. Versions and version ranges, like all syntactic elements, are fundamentally matters of taste, but we have tried in the Java Module System to make common versioning tasks easy and advanced versioning tasks possible.

First, the Java Module System (in the forthcoming JSR 277 EDR2) adopts the OSGi syntax for version range intervals. [ and ] mean the bound is inclusive and ( and ) mean the bound is exclusive:

    [1.2.3, 4.5.6)    ~ 1.2.3 <= x < 4.5.6
    (1.2.3, 4.5.6]    ~ 1.2.3 < x <= 4.5.6
    (1.2.3, 4.5.6)    ~ 1.2.3 < x < 4.5.6
    [1.2.3, 4.5.6]    ~ 1.2.3 <= x <= 4.5.6
All these intervals have the same meaning in the Java Module System as they do in OSGi.

Where the Java Module System differs from OSGi is in the interpretation of a single version. OSGi interprets a single version like 1.2.3 as "1.2.3 or greater" (OSGi R4.1 3.2.5). To get precisely version 1.2.3, you must write [1.2.3,1.2.3]. Adopting an implicit range is certainly concise, and use of exact versions is sufficiently rare that their [...,...] overhead is not too bad. But millions of programmers will first encounter versions via the Java Module System and it is best to adopt the simplest possible interpretation of any term. There is no doubt that someone seeing 1.2.3 for the first time thinks "exactly 1.2.3", so that is how the Java Module System interprets it. Ranges are denoted with explicit symbols. '+' means "or greater":

    1+        ~ [1, infinity)       ~ 1 <= x < infinity
    1.2+      ~ [1.2, infinity)     ~ 1.2 <= x < infinity
    1.2.3+    ~ [1.2.3, infinity)   ~ 1.2.3 <= x < infinity
    1.2.3.4+  ~ [1.2.3.4, infinity) ~ 1.2.3.4 <= x < infinity
'*' means any version in a particular release family:
    1.*      ~ [1, 2)            ~ 1 <= x < 2
    1.2.*    ~ [1.2, 1.3)        ~ 1.2 <= x < 1.3
    1.2.3.*  ~ [1.2.3, 1.2.4)    ~ 1.2.3 <= x < 1.2.4
Clearly, + and * in the Java Module System can express the same versions as intervals in OSGi, but without writing an ",infinity)" interval or adopting unintuitive "open versions" (1.2.3 == "1.2.3 or greater") to avoid the infinity interval.

The Java Module System also allows groups of ranges to be expressed, separated by ';'. These "union ranges" are separated by ';' because it works in command line expressions, unlike ',' and '&' !

    1.* ; [2.0, 2.7.3)                ~ 1.0.0 <= x < 2.7.3
    [1.2.3.4, 2.0) ; 2.* ; 3+         ~ 1.2.3.4 <= x < infinity
One feature you might expect are exclusive ranges, e.g. to express that the 2.5 product family was a disaster and should not be used. You might want to write:
   [1, 3) - 2.5.*
The Java Module System does not directly support exclusive ranges because it is easy to express them with union ranges:
   [1, 2.5)   ; [2.6, 3)
Or if you prefer to use a closed interval (this lets you avoid writing down the dreaded version 2.5):
   [1, 2.4.*] ; [2.6, 3)
Now suppose the problem is narrowed down from 2.5 to 2.5.1:
   [1, 3) - 2.5.1.*
You can express this with:
   [1, 2.5.1)   ; [2.5.2, 3)
or
   [1, 2.5.0.*] ; [2.5.2, 3)
Happily, the precision of the exclusion does not affect the length of the union.

The cardinality of the exclusion does affect the length of the union, so excluding two version ranges:

   [1, 3) - 2.5.1.* - 2.6.8.*
is expressible with:
   [1, 2.5.1)   ; [2.5.2, 2.6.8)   ; [2.6.9, 3)
or
   [1, 2.5.0.*] ; [2.5.2, 2.6.7.*] ; [2.6.9, 3)
The number of exclusive ranges, i.e. 2.5.1.* and 2.6.8.*, is the same as the number of ranges in the union. All the Java Module System really needs is unions (;) not exclusive ranges per se. Just as well, because taking the union of normal ranges and exclusive ranges could get pretty complicated.

In summary, we think it is reasonable for the Java Module System to let version numbers be version numbers, and introduce simple syntax (+, *) to denote ranges. Intervals work as they do in OSGi. Complex scenarios can use ; to group ranges and intervals.


Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • Stanley, did you consider allowing other qualifiers to the dependencies. Like "tested on", "should work with", "definitely won't work with", or even "has better performance with" qualifiers. That would allow for optimizing the dependencies based on the preferences by the user.

    Posted by: r_spilker on May 30, 2008 at 05:25 AM

  • I think it's a huge mistake to make depending on a single exact version to be the easiest thing to do. If your code really does work *only* with version 1.2.3, and neither 1.2.2 nor 1.2.4 will do, then it's quite right that OSGi makes you jump through a minor hoop to be explicit about that fact.
    Developers are lazy. If single version dependencies are the default then we will get a whole pile of libraries that have single version dependencies. Imagine the mess that will result. "What's that, you have version 1.2.15 of Log4J? Sorry, I only work with version 1.2.14. You'll just have to install both versions and partition your class space." Probably no application will work without multiple versions of every library it uses.
    Sure, the assumption that "x" means "x or above" is not perfect because sometimes a module will bind to a library version it can't handle. But defaults never can be perfect... the key is to choose the default that causes least harm.

    Posted by: njbartlett on May 30, 2008 at 03:16 PM

  • I have to say I like the +,*. It is clearly more intuitive without a lot of extra effort.

    Posted by: lstroud on May 31, 2008 at 06:18 AM

  • This JSR is turning into a philosophy class!! ... a debate of minutia. So much thought is going on to reinventing the wheel (i.e., versioning), and all the development is going on in private. Stanley, I don't think the public will give you a break until it appears the work is less secretive and less esoteric. And please, stop comparing against OSGi to show how this JSR uses so-called better conventions. Replicate what works.

    Posted by: paulusbenedictus on June 01, 2008 at 06:34 AM

  • The range syntax looks decent to me but I agree with paulusbenedictus that this discussion should be opened to the public using a discussion forum or something. The blog commenting system is not made for this sort of thing.

    Posted by: cowwoc on June 05, 2008 at 11:46 AM



Only logged in users may post comments. Login Here.


Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds