views:

260

answers:

3

I'm having a problem discovering services that are provided by some OSGi bundles that are not being activated. Let me describe the situation:

  • Bundle A defines interface X
  • Bundles B, C, and D provide services that implement interface X
    • These bundles' services are registered via Spring DM, so they are only created when the bundle is activated and Spring DM initialized the application context defined in the bundle
  • Bundle A is activated and at some point asks the service registry for services for interface X. It doesn't find any, because bundles B, C, and D haven't been moved into the ACTIVE state (they are only RESOLVED).

I cannot seem to get bundles B, C, or D to start, and therefore register their services. Forcing them to start by adding them to the config.ini is not an option, because there can be any number of bundles that are installed in the application (via an Eclipse p2-like update mechanism) that implement interface X.

The application is an Eclipse 3.5-based RCP app, using Spring 2.5.6 and Spring DM 1.2.1.

How do I force these bundles to be activated?

A: 

I think I've found the solution to this problem, though it feels a bit hackish.

I ran across this thread where Adrian Colyer implied that an external "bundle watcher" could be responsible for activating bundles when they are installed into the framework.

So, my solution was to:

  • Add a custom header to bundle B, C, and D's respective manifests, e.g., "MyApp-AutoStart: true"
  • Create a bundle listener that responds when a bundle is moved into the RESOLVED state, and looks for the header
  • If the header's value is "true," the bundle listener calls bundle.start()

Using this method, the bundles I want to be started are started without having to resort to using config.ini, and they can come and go as they please, but their services are available when queried.

Critical Failure
+1  A: 

What you really have is a dependency hierarchy problem, your proposed hacky solution is really just a band-aid over the underlying issue.

What you should really consider is the architecture of your system, as effectively what you have is a circular dependency (re: discussion in comments your original post). You have (like it or not) A requires services from (and in some sense depends on) B and C. Meanwhile, B and C directly depend on A, and as such, cannot start until A comes up.

In the best case, you can write code in B and C to listen for the existence of A, but this at best masks (as I mentioned) the underlying issue. What you should really consider is splitting A into two bundles, let's call them A1 and A2.

A1 should provide the interface which B and C require (depend on). A2 should have listeners for the services B and C depend on. At startup, if B and C are required services, A1 must be run, but A2 may start any time later, and everything should work.

Mark E
I'm going to try out your suggestion and see what happens. Thanks!
Critical Failure
A: 

Also have a look at felix fileinstall, which watches a directory for bundles and automatically installs and starts them. When a file is deleted, the bundle is stopped and uninstalled as well.

Leen Toelen