Is OSGi the right approach for us? - osgi

We have to support at least 2 versions of functionality at the same time. It can be in the web side or services, meaning we'll have different layout for different users in the web or service implementation will be different for different users. We should be able to route the users based on their login to the right version of the web application / bundle.
We thought of something like this (please see bigger picture here http://i.stack.imgur.com/6NxhF.png).
Also is it possible to have multiple web applications / bundles deployed as one EBA? If yes, is it possible to share the session between these web apps / bundles? As we are new to OSGi, looking forward to any suggestion on the design we have chosen. Appreciate any help / suggestions on this.
Thanks,
Bab.

OSGi could be right for you. In my last project we had something equivalent to your approach. We've developed a backend system with OSGi where we had a backend connector as a starting point for different other bundles who wants to use functionalities of the backend. In your case the backend is your shared bundle context. We then had a SOAP webservice, several servlets and webpages (which should be OSGi based as well) which sends requests to the backend connector. Of course you can send request directly to internal bundles like your manager, but I would propose a layered architecture. In case of shared sessions: The question is which component is responsible for handling sessions? If you want to have not only web applications in your environment, you can manage sessions via a database or an inmemory approach. A 'SessionManager' bundle in your shared context is then responsible for creating user sessions (sessionid for identification), relating sessionid and temp data, getting data for sessionid and deleting temp data for sessionid. With this approach each client request should send the sessionid, which will be validate somewhere in your shared context. Then you dont need the web sessions. The created sessionid could be stored in a specific HTTP header entry of Request/Response for the communication. But thats only one approach.
Hopefully, all above makes sence to you. If not send me an email and we can discuss it more in depth. :) Sometimes pictures say more as a lot of sentences and I could draw some if you want. ;)
Greetings.
Christian

Yes, OSGi can help you a lot with this.
The architecture you have chosen looks fine, I would suggest perhaps also adding a 'SessionManager' as suggested by Christian.
Regarding the OSGi specifics you will need for this:
If you have two different versions of the "Services" bundle, which are packaged in the same Java packages, you should definitely define package versions when exporting them in the manifests:
In Services V1:
Export-Package: com.acme.foo;version="1.24"
and in Services V2
Export-Package: com.acme.foo;version="2.3"
You can then control which package is imported in the Web bundles by defining restrictions, e.g. like this for whole intervals:
Import-Package: com.acme.foo;version="[1.23, 2)"
The beauty of this is that due to the modularity of OSGi and the separate classloaders of the bundles both versions of com.acme.foo can be installed and used in the same system. You cannot achieve this in the "usual" Java setup, because there there is only one classloader and one version of the package will shadow the other.
You can see OSGi demos and examples for example here
This was about the packages and libraries.
Now about the actual service objects:
You could also have two versions of the same service published in the OSGi Service Registry. The easiest way to differentiate between the two is to use service properties when registering the service:
Hashtable properties = new Hashtable();
properties.put( "service_flavour",
"advanced" );
context.registerService(
SomeService.class.getName(),
this, properties );
You can then use the props to lookup the correct service in the Web bundles:
ServiceTracker someServiceTracker = new ServiceTracker(bc, "(&(objectclass="+SomeService.class.getName()+")(service_flavour=advanced))", null);
someServiceTracker.open();
Regarding your question about EBA - I am not sure what you mean. You can install as many bundles as you want in any OSGi framework, and they can all register under different aliases in the OSGi HTTP service. As long as the aliases don't have a conflict with each other it is ok. You can also have one main servlet if you want, and distribute the handling of the different pages to other bundles without registering them as servlets too - your main web servlet could look them up in the OSGi service registry for example, and distribute the work. It all depends whether you expect more application logic/calculations etc, or is it more about formatting and representation of some existing data.
Hope this helps.

Related

How do you call an OSGi application from a non-OSGi application, and vice versa

I am considering writing a new set of applications using OSGi, but they will need to interact heavily with existing non-OSGi applications.
To clarify, the new applications will need to call into existing non-OSGi code bases maintained by other teams (usually propriety services of varying protocols), and new non-OSGi applications will need to call the new OSGi services.
I am not seeing much documentation for how to do this.
Can someone please point me to the correct steps
It sounds like you want to embed OSGi into a larger application. A good starting point for this is a blog post I wrote some time ago: http://njbartlett.name/2011/07/03/embedding-osgi.html
The trick to creating visibility between OSGi bundles and the objects "outside" OSGi is to publish and/or consume services using the system bundle's BundleContext. The embedding code must be aware of the objects from the outer application that you want to make visible into OSGi, and it should publish them as services. Be aware that you need to export the service interface packages via the system bundle exports -- how to do this is described in the blog post.
OSGi services are only for communications inside the same JVM process. So I guess you want to communicate between processes. In this case you have all the usual remoting protocols like SOAP, Rest, RMI. On the OSGi side you can bridge from OSGi services to offering SOAP or REST endpoints using Distributed OSGi (DOSGi).

OSGi Services: Requesting a Bundle's/Component's Referenced Services

