A key aspect of the OSGi general dependency model based on requirements and capabilities is the concept of a Namespace. A Namespace defines the semantics of a Requirement-Capability pair. The generic model is defined in the [3] Resources API Specification. This section defines a number of Namespaces that are not part of the OSGi Core Release 8 specification. Unless an attribute is specifically overridden, all Namespaces inherit the attributes and directives of the default Namespace as defined [4] Framework Namespaces Specification.
Each Namespace is defined with the following items:
-
Name - the name of an attribute or directive
-
Kind - Defines where the attribute or directive can be used
-
CA
- Capability Attribute -
CD
- Capability Directive -
RA
- Requirement Attribute -
RD
- Requirement Directive
-
-
M/O - Mandatory (
M
) or Optional (O
) -
Type - The data type
-
Syntax - Any syntax rules. The syntax refers in general to the syntaxes defined in [5] General Syntax Definitions and [6] Common Headers.
In general, capabilities in a Namespace are versioned using Semantic Versioning. See [7] Semantic Versioning. Therefore, a capability will specify a single version and a requirement will specify a version range. See osgi.extender Namespace for an example.
For some Namespaces, capabilities are not versioned using Semantic Versioning. The versioning scheme used in those Namespaces will be described in the specification for the Namespace.
An Extender is a bundle that uses the life
cycle events from another bundle, the extendee, to
extend that bundle's functionality when that bundle is active. It can use
metadata (headers, or files inside the extendee) to control its
functionality. Extendees therefore have a dependency on the Extender that
can be modeled with the osgi.extender
Namespace. The
definition for this Namespace can be found in the following table and the
ExtenderNamespace class.
Table 135.1 osgi.extender Namespace
Name | Kind | M/O | Type | Syntax | Description |
---|---|---|---|---|---|
osgi.extender |
CA |
M |
String |
symbolic-name |
A symbolic name for the extender. These names are
defined in their respective specifications and should in general
use the specification top level package name. For example,
|
version |
CA |
M |
Version |
version |
A version. This version must correspond to the specification of the extender. |
Specifications for extenders (Blueprint, Declarative Services, etc.)
should specify the values for these attributes. Extenders that provide
such a capability should list the packages that they use in their
specification in the uses
directive of that capability to
ensure class space consistency. For example a Declarative Services
implementation could declare its capability with the following manifest
header:
Provide-Capability: osgi.extender;
osgi.extender="osgi.component";
uses:="org.osgi.service.component";
version:Version="1.3"
A bundle that depends on a Declarative Services implementation should require such an extender with the following manifest header:
Require-Capability: osgi.extender;
filter:="(&(osgi.extender=osgi.component)(version>=1.3)(!(version>=2.0)))"
Extenders can extend an extendee bundle even if that bundle does not require the extender, unless the extender's specification explicitly forbids this. It is recommended that an extender should only extend a bundle if one of the following is true:
-
The bundle's wiring has a required wire for at least one
osgi.extender
capability with the name of the extender and the first of these required wires is wired to the extender. -
The bundle's wiring has no required wire for an
osgi.extender
capability with the name of the extender.
Otherwise, the extender should not extend the bundle.
The Framework provides a number of hooks that allow groups of bundles to be scoped. For example, the Subsystem Service Specification. An extender may want to extend the complete set of bundles installed in the Framework even when extendee bundles are hidden from the extender. The system bundle context provides a complete view of the bundles and services available in the Framework even if Framework hooks are used to scope groups of bundles. The system bundle context can be used by an extender to track all bundles installed in the Framework regardless of how Framework hooks are used to scope groups of bundles. This is useful in scenarios where several scoped groups contain bundles that require an extender. Instead of requiring an extender to be installed in each scoped group of bundles, a single extender that uses the system bundle context to track extendees can be installed to extend all scoped groups of bundles.
Products or technologies often have a number of related APIs consisting of a large set of packages. Some IDEs have not optimized for OSGi and requires work for each imported package. In these development environments using modularized systems tends to require a significant amount of manual effort to manage the imported packages.
The osgi.contract
Namespace addresses this IDE
deficiency. It allows a developer to specify a single name and version for
a contract that can then be expanded to a potentially large number of
packages. For example, a developer can then specify a dependency on Java
Enterprise Edition 6 contract that can be provided by an application
server.
The osgi.contract
Namespace provides such a name and
binds it to a set of packages with the uses constraint. The bundle that
declares this contract must then import or export each of the listed
packages with the correct versioning. Such a bundle is called a
contract bundle. The contract bundle must ensure that
it is bound to the correct versions of the packages contained within the
contract it is providing. If the contract bundle imports the packages
which are specified as part of the contract then proper matching
attributes must be used to make sure it is bound to the correct versions
of the packages.
Additionally, the osgi.contract
Namespace can be used
in cases where API is defined by parties that do not use Semantic
Versioning. In those cases, the version of the exported package can be
unclear and so it is difficult to specify a meaningful version range for
the package import. In such cases, importing the package
without specifying a version range and specifying a
requirement in the osgi.contract
Namespace can provide a way
to create portable bundles that use the API. OSGi has defined contract
names for a number of such APIs. See [2] Portable Java Contract Definitions for more
information.
An osgi.contract
capability can then be used in the
following ways:
-
IDEs can use the information in the
uses
directive to make all those packages available on the build path. In this case the developer no longer has to specify each package separately. -
During run time the
uses
clause is used to enforce that all packages in the contract form a consistent class space.
The uses
directive will make it impossible to get wired
to packages that are not valid for the contract. Since the uses constrains
enforce the consistency, it is in principle not necessary to version the
imported packages on client bundles since only the correctly versioned
packages can be used. Contracts are aggregates and therefore make clients
depend on the whole and all their transitive dependencies, even if the
client only uses a single package of the contract.
The recommended way of using contracts is to create a contract
bundle that provides the osgi.contract
capability and imports
the packages with their required version range. For example:
Provide-Capability: osgi.contract;
osgi.contract=JavaServlet;
version:Version=2.5;
uses:="javax.servlet,javax.servlet.http"
Export-Package:
javax.servlet; version="2.5",
javax.servlet.http; version="2.5"
A contract may support multiple versions of a named contract. Such a contract must use a single capability for the contract name that specifies a list of all the versions that are supported. For example, the JavaServlet 3.1 contract capability would be specified with the following:
Provide-Capability: osgi.contract;
osgi.contract=JavaServlet;
version:List<Version>="2.5,3.0,3.1";
uses:=
"javax.servlet,
javax.servlet.annotation,
javax.servlet.descriptor,
javax.servlet.http"
Export-Package:
javax.servlet; version="3.1",
javax.servlet.annotation; version="3.1",
javax.servlet.descriptor; version="3.1",
javax.servlet.http; version="3.1"
A client bundle that requires the Servlet 2.5 contract can then have the following manifest:
Require-Capability: osgi.contract;
filter:="(&(osgi.contract=JavaServlet)(version=2.5))",
Import-Package:
javax.servlet, javax.servlet.http
The client bundle will be constrained by the contract's uses constraints and automatically gets the correct packages. In this example, no semantic versioning is used for the contract because the Servlet Specifications do not use semantic versioning (version 3.0 is backward compatible with 2.X).
In this model it is even possible to use the normally not recommended DynamicImport-Package header with a wild card since also this header is constrained by the uses constraints. However, using a full wildcard can also dynamically import packages that are not part of the contract. To prevent these unwanted dynamic imports, the exporter could include an attribute on the exports. For example:
Require-Capability: osgi.contract;
filter:="(&(osgi.contract=JavaServlet)(version=2.5))"
DynamicImport-Package:
*;JavaServlet=contract
However, this model requires the exporter to specify an agreed attribute. The contract bundle does not require such coordination; it also allows the package exporters to reside in different and unrelated bundles.
The definition of the osgi.contract
Namespace is in the
following table and in the ContractNamespace class. See [2] Portable Java Contract Definitions.
Table 135.2 osgi.contract Namespace
Name | Kind | M/O | Type | Syntax | Description |
---|---|---|---|---|---|
osgi.contract |
CA |
M |
String |
symbolic-name |
A symbolic name for the contract. |
version |
CA |
O |
Version+ |
version |
A list of versions for the contract. A contract that supports multiple versions must use a single capability with a version attribute that lists all versions supported. |
uses |
CD |
O |
String |
|
For a contract, the standard uses clause is used to indicate which packages are part of the contract. The imports or exports of those packages link these packages to a particular version. |
As the osgi.contract
Namespace follows the versioning
of the associated contract, capabilities in this Namespace are
not semantically versioned. The associated
contracts are often versioned using marketing or other versioning
schemes and therefore the version number cannot be used as an indication
of backwards compatibility.
As a result, capabilities in the osgi.contract
Namespace use a discrete versioning scheme. In such
a versioning scheme, each version is treated as separate without any
implied relation to another version. A capability lists
all compatible versions. A requirement only selects
a single version.
The Service Namespace is intended to be used for:
-
Preventing a bundle from resolving if there is not at least one bundle that potentially can register a specific service.
-
Providing a hint to the provisioning agent that the bundle requires a given service.
-
Used as template for specifications like Blueprint and Declarative Services to express their provided and referenced services in the Repository model, see the Repository Service Specification.
A bundle providing this capability indicates that it can register such a service with at least the given custom attributes as service properties. At resolve time this is a promise since there is no guarantee that during runtime the bundle will actually register such a service; clients must handle this with the normal runtime dependency managers like Blueprint, Declarative Services, or others.
See the following table and the ServiceNamespace class for this Namespace definition.
Table 135.3 osgi.service Namespace
Name | Kind | M/O | Type | Syntax | Description |
---|---|---|---|---|---|
objectClass |
CA |
M |
|
|
The fully qualified name of the object class of the service. |
* |
CA |
O |
* |
* |
Custom attributes that will be provided as service
properties if they do not conflict with the service properties
rules and are not private service properties. Private properties
start with a full stop ( |
The Implementation Namespace is intended to be used for:
-
Preventing a bundle from resolving if there is not at least one bundle that provides an implementation of the specified specification or contract.
-
Providing uses constraints to ensure that bundles which require an implementation of a specification or contract will be wired appropriately by the framework.
-
Providing a hint to the provisioning agent that the bundle requires a given specification or contract implementation.
-
Used as a general capability Namespace for specifications or contracts to express their provided function in the Repository model, see the Repository Service Specification.
A bundle providing this capability indicates that it implements a specification or contract with the specified name and version. For example, the Asynchronous Service Specification would provide the following capability:
Provide-Capability: osgi.implementation;
osgi.implementation="osgi.async";
version:Version="1.0";
uses:="org.osgi.service.async"
See the following table and the ImplementationNamespace class for this Namespace definition.
Table 135.4 osgi.implementation Namespace
Name | Kind | M/O | Type | Syntax | Description |
---|---|---|---|---|---|
osgi.implementation |
CA |
M |
|
|
The symbolic name of the specification or contract.
The OSGi Working Group reserves names that start with
" |
version |
CA |
M |
|
|
The version of the implemented specification or contract. |
* |
CA |
O |
* |
* |
Custom attributes that can be used to further identify the implementation |
The Unresolvable Namespace is intended to be used to mark a bundle as unresolvable:
-
Preventing the bundle from resolving since it is intended for compilation use only and is not intended for runtime use.
-
Providing a hint to the provisioning agent that the bundle must not be included in a provisioning solution.
For example, a bundle that must be unresolvable at runtime can include the following requirement:
Require-Capability: osgi.unresolvable;
filter:="(&(must.not.resolve=*)(!(must.not.resolve=*)))"
The filter expression in the example above always evaluates to
false
.
See the UnresolvableNamespace class for this Namespace definition.
Contract Namespace Package Version 1.0.
Bundles should not need to import this package at runtime since all the types in this package just contain constants for capability and requirement namespaces specified by the OSGi Working Group.
-
ContractNamespace
- Contract Capability and Requirement Namespace.
Contract Capability and Requirement Namespace.
This class defines the names for the attributes and directives for this
namespace. All unspecified capability attributes are of type String
and are used as arbitrary matching attributes for the capability. The values
associated with the specified directive and attribute keys are of type
String
, unless otherwise indicated.
Immutable
The capability attribute contains the Version
s of the
specification of the contract. The value of this attribute must be of
type Version
, Version[]
, or List<Version>
.
Extender Namespace Package Version 1.0.
Bundles should not need to import this package at runtime since all the types in this package just contain constants for capability and requirement namespaces specified by the OSGi Working Group.
-
ExtenderNamespace
- Extender Capability and Requirement Namespace.
Extender Capability and Requirement Namespace.
This class defines the names for the attributes and directives for this
namespace. All unspecified capability attributes are of type String
and are used as arbitrary matching attributes for the capability. The values
associated with the specified directive and attribute keys are of type
String
, unless otherwise indicated.
Immutable
The capability attribute contains the Version
of the
specification of the extender. The value of this attribute must be of
type Version
.
Service Namespace Package Version 1.0.
Bundles should not need to import this package at runtime since all the types in this package just contain constants for capability and requirement namespaces specified by the OSGi Working Group.
-
ServiceNamespace
- Service Capability and Requirement Namespace.
Service Capability and Requirement Namespace.
This class defines the names for the attributes and directives for this namespace.
All unspecified capability attributes are of one of the following types:
-
String
-
Version
-
Long
-
Double
-
List<String>
-
List<Version>
-
List<Long>
-
List<Double>
and are used as arbitrary matching attributes for the capability. The values
associated with the specified directive and attribute keys are of type
String
, unless otherwise indicated.
Immutable
The capability attribute used to specify the types of the service. The
value of this attribute must be of type List<String>
.
A ServiceNamespace
capability should express a
uses constraint for all the
packages mentioned in the value of this attribute.
Implementation Namespace Package Version 1.0.
Bundles should not need to import this package at runtime since all the types in this package just contain constants for capability and requirement namespaces specified by the OSGi Working Group.
-
ImplementationNamespace
- Implementation Capability and Requirement Namespace.
Implementation Capability and Requirement Namespace.
This class defines the names for the attributes and directives for this namespace.
This class defines the names for the attributes and directives for this
namespace. All unspecified capability attributes are of type String
and are used as arbitrary matching attributes for the capability. The values
associated with the specified directive and attribute keys are of type
String
, unless otherwise indicated.
Immutable
The capability attribute contains the Version
of the
specification or contract being implemented. The value of this attribute
must be of type Version
.
Namespace name for "implementation" capabilities and requirements. This is also the capability attribute used to specify the name of the specification or contract being implemented.
A ImplementationNamespace
capability should express a
uses constraint for the
appropriate packages defined by the specification/contract the packages
mentioned in the value of this attribute.
Unresolvable Namespace Package Version 1.0.
Bundles should not need to import this package at runtime since all the types in this package just contain constants for capability and requirement namespaces specified by the OSGi Working Group.
-
UnresolvableNamespace
- Unresolvable Capability and Requirement Namespace.
Unresolvable Capability and Requirement Namespace.
This class defines the names for the attributes and directives for this namespace.
This class defines the names for the attributes and directives for this
namespace. All unspecified capability attributes are of type String
and are used as arbitrary matching attributes for the capability. The values
associated with the specified directive and attribute keys are of type
String
, unless otherwise indicated.
Immutable
An unresolvable filter expression.
This can be used as the filter expression for an UnresolvableNamespace requirement.
@Requirement(namespace = UnresolvableNamespace.UNRESOLVABLE_NAMESPACE,
filter = UnresolvableNamespace.UNRESOLVABLE_FILTER)
Namespace name for "unresolvable" capabilities and requirements.
This is typically used as follows to prevent a bundle from being resolvable.
Require-Capability: osgi.unresolvable;
filter:="(&(must.not.resolve=*)(!(must.not.resolve=*)))"
[1]Specification Referenceshttps://docs.osgi.org/reference/
[2]Portable Java Contract Definitionshttps://docs.osgi.org/reference/portable-java-contracts.html