When a bundle is programmatically started, should dependencies also be started? - osgi

Here's the scenario:
I have a bundle 'BundleA' installed and started in an OSGi container. A new version of BundleA is available. BundleA is provisioned using Felix Bundle Repository. The new version of BundleA declares a new package level requirement on a package from 'BundleB'.
Before I update BundleA (using OBR's deploy()) I stop BundleA because I want all threads to stop running and the deactivator provides this ability.
When I perform a deploy() on BundleA, BundleB is also installed, as expected.
I then programmatically start() BundleA again, and BundleA starts. But BundleB is 'resolved', not 'active'. I can manually start BundleB and it works as expected.
Is this expected, related to a way I am programmatically calling OSGi API, or did something go wrong?

That's the expected default behavior.
You can enable automatic activation of bundles as soon as any class from them is loaded. In order to do so, you need to set the Bundle-ActivationPolicy: lazy header.
In Eclipse that's the checkbox "Activate this plug-in when one of its classes is loaded" in the Manifest editor on the Overview page.

The OSGi framework does not automatically start bundles. (It will restart previously started bundles on framework launch however.) The framework does not know anything about start dependencies between bundles and bundles should not require a certain start order. As Gunnar mentioned, you can use activation policy to trigger lazy activation but that will not do anything if you have not called start on the bundle with the lazy activation policy.

Related

Only activate OSGi component when an optional dependency is available

I have an OSGi bundle that declares an optional dependency on the org.osgi.service.subsystem package. It listens for the addition of a new Subsystem instance, using DS. However, this DS component activates even if the dependency is unavailable.
Is there a way to only activate this DS component if the optional dependency is available?
Basically, this DS component performs processing that is only relevant if there are actually subsystems present in the runtime. If there are none, and the class is not available in the runtime, this component should remain dormant.
As far as I know this is not possible. There is an even bigger problem that you bundle will not automatically bind to the optional package if it becomes available after you bundle resolved. You will have to refresh the bundle explicitly.
So the better solution in this case would be to move the component into a separate bundle that has a mandatory dependency on the subsystem package. It could then be installed together with the subsystem support.

Maintaining OSGi bundle's state manually

Is there any approach via we can maintain and control OSGi bundles' state manually via code?
I have a requirement where in I need to download, copy and install/activate/deactivate/delete OSGi bundles in run time environment.
Any help/references will be appreciated.
Thanks!
You install a bundle with BundleContext.install by supplying a URL or an InputStream. As result you get a Bundle. In Bundle you can then call start(), stop() and uninstall(). You get the BundleContext inside the Activator of any already existing bundle.
http://www.osgi.org/javadoc/r4v43/core/org/osgi/framework/BundleContext.html

Lazy activation of Eclipse plugins

I would like to know what is "Activate this plug-in when one of its classes is loaded" check-box in Eclipse manifest editor useful for.
I thought Eclipse always use "lazy initialization" approach. Does have this option a relation to the BundleActivator class of the plugin? is initialization something different to activation?
Here is a similar question, but I don't understand it entirely.
Ticking the box causes the following header to be set in the manifest:
Bundle-ActivationPolicy: lazy
I'll start with how "pure" OSGi deals with this. IF the bundle is started with the START_ACTIVATION_POLICY flag then the bundle enters the STARTING state but the activator's start() method is not invoked and a ClassLoader is not allocated for the bundle. The bundle stays in STARTING until, for whatever reason, a class needs to be loaded from the bundle. At that point a ClassLoader is allocated and the activator (if any) is instantiated and its start() method is invoked before the requested class is loaded.
However Eclipse layers additional semantics on the top. As background, Eclipse always tries to avoid starting bundles in order to keep its start-up time minimal. A very small core set of bundles is started by default (the list is in configuration/config.ini) and one of these is called the p2 "simpleconfigurator". The simpleconfigurator looks for bundles that have the Bundle-ActivationPolicy:lazy header and it starts them with the START_ACTIVATION_POLICY flag... therefore these bundles will be "lazily" started as described above.
The important point is that all other bundles that do not contain the header will not be started at all under Eclipse. They will stay in RESOLVED state, their activators will not be invoked, and if they contain any Declarative Services component they will not be loaded. This is because Declarative Services only ever looks at bundles that are in ACTIVE or STARTING state.
Therefore the main reason to use the header is if we want to write a bundle containing Declarative Services components that need to work under Eclipse.
In other environments there is no need to use the header. Most normal OSGi apps simply start all bundles, rather than trying to selectively start a subset of bundles. Note that this doesn't mean OSGi apps don't worry about lazy loading! Declarative Services already supports lazy loading without messing around with bundle class loading triggers. In my opinion Eclipse gets this wrong and has added unnecessary complexity to the bundle lifecycle. Nevertheless if you are running in Eclipse then you have no choice but to understand and work with its limitation.

What is the natural start order for package-dependent OSGI bundles (under Karaf)?

I have a problem on 2.2.8 version of Karaf (and most probably on the earlier versions too).
I'm going to use Karaf to host the system with dynamically deployed bundles. Bundles are deployed by users and i cannot know beforehand which are they.
I expect order of the BundleActivator.start() to exactly correspond to package dependencies between bundles (dependencies of import/export packages) and planning to expect that it will be safe to assume that bundle0 will be completely initialized before bundle1 is going to be started. But it is not so - it seems that BundleActivator.start() is invoked in a "random" order and disregards package dependencies between bundles.
Sample use-case, I have 3 libs
test-lib0 - defines testlib0.ITestRoot, exports testlib0 package
test-lib1 - defines testlib1.TestRoot implements ITestRoot, exports testlib1 package
test-lib2 - uses both libs, ITestRoot and TestRoot
When Karaf is started, i see following sample output in console
karaf#root> TestLib1Activator.start()
TestLib2Activator.start()
ITestRoot: interface com.testorg.testlib0.ITestRoot - 16634462
TestRoot: class com.testorg.testlib1.TestRoot - 21576551
TestLib0Activator.start()
but i expect it should be always in this order
TestLib0Activator.start()
TestLib1Activator.start()
TestLib2Activator.start()
ITestRoot: interface com.testorg.testlib0.ITestRoot - 16634462
TestRoot: class com.testorg.testlib1.TestRoot - 21576551
I'm attaching sample project for tests. Test case: after "mvn install" just move jars from ./deploy folder to the same folder of Karaf, trace messages should appear in console.
(Note: it may work correctly from the first attempt, try one more time then :))
Sample test project
http://karaf.922171.n3.nabble.com/file/n4025256/KarafTest.zip
Note: this is cross-post from http://karaf.922171.n3.nabble.com/What-is-the-natural-start-order-for-dependent-bundle-td4025256.html
In OSGi the bundle lifecycle is installed → resolved → starting → started.
Import-Package and Export-Package only influence when the bundle goes from installed to resolved. So the framework makes sure all bundles you import packages from are resolved before your bundle but then your bundle only goes to the resolved state. Then in a second step the activators are called. So you can not assume the activators are called in the same order. If you need some initializations before your testlib2 can work then you should use OSGi services.
So If I understood your case correctly then you testlib0 defines an interface, testlib1 implements it and testlib2 wants to use the implementation. So the best way to achieve this is to publish the impl as an OSGi service in testlib1 and reference this service in testlib3. You can then use the service with a ServiceTracker or with e.g. blueprint. I have a small example that shows this: http://www.liquid-reality.de/x/DIBZ . So if you do your case like in my example blueprint makes sure that the context of testlib2 only gets started when the service is there. It will even stop testlib2 when the service goes away.

