OSGi 4.3 brings some Generics and Capabilities
At EclipseCon 2011, the next release of the core OSGi platform were announced and made available as a public final draft, with the released document happening in the near future. BJ Hargrave gave a presentation on what's new in OSGi 4.3, which sums up the key differences between it and previous releases.
One of the most anticipated features is the addition of generics to the core OSGi API. This allows type-safe operations to look up (say) services of a specific type, instead of having to do casts. However, since OSGi needs to run on embedded (pre-1.5) VMs, it was not possible to use a 1.5 compiler to build the core APIs. Instead, a largely forgotten option,
-target jsr14 allows Java code with generics to be compiled but run on a 1.4 compatible JRE. This option was originally introduced as part of the transition for Generics in JSR 14, but still exists in today's compilers. This permits client code (compiled against either 1.4 with
-target jsr14, or 1.5 and above) to refer to services such as:
// OSGi 4.2 way // ServiceReference ref = context.getServiceReference( // LogService.class.getName()); // LogService log = (LogService)context.getService(ref); // OSGi 4.3 way ServiceReference<LogService> ref = context.getServiceReference( LogService.class); LogService log = context.getService(ref);
However, since the core is not fully Java 1.5 then other features (such as
enum and annotations) have not been used.
The traditional unit of dependency in an OSGi environment is either package or bundle dependencies (through
Require-Bundle). Although these dependencies work fine for code, they are not very good at representing non-code dependencies. For example, a bundle might need a certain amount of memory or the presence of a webserver, neither of which may be represented as a specific package or bundle.
OSGi 4.3 introduces the notion of generic capabilities, which can be used with
Provide-Capability. Non-optional capability requirements must be satisfied before a bundle can be resolved. A typical use-case for this is for the provision of OSGi Declarative Services, which aren't represented as a package dependency but may still be required in order for a bundle to be resolved correctly.
In addition, the minimum required version can be exposed as a capability requirement:
// Old way // Bundle-RequiredExecutionEnvironment: JavaSE-1.6 // New way Require-Capability: osgi.ee;filter:="(&(osgi.ee="JavaSE")(version>=1.6))"
As a result of this generalisation, the
Bundle-RequiredExecutionEnvironment has been deprecated (but still available) in OSGi 4.3.
OSGi Remote Services aren't new (they were chapter 13 in OSGi 4.2 compendium) but they have been promoted to the OSGi 4.3 Core specification. As a result, all OSGi 4.3 runtimes will have support for Remote Services.
Some services, like
PackageAdmin, were used to provide meta information about a bundle but without polluting the bundle's interface with type-specific accessors. This typically resulted in boiler-plate code to find out how a bundle was wired up, or what its start level was.
To simplify matters, OSGi 4.3 introduces an
adapt(Class) method on
Bundle. Much like Eclipse's IAdaptable pattern, this allows a
Bundle to be converted into known type. In essence, if the bundle knows how to convert itself into the given type, an instance will be returned; if not (or permissions prevent it) then
null is returned instead. This simplifies
StatLevelAdmin as follows:
BundleWiring wiring = bundle.adapt(BundleWiring.class); // wiring.getRequirements(null) BundleStartLevel bsl = bundle.adapt(BundleStartLevel.class); // bsl.getStartLevel()
The existing services will remain but general users are encouraged to use the new adapt pattern for ease of implementation.
Weaving support has also been formalised, which permits extensions to plug into the class loading mechanisms of other bundles. This technique is used by some runtime systems – particularly those implementing JPA or other database backed persistence stores – in order to create code used specifically for that particular class type. The Weaving hook allows a standard mechanism to be in place for OSGi frameworks, which previously used a provider-specific mechanism.
Nested frameworks no more
Although a trial implementation has been available in Equinox for a while, the nested frameworks support (where a framework can launch nested versions) has not been put forward as part of the 4.3 specification.
Instead, a more powerful
ResolverHook API has been created, which allows an extension to create virtual sets of bundles to hide bundles from one another. This follows the
ServiceHook which has been previously available which allows services to be hidden from others.
It is thus possible to emulate nested frameworks by creating bundle groups who cannot see each other. This has been used to implement the new Virgo region model has been reworked to support this new model.
A side effect means that it's now possible to install multiple versions of the same bundle/version pair in the same framework, provided that these are hidden from each other. Previously, it would be an error to attempt to install the same bundle a second time. This won't be enabled by default, but it will be possible to mark a bundle as being capable of doing this with an attribute
org.osgi.framework.bsnversion=multiple in the properties when launching framework. By default, it is set to
The new OSGi specification will bring a number of useful features for the framework; for those bundles which don't need to support older frameworks, the use of the new generic API is likely to be a big reason for switching over. The nested frameworks and weaving is unlikely to have a direct effect, but those implementing lower level libraries will switch over to using standardised hooks, which will increase the platform interoperability between different OSGi frameworks.
The specification is not yet officially released, but is expected to be available prior to this year's Eclipse release, since Equinox 3.7 is likely to be declared the reference implementation.
Actually what has moved to the core specification is Chapter 13 of the compendium, which contains only declarations and properties. That means that any OSGi bundle can declare a service as remoteable, or e.g. create a filter that excludes remote proxy services, without pulling in the compendium spec bundle.
In order to actually make services remote, you will still need a remoting agent such as Eclipse ECF, Apache CXF or Paremus Nimble RSA. These agents are not moving into the core and never will.
InfoQ Sep 01, 2015