I’m currently “struggling” with OSGi services, or to be more specific, with the wiring between the services. I’m aware of the basics of DS, SCR and the general strategies for a component instance to acquire services. Anyway, here is my problem:
Following DS, components declare e.g. their provided and consumed services in a XML-file. In my case, I’m interested in the “consumed/referenced” services of a particular component (which are declared by the “Reference” tag in the component’s XML-file).
E.g. consider a running OSGi-application: a bunch of bundles collaborating with each other based on services (DS). Now, I want to pick a particular bundle and query all its references to the services it (may) consume - no matter if these services are currently available or not.
Referring to Apache Felix GoGo shell commands, like inspect requirements *, I do get information about the imported packages etc. but not a complete overview about the consumed services (-> both currently consumed services and services the component is waiting for).
I’ve read about the Framework API which provides insight in the registration, modification and deregistration of service but apparently, it does not provide the information about what services bundles are waiting for. Following the OSGi core specification, this could be achieved by a Listener Hook.
Isn’t there a way, where I just can query e.g. the SCR to get all referenced services of a specific bundle? Obviously, the SCR is supposed to read the bundle’s Service-Component-XML-file and to “register” some kind of “Service Tracker” to track the consumed/referenced services – hence the information of a bundle’s consumed/referenced services should somehow be available, shouldn’t it?
It would be great if you could help me with this.
Thanks,
Don
Checkout xray, http://softwaresimplexity.blogspot.com/2012/07/xray-again.html, from Peter Kriens.

Programmatically adding declarative services

Is it possible to add declarative services using some kind of api?
A little background:
I have a server application based on dynamic scripts (they can be added, edited or removed at any time).
Those scripts have dependencies to OSGi services and possibly each other. Whenever a script gets
edited, the script gets compiled to javascript, and its dependencies are detected.
At that point, I'd like to (re)register it as a declarative service, so it will be activated / deactivated when its
dependencies come and go.
Is this even possible? Or is there something major I'm missing?
If it isn't possible with an OSGi standard, is there a specific solution for Felix or Equinox?
Can you do that in the other frameworks, like iPojo or blueprint?
There is no API to imperatively add declarative services. You can use the normal OSGi api to register and use services. Perhaps that is what you want?
You may want to checkout the Dependency Manager which may provide an API model giving you the dependency support you want.

OSGi and Component Management

I have a dynamic application that uses OSGi to load modular functionality at runtime. OSGi bundles contain the modular functionality and the application loads the bundles when they are needed. This approach works okay, but I would like a more granular solution. The bundles contain components controlled through Declarative Services. I'd like to be able to load a bundle, and only enable the components that are needed within the bundle. I've done research in this area, but cannot find a solution that I'm satisfied with. One approach was to create a "gatekeeper" component that is always enabled in the bundle and through the ComponentContext let it call enable and disable component. It's a viable solution, but I could not figure out a way for the "gatekeeper" to "know about" the other components in the bundle without hard coding the component names as properties in the "gatekeepers" SCR xml descriptor.
What I prefer is a way to load bundles and "know about" all components within the loaded bundles. Be able to determine what bundle the components are located in and what state they are currently in (similar to the equinox console command 'ls' that lists out all components). I would like to enable and disable the components when needed.
How does the console do this and how could I do this in an application?
Update:
#Neil Bartlett: Sorry for the delay. I had to move on to something else. Now I'm back on this issue. Really would appreciate any further assistance. My application is role based. I need to enable components based on the functionality they provide. The goal is for all role based components to initially be disabled. Upon role change, a role manager polls each component for its provided functionality and determines whether to load it. Each component will broadcast what functionality it provides (through a common service interface). ScrService will not allow me to enable an initially disabled service component. Having the components initially enabled and let ScrService disable them as soon as possible during application startup does not fit my needs.
Have a look at ScrService. Bothe equinox and felix has it.
However, components can be made to load lazily, i.e. only when needed by other components/bundles; but that is perhaps not what you want.
In your service description, mark the components as enabled, but requiring configuration information provided by the Configuration Management service. you then can write a CM plugin service (can't remember the exact term) that can publish and modify the configuration of your components. Services by default are identified by their name, which by default is their implementation class name. Configuration data is passed as a map, and it can be empty. DS will make the service available as soon as the CM provides a configuration.
I have a similar issue, but for a different purpose:
- I have apache file install and configuration admin service to configure my components externally with property files.
- I needed to make sure that some components get the config from the outer file and the only way I've found so far is that I mark my components with ConfigurationPolicy.REQUIRED.
- But that way my plugin projects doesn't run in eclipse (where there are no config files).
- The component.xml also contains a default development configuration so I'm okay with that, just my component doesn't start until there is a config data avalilable with configadmin. My components ar unsatisfied this way, until someone creates a configadmin entry.
- I figured out that if I create a osgi command line extender that sends empty configurations to service pid's they would start up with default values in component.xml files.
- I just came here to find a way to list all bundles
But I think this solution I use can also work with your setup and that's why I write this.
Just mark all your components with the configurtationpolicy.require and you can selectively start and stop them with adding and removing configurations with configadmin. This could be hard if you already use the configadmin for other purposes too, but it may be managable as a last resort.

Auto updating a remote osgi instance (a swing gui)

I am planning to use osgi in a typical client-server (with swing gui) application. Hot deploying bundles to the server is made easy with fileinstall but now I am looking for something similar on the GUI.
The GUI is started with webstart but I want to update bundles without asking the user to close and restart.
I was planning to have a server side bundle which monitors a directory containing bundles, exposes the bundles over http and notifies the clients when something has changed. A client side bundle would listen for the notifications and do the bundle installs/updates using the methods on BundleContext and Bundle.
(Note: I already have an RMI like link between the server and clients which can be used for the notifications)
Is there anything which already does this or similar?
I would at least like to reuse fileinstall for the filesystem watching part but I don't want the GUI bundles started on the server.
P2 is a great provisioning system for OSGi based applications. Eclipse uses it, and there are a lot of uses even for non-OSGi applications. You should definitely have a look at it before you start building you own update system. You can also check Apache Ace.
The Fractal example for the Paremus Service Fabric may be instructive here ( https://docs.paremus.com/display/SF16/Demonstration ). In this example both Server and Client side OSGi bundles may be dynamically installed. RMI is also supported.
Regards
Richard

Resources