contexts. What happens when a module implements a new piece of functionality that
breaks existing behavior, either by design or as an unhappy accident? Some consuming
modules will want to pick up the new function, but others will need to stick with the old
behaviors. Coordinating this requires the module changes to be accompanied by a ver-
Let's go a step further. What if the updated module is consumed by several mod-
ules within the same system, some of which want the new version, and some the old
version? This kind of coexistence of versions is important in a complex environment,
and it can only be achieved by having versions as first-class properties of modules and
compartmentalizing the class space.
Versions, versions everywhere!
Versioning is incredibly important in OSGi. It's so important that if you don't supply a
version in your metadata, then you'll still have version 0.0.0! Another important point
is that versioning doesn't only apply to packages; OSGi bundles are also versioned.
This means that in a running framework you might have not only multiple versions of
the same package, but multiple versions of the same bundle as well!
The semantic versioning scheme
Versioning is a way of communicating about what's changing (or not changing) in
software, and so it's essential that the language used be shared. How should modules
and packages be versioned? When should the version number change? What's most
important is being able to distinguish between changes that will break consumers of a
class by changing an API , and changes that are internal only.
The OSG i alliance recommends a scheme called semantic versioning . The details
are available at http://www.osgi.org/wiki/uploads/Links/SemanticVersioning.pdf .
Semantic versioning is a simple scheme, but it conveys much more meaning about
what's changing than normal versions do. Every version consists of four parts: major,
minor, micro, and qualifier. A change to the major part of a version number (for exam-
ple, changing 2.0.0 to 3.0.0) indicates that the code change isn't backwards compatible.
Removing a method or changing its argument types is an example of this kind of break-
ing change. A change to the minor part indicates a change that is backwards compatible
for consumers of an API , but not for implementation providers. For example, the minor
version should be incremented if a method is added to an interface in the API , because
this will require changes to implementations. If a change doesn't affect the externals at
all, it should be indicated by a change to the micro version. Such a change could be a
bug fix, or a performance improvement, or even some internal changes that remove a
private method from an API class. Having a strong division between bundle internals and
bundle externals means the internals can be changed dramatically without anything
other than the micro version of the bundle needing to change. Finally, the qualifier is
used to add extra information, such as a build date.
Search WWH ::