16

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.

xconspirisist
  • 1,451
  • 2
  • 13
  • 26

3 Answers3

12

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:

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.

Community
  • 1
  • 1
seh
  • 14,999
  • 2
  • 48
  • 58
  • I am currently iterating over a each file in various directories, using Felix File Install. When I have "parsed" those directories I have all the bundles installed and ready to go. The problem is that they all have a start level of 1. This means an administrator would have to assign a bundle start level to each bundle manually to get the application running. I feel this isn't practical, can you include in your answer a technique to work around this? The end result would be when the framework is started it knows the start levels for each bundle without administrator interaction. – xconspirisist Sep 18 '11 at 15:47
  • 4
    It isn't practical to use FileInstall in a production application. I recommend you use a more stable and repeatable mechanism for installing bundles, e.g. by reading a configuration file containing a list of bundle locations with start levels. (Even better of course: stop relying on start levels altogether -- the fact that you have to use them usually indicates that you have done something wrong). – Neil Bartlett Sep 18 '11 at 19:35
  • Neil, thank you very much for your comment. What is preferred over startlevels and is there a standard format for a configuration file describing the bundles to load? – xconspirisist Sep 18 '11 at 19:38
  • 1
    @xconspirisist: Better than using start levels is... not using them ;-) .. More usefully, try to design your bundles so that start order does not matter. You don't say why you want to use start levels so I can't offer any more specific advice than that; I suggest posting more background information on this. – Neil Bartlett Sep 19 '11 at 01:22
  • Neil, these comments could go on for a little while. I had a look around your blog and see you are quite an authority on OSGi! I brought a book on OSGi and Felix and found quite a few questions answered within minutes. The modest section on start levels has answered my question. Thanks for your comments, I will accept the original answer. – xconspirisist Sep 19 '11 at 08:29
  • 2
    @Neil: why do you say using File Install isn't practical in a production application? – Richard Steele Sep 20 '11 at 18:12
8

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.

Mike Van
  • 1,048
  • 7
  • 26
  • 1
    Mike, thank you so very much for your additional comments, I found them quite insightful. Initially I thought this would be simple, my intention for using start levels was not to mitigate dependency issues but rather to implement a crude from of "run levels" to the system, much like you would find on linux. I recognize now from comments by yourself, Neil and seh that there are vast gaps in my OSGi knowledge that I need to fill in - before I continue with my grand vision for this super system! Thanks again. – xconspirisist Sep 21 '11 at 09:35
3
bundle.adapt(BundleStartLevel.class).setStartLevel(startlevel);
MatthiasG
  • 4,434
  • 3
  • 27
  • 47
Roland
  • 169
  • 2
  • 4
  • 2
    This could be explained better. Generally, human beings don't speak well in code. Especially if they don't understand the libraries being used. – Mike Van Jun 02 '16 at 20:59
  • This was a good suggestion. There are javadocs explaining it more. I used something like this in a bundle's activate method, which resolved my startup sequence problems. https://docs.osgi.org/javadoc/r4v43/core/org/osgi/framework/startlevel/BundleStartLevel.html – Cris Rockwell Jun 29 '20 at 17:04
  • If the call was bundle.getStartLevel().setStartLevel(startLevel), I don't think Mike would have had a problem understanding what's going one here! But instead the interface uses an "adapter pattern". If you don't understand that pattern, it's easy to be confused on what's going on. Here a link to a site that does a good job explaining the adapter pattern: https://refactoring.guru/design-patterns/adapter/java/example#:~:text=Adapter%20in%20Java%20Adapter%20is%20a%20structural%20design,format%20and%20interface%20recognizable%20by%20the%20second%20object. – Tom Rutchik Jun 10 '21 at 15:25
  • In Osgi, the use of the adapt method has the benefit of stopping the dependency chain. For example, if bundle had the method BundleStartLevel getStartLevel(), you'll find that the dependency on BundleStartLevel, would bring in such other dependencies such as BundleRevision, BundleWiring, etc. The adapt function stops the the dependency chain so you don't end up bring everything else in. – Tom Rutchik Jun 23 '21 at 19:43