New Features for the Framework
What’s New in Core 4.3?
The OSGi Alliance has recently published the OSGi Service Platform Release 4 Core Specification Version 4.3. This update to the Core specification adds a number of new features to the OSGi Framework. Some of the new features are useful to application programmers while other new features are meant for systems programmers. Let's take a look at these new features.
Release 1 of the OSGi specifications came out in 2000, well before Java 5 introduced a number of new and useful language features. The OSGi Framework API looks a bit old fashioned in the absence of the use of any of these new language features. But Java Micro Edition (CDC-1.1/Foundation-1.1), based upon the Java 1.4 language and class libraries, is still a target platform for OSGi development. So to update the OSGi Framework API for Java 5 language features would mean abandoning the Java ME users of OSGi. The OSGi Alliance did not want to do that.
Instead, we took advantage of the undocumented compiler option -target jsr14 to allow the use of Java 5 generics in the API while still supporting the Java ME platform. Both javac from the JDK and the Eclipse Compiler for Java support this option in their current releases. Since enums and annotations require class library support which does not exist in Java ME, the OSGi Framework API does not use these language features.
The main place in the OSGi Framework API where generics are used is in the Service Layer APIs for type safety. Several methods have been overridden to take Class objects and the service related interfaces have formal types. So now one can use the Service Layer in a type safe manner.
The changes provide type safe references to OSGi services and avoid the need for explicit casts.
Capabilities and Requirements
OSGi bundles have always been able to export packages to, and import package from, other bundles. The resolver in the OSGi Framework has to match exporters to importers in order to resolve bundles for execution. For the Core 4.3 release, we have generalized this into the concepts of bundles offering capabilities to other bundles and bundles expressing requirements for a capability from another bundle.
We define a capability as a set of attributes (key/value pairs) in a namespace and a requirement as a filter expression over the attribute set of a capability in a namespace. The specification defines the built-in namespaces: osgi.wiring.package, osgi.wiring.bundle and osgi.wiring.host, to represent the existing concepts of exporting and importing packages, requiring bundles and being a fragment respectively. For example, within the osgi.wiring.package namespace, an export package is represented by a capability and an import package is represented by a requirement.
The idea of generic capabilities and requirements is also added. This allows bundle programmers to define their own namespaces so a bundle can provide a capability with the new Provide-Capability manifest header and have a requirement for a capability with the new Require-Capability manifest header.
These requirements become additional constraints to the resolver in the OSGi Framework and are visible in the new Bundle Wiring API (Figure 1).
A bundle cannot be resolved unless its mandatory requirements can be satisfied by a capability from some bundle. The built-in namespaces cannot be used on the new Provide-Capability and Require-Capability manifest headers).
In addition to the built-in namespaces, the specification defines the new osgi.ee namespace to replace the org.osgi.framework.executionenvironment framework launching property and the Bundle-RequiredExecutionEnvironment manifest header. Now bundles can use the Require-Capability manifest header to declare a requirement in the osgi.ee namespace on the execution environment. Frameworks can be configured with the new org.osgi.framework.system capabilities and org.osgi.framework.system.capabilities.extra framework launching properties to provide capabilities in the osgi.ee namespace representing the current execution environment. This will result in the system bundle providing the specified capabilities which can then satisfy the requirement from a bundle.
Bundle Wiring API
The PackageAdmin framework service was introduced by Release 2 in 2001. Using a service to supply framework function was an important choice at the time. It enabled additional function to be added in an optional manner so resource constrained systems could implement the OSGi Framework without implementing the PackageAdmin service. It also avoided adding methods to the core framework types such as Bundle which would only be interesting to systems programmers. But the cost of this design choice was an API that is not very object oriented since you have to pass the Bundle objects to the methods. Ten years later, today’s resource constrained systems are much bigger, and we also find that the PackageAdmin service does not well model the actual wiring of bundles in the Framework.
In 4.3, we introduce the new Bundle Wiring API which replaces PackageAdmin and provides a much richer model of the wiring relationship between bundles. Instead of using a service to deliver the new API, the API is available via the new, type safe adapt method on Bundle. To learn about the wiring state of a bundle, adapt the Bundle object to the desired bundle wiring type. For example:
Whenever a bundle is installed or updated, a new revision of the bundle is created. A BundleRevision for a bundle contains information about a specific revision of the bundle such as the symbolic name, version and declared capabilities and requirements. The most recent revision of a bundle is called the current revision and can be obtained by adapting the bundle to the BundleRevision type.
Whenever a bundle is resolved, a new wiring of the bundle is created. A BundleWiring for a bundle contains information about a specific wiring of the bundle, such as the capabilities and requirements that are wired together. The wiring can also be used to scan the class path of a bundle and to obtain the class loader of a bundle. The most recent wiring of a bundle is called the current wiring and can be obtained by adapting the bundle to the BundleWiring type (Figure 2).
If a bundle has been updated, older revisions and wirings of the bundle may still be in use. All the available revisions of a bundle can be obtained by adapting the bundle to the BundleRevisions type (Figure 3).
The system bundle can be adapted to the FrameworkWiring type which provides access to framework wide wiring operations. Using the FrameworkWiring object, bundles can be resolved and refreshed. Refreshing a bundle will result in the non-current revisions and wirings to be released by the Framework. The removal pending bundles, that is, the bundles which have non-current revisions and wirings, can also be obtained. All of these operations are very useful for management code (Figure 4).
While PackageAdmin has been deprecated and replaced by the Bundle Wiring API, framework implementations will still implement the PackageAdmin service for some time to come to support existing bundles that use the PackageAdmin service.
- Capabilities and Requirements
- Start Level API