Java Reference
In-Depth Information
precise version of 1.0.0 on a package import, you would need to write
ver-
sion="[1.0.0, 1.0.0]"
. Specifying
version="1.0.0"
means any version
greater than 1.0.0.
But this import is pretty vague. The importer risks being broken by changes to the
food.experimental
that aren't backward compatible. To avoid this, the importer
should explicitly specify a minimum and maximum range as follows:
Import-Package: food.experimental;version="[0.0.0,1.0.0)"
But what's a sensible range? The rules of semantic versioning don't apply to versions
below 1.0.0. Some projects (including Apache Aries) treat all minor increments below
versions 1.0.0 as potentially breaking changes. One sensible upper range is
"[0.0.0,0.1.0)"
. On the other hand, when you release a new version of the
food.experimental
package, you may decide to reform your nonversioning ways, and
start on a clean slate with a sensible version of
1.0.0
. Neither an import of
"[0.0.0,1.0.0)"
nor
"[0.0.0,0.1.0)"
would be satisfied by a
food.experimental
package exported with version 1.0.0, even if nothing significant had changed. The net
effect of this ambiguity is uncertainty for importers of the package. They won't know
whether a change from 0.0.0 to 1.0.0 is a breaking change or a trivial change to move
to a versioned package. The easiest way to avoid all the confusion is to start off as you
mean to go on and give packages meaningful versions from the first release.
A.2.5
Consumers and providers, not clients and implementors
One of the most confusing things about semantic versioning is that it can't be boiled
down to, “I implement interface X, therefore I need a version range of [1,1.1).” This
is why we talk about
API
providers and consumers rather than any less generic terms.
A provider of an
API
isn't only the bundle that exports the package, but also any
bundle that provides a backing implementation for use by a consumer. A good exam-
ple here would be the Servlet
API
and a Web Container implementation (for example,
Jetty). The Servlet
API
bundle is clearly a provider, but less obviously, so is Jetty. This is
because consumers of the Servlet
API
(web applications, to the developer) expect the
presence of a Web Container as well as the
API
classes.
It doesn't normally take much of an effort for people to understand that providers
may not export the
API
they use, they can still fall back on the mental model that if
they implement an interface then that makes them a provider. Unfortunately, this
isn't correct! Once again the Servlet
API
provides a good example. Clearly a web appli-
cation is a consumer of the Servlet
API
, but web applications extensively implement
abstract classes and interfaces from the Servlet
API
. Try writing a functional servlet
without extending
Servlet
or
HttpServlet
. There are plenty more examples in the
Servlet
API
, but also in other
API
s.
To truly understand semantic versioning, you need to have a clear division
between
API
interfaces that are implemented or extended by a provider (for example
HttpServletRequest
), and ones that are implemented or extended by the consumer
(for example
HttpServlet
). If you add a method to an interface implemented by a