How is the OSGi bundle start level defined?
I am using Apache felix and would like to persist the start level across framework executions. I do not anticipate a need to change the start level of a bundle very frequently at all an an entry in Manifest.MF seems the most sensible. I've to org.osgi.framework.startlevel but have not seen a practical example.
I am also using maven with the maven-bundle-plugin, if there is an elegant way to incorporate the start level in the POM that would be brilliant.
Bundles don't define their own start level at build-time; the administrator or agent that installs the bundle into the framework defines it.
The core framework defines a Start Level interface in section 8. Quoting:
The Start Level API provides the following functions:
Controls the beginning start level of the OSGi Framework.
Is used to modify the active start level of the Framework.
Can be used to assign a specific start level to a bundle.
Can set the initial start level for newly installed bundles.
The last two are relevant to your inquiry here. Section 8.3.4—Changing a Bundle's Start Level—indicates that the framework will store an assigned start level persistently.
If you're using Apache Felix, there are several ways you can install bundles and assign their start level, whether explicitly or by allowing them to inherit a default start level for installed bundles:
- Felix File Install (see the
felix.fileinstall.start.level
property, though it's not per-bundle)
- Felix Bundle Auto-Deploy (see the
felix.auto.install.<n>
property)
- GoGo Shell Command (see the
bundlelevel
command)
Also, see the felix.startlevel.bundle
property, which controls bundles installed through means other than those above.
As for setting a manifest property (such as with Maven at build time), there used to be a way to do this in Equinox—now deprecated—but there is no standard means for a bundle to indicate to the framework what its proper start level should be.
X,
I think there is an easier way to do what you're talking about. Currently, you are using the Felix OSGi implementation directly, which is very powerful. However, if you'd like the kind of granular control over bundle deployment, that's built into an OSGi container called Karaf. Think of Karaf as a car whose engine can be either Felix or Equinox. It something that rides on top of OSGi framework implementations and offers additional functionality. For example, Karaf provides a Provisioning mechanism. Deploying multiple bundles is called Provisioning. Because Provisioning isn't part of the OSGi spec, different OSGi containers implement provisioning in different ways. In Karaf, we do this through something called a features.xml file.
In a features.xml file, you identify a specific set of bundles you want deployed together. Then you name that group. In this file you can also identify the specific start order you'd like Karaf to deploy the bundes.
A word on OSGi start-orders. A bundle cannot be started until all mandatory wiring has occured. This means that you can define a start order, but OSGi takes this as guidances, not mandatory. For example, if you have a bundle A that requires an import of bundle b's "foo" package, you can tell the container to start A before B all you want. But it won't respect that order because in reality B needs to be started in order to A to start. Its ok though, the container knows (usually) what order to start bundles in.
The rub comes in the use of optional versus mandatory imports in a bundle. If your bundle imports b.foo, but that import is optional, the container will respect the bundle start order (A then B). But watch out, if A actually needs to import b.foo, but you've marked it as optional, A will start without Wiring to b.foo, and A will throw a ClassNotFoundException. This nasty little bug can occur when using the various packages in Spring.
To make your life easy, Spring does the majority of its imports as "optional". If a given spring bundle actually needs to resolve a dependancy before working and that import is marked as optional, your bundles will deploy sparodically. Of course,the fix for this is to create a bundle fragment that modifies the bundle imports to "mandatory", but that's really beyond the scope of your question.
I hope this clarifies things for you.
bundle.adapt(BundleStartLevel.class).setStartLevel(startlevel);