Restlet converter registration in OSGI environment - osgi

We run Restlet 2.1 in an OSGi environment (Equinox) as bundle (ie. not as library within a bundle). The problem is that the Restlet Engine does not detect helpers (like converters) that are provided by Restlet extensions. Specifically, the EngineClassLoader#getResources() call does not return any result. The extensions are also deployed as OSGi bundles in the target platform.
Is automatic converter registration actually supposed to work within OSGi environments?

In fact, Restlet supports such feature thanks to a dedicated activator (see the Activator class in the package org.restlet.engine.internal).
This activator introspects bundles to find out the following things:
servers corresponding to registered servers
servers corresponding to registered clients
authenticators corresponding to registered clients
converters
Be aware that to use this feature, we must use the OSGi edition of Restlet since it's the only that has the MANIFEST file of the org.restlet bundle with the activator class specified. Otherwise you don't have to care about the bundle loading order...
Hope it helps you.
Thierry

Unless the Restlet-bundle explicitly imports the packages that contain the extensions (and I doubt it does, and it shouldn't), it wouldn't be able to load them, because bundles have isolated class-spaces.
A possible solution would be to provide the extensions as fragments attached to the Restlet-bundle. Thus, if you make it use the bundle-classloader (the documentation says this can be done by setting the Engines classloader), it would be able to load classes from the fragments.

Indeed it doesn't quite work for OSGi, as it depends on the ability to see the entire class space.
The way to do this in OSGi would be to use the service registry for the extensions, but that only works for OSGi aware libraries.
There is some help on the way: In the recently released OSGi 5 (Service Loader Mediator) there will be support to 'bridge' META-INF/services (I don't know if Restlet uses those, though) onto OSGi services, so 'legacy' libraries should work well within OSGi.
There is an implementation in Apache Aries called Spi-Fly. I looked at it briefly a while back. It might do the trick for you, it might not.

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.

Does javax.imageio.spi.ServiceRegistry work in an OSGi container?

Can anyone tell me definitively if a osgi bundle that contains code that calls
javax.imageio.spi.ServiceRegistry
to find a service (in META-INF\service) will find that service, if that service implementation is in another bundle.
I'm not finding any documentation that is specific about this. I'm using the felix osgi container. Any pointers would be gratefully received.
I suspect it does work and my problem lies elsewhere as I notice that in the xdocreport osgi bundle fr.opensagres.xdocreport.core, ServiceRegistry gets used here but maybe its not supported on all osgi containers?
Out of the Box, OSGi doesn't support this, you'll need to tweak your code a bit.
But there are tools around like Aries SPI Fly and Pax-Swissbox that support you
in using these SPI "services"
No, it doesn't. I think it will only discover services in the system class loader, so that is pretty useless for bundles.
There might be a workaround, this post is pretty helpful, although I doubt if it is of any use to your problem.
Also OSGi 5 will have support for it ('Service Loader Mediator'). The reference implementation is SPI Fly from Apache Aries
Hi thanks everyone for your answers.
I think ServiceRegistry will work in an osgi container to instantiate a service but only within the same classloader.
And that's facilitated by use of osgi fragments. So as long as the implementer is in a fragment that defines its Fragment-host as the bundle that contains the class that has the ServiceRegistry lookup code, then ServiceRegistry will work.
This is why it is working in the xdocreport code I linked to.
In this case the ServiceLoader code is called from an abstract class in fr.opensagres.xdocreport.core (a bundle), which is extended by concrete class in fr.opensagres.xdocreport.document (so the ServiceRegistry call is in fr.opensagres.xdocreport.document). The Service implementation is in fr.opensagres.xdocreport.document.docx. a fragment whose has defined its frament-host as fr.opensagres.xdocreport.document.
So fr.opensagres.xdocreport.document and fr.opensagres.xdocreport.document.docx use the same class loader...so it works!
In XDocReport we wanted have a modular API reporting to manage :
any document kind (docx, odt, pptx...). And you can implement your own document kind if you wish and register it via javax.imageio.spi.ServiceRegistry.
any template engine kind (Freemarker, velocity...). And you can implement your own template kind if you wish and register it via javax.imageio.spi.ServiceRegistry.
any converter type (docx->pdf converter with POI+iText, docx->xhtml converter with POI, odt->pdf converter with ODFDOM+iText, odt->xhtml converter with ODFDOM...). And you can implement your own converter if you wish and register it via javax.imageio.spi.ServiceRegistry (ex: implement docx->pdf converter with docx4j+FOP, docx->pdf converter with JODConverter, etc).
As you have understood, javax.imageio.spi.ServiceRegistry works on OSGi context because we use OSGi fragment (share the same classloader) and not OSGi bundle. We have done this choice to manage non OSGi and OSGi context both with the same code.
We have decided to use OSGi fragment and not OSGi bundle because :
if we use OSGi bundle, we need to develop an OSGi Activator to register our discovery (in this context bundle, javax.imageio.spi.ServiceRegistry doesn't work).
if we use OSGi bundle, you need configure the start level for each bundles which register discovery.
The only disavantage to use OSGi fragment is that you cannot use in your OSGi container several version of XDocReport template, converter, document. But is it a good feature for XDocReport?
You must not that javax.imageio.spi.ServiceRegistry works with JDK5 (and JDK6). JDK6 provides java.util.ServiceLoader which is new clas to regsiter services as javax.imageio.spi.ServiceRegistry.
in XDocReport we wish to support JDK5+JDK6. XDocReport 0.9.8 used only javax.imageio.spi.ServiceRegistry. But it seems that Google App Engine forbid the use of this class (see our issue 132). So I have developped for XDocReport 1.0.0 JDKServiceLoader to manage with Java reflection both java.util.ServiceLoader and javax.imageio.spi.ServiceRegistry for JDK5 and JDK6.
Regards Angelo

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.

Is separate OSGI bundles for api and implementation common practice?

I have a class with dependencies which I want to hot deploy without restarting the dependencies. The class has an interface but there's only one concrete implementation.
Initially I created a single bundle with exported the interface and registered the implementation using activator and implementation classes which were not exported. However, if I update the bundle, bundles which use the registered service get restarted after the update when PackageAdmin#refreshPackages is called (this is automatic when using fileinstall).
I have fixed this by creating a separate api bundle.
Is this the best way to achieve this?
Would you ever have a bundle which exports its api and includes the implementation in the same bundle. As far as I can see any give bundle would either export all its classes or no classes. What am I missing?
It is definitely a best practice to separate API bundles from their implementations in OSGi. If you do this, then any bundle that uses the API only needs to import classes from the API bundle, which can allow you to change implementations at runtime without restarting your dependent bundles.
Ideally your implementation bundle would implement the interface and export implementation as a service on the API provided interface. This allows the client bundles to utilize the service without referencing the implementation bundle.
In Apache Sling we do both: major APIs are in their own bundles, but for smaller things like extensions or optional components we often provide the default implementation in the same bundle as the API.
In the latter case, you can still allow for those default services to be replaceable, for example using service ranking values when you want to override them.
A bundle does not have to export all its classes, our bundles which include default services export just the API packages (and the default implementations are in different packages, obviously).
Unless there is a hard requirement to be able to replace implementation at runtime, without restarting client bundles, I would personally advocate keeping the explicit dependency link between API and implementation (either by including impl classes in the API bundle, or by having the API bundle import implementation packages from the impl. bundle).
The pb with the patterns suggested above is that they break the dependency chain. The benefits of dependency management go far beyond simple API compatibility, they also include ensuring predictable, consistent runtime behavior, as well as compatibility with the deployment ecosystem, and all of those require managing the implementation dependencies.

Resources