Conceptually, what does it mean to “activate a bundle” in OSGi (e.g. what operations are done on a bundle to activate it). What happens, exactly?
If the bundle has a BundleActivator then the start method of it is called.
Frameworks like declarative services might also watch the bundle status and activate components declared in the bundle.
Related
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
I am reading "OGSi in Action" where in an interesting comment has been made :
"The module layer uses the metadata in bundles to make sure all their dependencies are satisfied before they can be used. This symbiotic relationship creates a chicken-and-egg situation when you want to use your bundles; to use a bundle you have to install it, but to
install a bundle you must have a bundle context, which are only given to bundles."
The book goes to great length in explaining bundle dependency resolution , but the "chicken and egg" scenario described above hasnt really been explored further. To install a bundle , BundleContext is needed, which is only provided to bundles. So who created the first "bootstrapping" bundle ? Is this contained in the "shells" that are provided (using packageAdmin?) ? PackageAdmin has
Bundle getBundle(Class clazz);
and Bundle can provide the BundleContext, but the bundle has to be installed first ... and so on !!
How does this work ?
See the Framework Launching API which provides the launcher with access to the system bundle's Bundle Context to install the "first" bundles.
From the javadoc of Bundle.getBundleContext():
If this bundle is not in the STARTING, ACTIVE, or STOPPING states or
this bundle is a fragment bundle, then this bundle has no valid
BundleContext. This method will return null if this bundle has no
valid BundleContext.
I do not know what the writer of the book thought about. If you install a bundle programmatically, you install it via the bundle context of other bundle.
With all my respect, I think this paragraph is wrong. This "chicken and egg" philosophical question could be raised in case of the system bundle. However, I do not think that answering the unnecessary question would give a better understanding for the reader, who wants to get started with OSGi.
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.
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.
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.