New Features for the Framework

What’s New in Core 4.3?

BJHargrave
What-s-New-in-Core-4-3

OSGi Director of Technology, Peter Kriens, and Senior Technical Staff Member at IBM, BJ Hargrave, look at the latest OSGi spec.

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.

For example:

Becomes:

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.

     
   

Start Level API

The StartLevel framework service was
introduced by Release 3 in 2003. Like the PackageAdmin service, it
was also provided as a framework service as a way to add function
to the Framework that could be optional and not complicate the core
types. But this design, like PackageAdmin, was not very object
oriented.

 

In 4.3, with the introduction of the
adapt method to Bundle, we introduce the new
Start Level API which replaces the StartLevel framework service. To
inspect or modify the start level information for a bundle, the
bundle can be adapted to the BundleStartLevel type. To
inspect or modify the start level information for the Framework,
the system bundle can be adapted to the
FrameworkStartLevel type (Figure 5).

 

While StartLevel has been deprecated
and replaced by the Start Level API, framework implementations will
still implement the StartLevel service for some time to come to
support existing bundles that use the StartLevel service.

 

Weaving Hooks


Bytecode weaving is becoming very
popular particularly in enterprise applications such as those using
JPA. There has long been interest in bytecode weaving in OSGi but
there has never been an OSGi standard way to do it. In 4.3, we
introduce Weaving Hooks.

 

Weaving Hooks are services
registered by bundles that are prepared to weave the class files
loaded from other bundles. Whenever the Framework is preparing to
load a class from a bundle, it first calls the weaving hooks to
give them an opportunity to mutate the class file for the class.
The Framework will create a WovenClass object for the
class being loaded and call the WeavingHook services in
service ranking order.

 

Each weaving hook will have the
opportunity to mutate the byte array containing the class file of
the class to be loaded. Since it is quite common for a weaver to
add code which may call classes which are not originally used by
the bundle, for example, tracing or logging APIs, the weaver needs
to be able to modify the woven bundle’s wiring so the bundle can
access these classes. So the WovenClass object lets the
weaving hook add DynamicImport-Package entries to the
bundle’s wiring. These entries can refer to the packages which
contain the classes used by the newly woven class. Once all the
weaving hooks have been called, the Framework will put the new
DynamicImport-Package entries into effect and call the VM
to define the woven class (Figure 6).

Since weaving hooks can modify
classes from other bundles, care must be taken in developing and
deploying weaver bundles to ensure the integrity and security of
the system.

 

Resolver Hooks


In previously released drafts for
Core 4.3, there were specification proposals for Composite Bundles
and virtual frameworks. These proposals were attempts at defining a
grouping model for bundles such that bundles in a group would be
able to share packages and services while bundles outside the group
would have more limited access.

 

Both of these design proposals have
been replaced in the final Core 4.3 specification with the
introduction of Resolver Hooks and Bundle Hooks. The Resolver
Hooks, along with Bundle Hooks and Service Hooks, provide low level
primitives upon which grouping policies for bundles can be
implemented. Using these hooks allows different grouping policies
to be created rather than specifying a single grouping policy into
the Framework.

 

A ResolverHookFactory is a
service that is registered by bundles that wish to influence the
Framework’s resolver and how it wires bundles together. For each
resolve operation, the Framework will call the
ResolverHookFactory services, in service ranking order,
requesting a ResolverHook object that will be used for the
duration of the resolve operation. Each resolver hook object will
be called and given the opportunity to influence the resolve
operation by restricting the bundles that can be resolved and which
candidate capabilities can be used to satisfy a requirement (Figure
7).

 

So, while a resolver hook can’t
actually make the decisions about how the bundles are wired
together, it can influence the choices the resolver can make. This
allows a resolver hook to create a grouping policy for bundles with
respect to how the bundles can be wired. Using the new Resolver
Hooks, the Service Hooks introduced by 4.2, and the new Bundle
Hooks, a complete grouping model can be implemented.

 

Since resolver hooks can modify how,
and even if, bundles are resolved, care must be taken in developing
and deploying resolver hooks to ensure the integrity and
reliability of the system.

 

Bundle Hooks


The Service Hooks introduced by 4.2
and the new Resolver Hooks are important parts of implementing a
grouping policy for bundles. With Resolver Hooks you can place
limits on how bundles are wired together at resolve time. With
Service Hooks you can place limits on what services are visible to
a bundle. The missing piece is how to limit which bundles are
visible to a bundle. This is the purpose of the newly introduced
Bundle Hooks.

 

Bundle Hooks are services registered
by bundles that are called by the Framework, in service ranking
order, when the Framework must decide whether a bundle can observe
another bundle. Two bundle hooks are defined. The Find Hooks are
called by the Framework during the processing of the
getBundle(long) and getBundles() methods of
Bundle-Context. These methods are used by bundles to find
other bundles. A FindHook is able to remove bundles from
the result set thus preventing the calling bundle from observing
the removed bundles.

 

The other bundle hook is the Event
Hook. The Event Hooks are called by the Framework during the
delivery of Bundle Events. An EventHook can remove bundles
from the set of bundles whose listeners would receive the bundle
event. This prevents the removed bundles from observing the Bundle
Event (Figure 8).

 

Bundle Hook implementations must
take care to ensure that bundles consistently observe or don’t
observe other bundles. That is, with the Event Hook, a bundle
should see either all or none of the life cycle events for a
bundle. Seeing only a partial set of events can result in undefined
behavior for the  observing bundle.

 

Summary

Version 4.3 of the Core
specification is another incremental improvement over past
specifications. The basic abstractions of OSGi: modularity, dynamic
life cycle and services, all continue as before. These new features
add to the level of introspection and control of the Framework.

 

Some of the new features enable new
and powerful capabilities to be built upon the Framework. Take care
if you decide to use these low level features since they can have a
significant effect on other bundles.

 

At the OSGi Alliance, we are
continuing to work on new specifications and enhancements to the
existing specifications. If you have input or want to participate
in the effort, please check out the OSGi Alliance
website
for information on joining the OSGi Alliance or
providing feedback.

Author
BJHargrave
BJ Hargrave is a Senior Technical Staff Member at IBM with over 20 years of experience as a software architect and developer. His focus is small computer operating systems (kernels, file systems, development tools, application binary interface specifi cations) and Java technology. He holds multiple patents related to Java and is the IBM expert and lead architect for OSGi technologies. BJ holds a Bachelor of Science in Computer Science from Rensselaer Polytechnic Institute and a Master of Science in Computer Science from the University of Miami. BJ has been a leader in the development of the OSGi technology since its inception and was named an OSGi Fellow in 2002 for his technical contributions and leadership in the OSGi Alliance. He is currently CTO of the OSGi Alliance and chair of the OSGi Core Platform Expert Group. BJ is also a committer on the Eclipse Equinox project.
Comments
comments powered by Disqus