How to use dependent bundles in different container in Fabri8? - osgi

I am trying to understand the capabilities of Fabric8's container management.
I just want to clarify weather the following scenario can be achieved by using Fabric8 in JBossFuse.
I have created simple 2 bundles (tick, tock bundles inspired by the : http://kevinboone.net/osgitest.html).
Simply Tick bundle is exporting a package and Tock bundle is importing it. In another words, Tock Bundle depends on the Tick Bundle.
These 2 bundles are working perfectly when deployed in a single container (say in a one child container in JBoossFuse).
Then I have created a cluster by using the fabric8 and added its containers to the Fabric Ensemble as well.
And I have created 2 profiles. TickProfile contains the Tick bundle and Tock profile contains the Tock bundle.
I have deployed above 2 profiles in 2 different containers as follows,
Then it is not working properly because Tock bundle cannot resolve its dependency of Tick Bundle which is exposed by Tick Bundle (because those bundles are in two different containers).
I thought this is possible with fabric8 but it seems it cannot.
It would be really appreciated if someone can tell me whether there is any way of achieving this.
Thanks.

No this is not possible. Package export and import on OSGi level is bounded to the JVM. This means bundles in different JVMs will not be able to import each others classes.
The only OSGi concept that supports clustering are Services. The OSGi specification calls that Remote Services.
See: https://wiki.eclipse.org/Tutorial:_Building_your_first_OSGi_Remote_Service
Eclipse implementation: https://wiki.eclipse.org/OSGi_Remote_Services_and_ECF
Apache implementation: http://cxf.apache.org/distributed-osgi.html

Related

OSGI bundles and multiple jvms

osgi (equinox 3.6) framework while loading bundle creates bundle meta files in specified bundle directory . we are working on spawning multiple jvm's . Can we use bundle folder where my previous jvm has created ? I meant can we install all bundles once and use them for many applications?
It's a bit difficult to work out what you're asking... but it sounds like you want to share the OSGi storage directory between multiple separate OSGi frameworks running in different JVMs. This is not possible.
a) Yes you can share the same location URL among frameworks
b) You cannot share the framework bundle storage area/bundle cache (org.osgi.framework.storage property)
You know there is a special reference: schema for OSGi frameworks? This allows you to install frameworks quicker. Just prefix a URL with reference: scheme.
reference:file://....

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.

Is an OSGi service still "OSGi managed" when it's obtained by non-OSGi code?

As an OSGi newbie, I'm trying to wrap my head around the boundaries of the OSGi runtime. My app, which is not build on OSGi, i.e. it's not running in an OSGi container, starts an OSGi container into which we deploy OSGi bundles at run time. Some of these bundles register services. Later, in our non-OSGi code, we obtain those services and use them.
I'm having trouble wrapping my feeble mind around the OSGi boundaries here. To be specific, when I obtain a service and invoke one of its methods, can I assume that all of the subsequent execution is executing within the OSGi container (Felix)? In other words, are dependencies in that code resolved via the OSGi modularity mechanisms? Or did I lose that OSGi management because I am using the service from non-OSGi code?
If my question seems founded in obvious mistaken assumptions about OSGi, please feel free to point them out.
Chad, to more effectively answer your question, I'd like to know a few things:
1) How exactly are you getting the service reference from an external application?
2) Is the external application a stand-alone application, or is it inside of a different container? If so, there are ways to make that happen.
The question you pose is interesting. Lets put it into a context. Lets assume you are able to get a reference to an OSGi service from Felix by an external application. When you use this service, you will be interacting with it via an interface. In that interface in OSGi, you will have import statements referenced which will be used in the method signatures of the interface and also in any final attributes. These import statements will have thier matching dependant libraries defined in your pom.xml file.
In order to use the service by an external application, you will need to publish an API ".jar" file that will contain the interface, and will reference the interfaces' dependancies. Your external application will need to use that API, and will likely have it assembled into your .war, .jar, or .ear file's lib directory. Because of this, none of your external application's dependancies can conflict with your API dependancies.
As long as you can use the API, then you're right, none of the SPI's dependencies matter. You can use Spring 3.0.4.RELEASE in your external app and still use Spring 2.5.6.SNAPSHOT in your OSGi application. As long as the API doesn't have any dependancies that conflict with the external application, you should be ok. The trick here is that you need to put your interfaces into a minimal .jar file as your API, and then put your implementation details into an SPI. Your external ap will use the API, and inside OSGI, you will use both the API and SPI.
Please let me know if this helps.
If you can get the service, then the dependencies are satisfied by definition, because bundles cannot provide services unless their dependencies are satisfied. Executing services on the outside doesn't really change anything.

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

With OSGI how does one pass parameters from a host to a embedded bundle

In the end i will perhaps provide a helper so that the activator can import and export services and other types of meta data about the system.
By parameters i mean objects in general, perhaps via a map. it would be great if one bundle when installing another had a mechanism to send parameters to the starting bundle. I suppose i could include a service on the later bundle and use it as a configuration service but that seems a bit unelegant.
If you want to "send" some configuration parameters to a starting bundle you can use standard OSGi services like Configuration Admin Service. If you want to pass around arbitrary objects you should probably use OSGi service registry.
Could you please clarify your question? What you mean by "host" bundle and "embedded" bundle? What kind of "helper" do you want to provide? Most importantly what kind parameters you want to pass from one bundle to another?
To do (pre-) runtime configuration of a bundle, you should use the Configuration Admin Service. For pojos etc you can follow this pattern:
Bundle A installs and starts Bundle B
Bundle B registers a "configuration" service, e.g. with the interface acme.ConfigureB.
Bundle A tracks services with the interface acme.ConfigureB.
Whenever A receives the tracker callback for acme.ConfigureB it does all the necessary configurations.

Resources