OSGI Embedded Equinox - Bundle to access pojos not instantiated in osgi framework

I have a server side application and want to embed an osgi framework into for dynamic bundle loading.
Suppose I want to expose a QuoteImpl implementing IQuote(instantiated as part of the server container bootstrap/Spring) to be used by different Bundles.
Q1. Is there a clean way of exposing server-application instances to Bundles ? (btw because of legacy it is not possible to make server code into bundle :) and donot want to make entire application osgi'ed.
Tried exposing via a service and bundle to cast into an IQuote. Not sure I am doing it well but fails with unresolved compilation problems as IQuote resides in the core app projects as opposed to the bundle project. any ideas?
Yes the way to do this is with a service. The "host" application would publish the service and the bundles inside OSGi would consume the service in the normal way.
The key to get this working is that the service API (i.e. the package containing IQuote) must be exported by the host application through the system bundle exports. You can control this by setting the org.osgi.framework.system.packages.extra property when you create the embedded OSGi framework. I wrote a blog post on this subject that should help you get started (look for the heading "Exposing Application Packages").
You state that you have compilation problems. To fix those it's necessary to know how you have structured your projects and build system.
This is how I embedded Equinox OSGi runtime in my Java class. I suppose you could do the same. https://github.com/sarxos/equinox-launcher/blob/master/src/main/java/com/github/sarxos/equinox/Launcher.java

Resources