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

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.

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).

Branding Apache Felix web console

I am trying to brand a Apache Felix web console, but I am not able to find resource for the same. As per Apache Felix website,
Branding for the Web Console can be provided in two ways: By registering a BrandingPlugin service or by providing a branding properties files. The Web Console uses the branding from the BrandingPlugin service registered with the highest ranking.
But I am not understanding how to register a BrandingPlugin service? What and Jar files should I put? Is there any guidance or tutorial available for the same? If yes, can you guide me in this?
Since I am totaly getting confused with Apache Felix's website, since those documents are not clear on this.
You may find it helpful to do some background reading on OSGi services. OSGi provides a service registry, and most interactions in an OSGi environment are handled by registering and consuming services. It doesn't matter what jar file you put the service in; the only thing that matters is the interface name its registered under.
You can register services in lots of ways; programmatically from a BundleActivator, using Declarative Services (also known as SCR), and using Blueprint are some of the most popular patterns. Which one is easiest for you depends on how you're building your jars and what other OSGi facilities you're using. If you've already got an Activator the programmatic route may be the quickest way to get started; if you're using the Maven bundle plugin you may find SCR annotations easiest.
What you'll need to do is include an implementation of the 'BrandingPlugin' interface in a jar which gets started by your OSGi runtime, and register that implementation as an OSGi service. Once you've done this you should see that the Felix console discovers your BrandingPlugin implementation and uses it.

Is OSGi the right approach for us?

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.

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.

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.

Resources