When to use ServiceLoader over something like OSGi - java

Being someone who is allergic to dependencies, when would I use something like OSGi instead of the built in java 6 http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html (I want to let plugin jars just be dropped in).
(FYI this is in a scala app, open to any suggestions, ServiceLoader is pretty damn close to what I want).

If ServiceLoader mostly fits your needs, that says that you're looking for service discovery via the presence of files on the class path. That's only a small part of what OSGi provides.
OSGi will let you dynamically install bundles, advertise services, revoke advertisements, and uninstall bundles all while the application is running. Furthermore, as a consumer of services, you can look them up eagerly -- with filtering predicate queries -- and detect when offered service providers come and go. These bundles need not lie on the class path, and they can be provided in various forms; Jar files and "exploded directories" are the two I recall.
By contrast, ServiceLoader does just one thing: it exposes discoverable factories. Usually you'll create a factory-style interface that takes some argument to decide whether that provider can offer the appropriate service, such as mapping a given character set name to a CharsetDecoder. There's no formalized protocol for acquiring and releasing a service from such a provider. OSGi does formalize the binding and unbinding of consumers to services. The consumer can receive notification when new providers come online, and the provider can receive notification when a consumer acquires and releases a service instance. If this life-cycle control is important to your service and you forgo OSGi, you'll have to build this yourself; ServiceLoader doesn't go that far.
Alternately, rather than eager service lookup and use, you can take a more passive, declarative approach and let one of the OSGi dependency managers match your stated needs to the available service providers. There are many dependency managers to choose from. Spring Dynamic Modules is one of the most capable.
OSGi provides many other "middleware" facilities. I won't try to sell you on them here, as your question focuses mostly on what you'd be missing out on by choosing ServiceLoader.

As seh points out, if you're only interested in simple service discovery then ServiceLoader is a lightweight way to decouple consumers from providers. But it doesn't offer any assistance with composing services together.
For example, suppose service A needs to use service B. This is a "service dependency"... but what should A do if B is not available? In OSGi we can arrange that if B is not available then neither will A be -- assuming the dependency is mandatory; we can also support optional dependencies. On the other hand when using ServiceLoader, service A has no control over its availability so long as the JAR enclosing it is on the classpath... so it must provide its functionality even in the absence of required "back end" services.
Another thing to bear in mind with ServiceLoader is to try to abstract the lookup mechanism. The publish mechanism is quite nice and clean and declarative. But the lookup (via java.util.ServiceLoader) is as ugly as hell, implemented as a classpath scanner that breaks horribly if you put the code into any environment (such as OSGi or Java EE) that does not have global visibility. If your code gets tangled up with that then you'll have a hard time running it on OSGi later. Better to write an abstraction that you can replace when the time comes.

Related

What are the minimum requirements to get a CXF (JAX-RS) Web Resource up and running in Felix?

I'd like to get CXF, which implements JAX-RS, up and running in OSGI (specifically, Apache Karaf running Apache Felix).
Using this project: cxf-osgi-activator as an example, I see that the engineer made a design decision to split up the jetty Karaf feature from the jax-rs Karaf feature. Is there a dependency between the two at runtime? Does the jax-rs feature use some trick (from the environment: OSGI HTTP Service, for example) to get itself listening for inbound connections, or is that still needed? Maybe my question can be answered with an explanation of line 250 of the RestDeployer.java file. Where is it pulling its Server from exactly? Does it always get one, or does it have a dependency on the jetty Karaf feature?
I had a look at the tests, which seem to use iPojo or Declarative Services (hard for me to tell the difference!) to cut down on boiler plate code, but at the expense of understanding (because it requires more in-depth knowledge on the subject than I have at the moment it would seem.)
The official CXF documentation is less than desirable on this subject.
My understanding is that it boils down to having:
a web resource file annotated with JAX-RS annotations to map inbound calls to local functions
CXF runtime (some registration service that manages the lifecycle from reception of a call to return of serialized information)
a server (Java Servlet or effectively an abstraction thereof that spawns threads for a given port) Purpose of cxf-rt-transports-http-jetty
How does this all play together in OSGI? I should also mention that am most familiar with Gradle, and the Maven pom.xml files likely contain things that I do not recognize.
I do not like the accepted answer to CXF web services with OSGI and Karaf, because it is specific to Blueprint, which I do not want to use because of its reliance on XML. I am looking for a technical answer here that explains the relationship between CXF and OSGI (like the OSGI HTTP Service).
Related:
Apache CXF/JAX-RS, Felix and Jetty
Purpose of cxf-rt-transports-http-jetty
Firstly, a tiny recap about OSGi :
OSGi is a specification that needs to be implemented
Felix/Equinox are the two implementations found in karaf (see your etc/config.properties, with the property karaf.framework to check the one you use, you can change it !)
Karaf is an administration tool that will use Felix/Equinox behind each command you make. Often, those commands are proxied to the corresponding behaviour defined by OSGi to the Felix/Equinox implementation.
So, the solution you linked with Blueprint is still true no matter your context. However, if you don't like Blueprint, you can either check Declarative Services where each "bean" you would have defined in a "spring/blueprint" world would become #Service/#Reference (more pure to OSGi original way of thinking) or use OSGI CDI Integration which will be way more intuitive if you are used to the more classic #Named/#Inject way of thinking inside a bundle.
But in the end, it's exactly the same principles : you want to have a Server running registering itself to the CXF Bus (which normally you shouldn't declare in your bundle, you can use the default one) and your Service registering itself in Server.

Develop a simple plugin modular rest reachable service in Java

I want to develop a service that exposes a rest API to upload plugins and the plugins are locally executable, i.e. other classes from the server use them.
The plugins also:
The plugin should be a jar file that is submitted through the REST API and once is validated, is then made available through another API method to see the metadata and to execute.
Are not too complex (they should all contain at least a a class that extends of an abstract class or an interface implementation of an interface, the service) but could have their own dependencies.
The API allows to validate that the plugin is compliant with the service and that it declares some additional information on an XML or JSON file contained on the JAR.
Have some metadata that has to be exposed through the API (Version, who made it, is it usable, what data can it be handled) in Json form.
All implement an algorithm to perform some data crunch so they all have something like an execute() method. The result of executing this method is handled to another class, so is not totally important to expose it on the API.
Must be able to be uploaded and executed by the other server classes in runtime, so no restart is possible
The thing is that I am not sure where to start, since I had already developed some of the basic API on Spring-boot since it had all the things I needed to easily develop a REST API but the more I read about how to dynamically load modules (plugins) the more I see that Spring does not support this ind of thing and I am not sure a class loader or Service loader would work in that context.
I found out about OSGi framework but I honestly do not know it changing the whole technology stack will help me so I want to make sure it is the right answer, and if yes, then find some resources that point me in the right direction, e.g. some tutorial that implements something similar.
Thank you for any advice.
Checkout OSGi enRoute. It includes a model to developing RESTful services: http://enroute.osgi.org/services/osgi.enroute.rest.api.html.
OSGi sounds like the best match to what you try to do.
You can install everything as a bundle including your main application. Nowadays this is much less work than some years before but still not to be underestimated.
The other option is to start an embedded OSGi framework where you just install your plugins. This is less work but you need to know exactly how it works.
So for both cases I suggest to get help from an external OSGi expert as it speeds up the transition a lot and avoids many wrong paths you will choose as a beginner.

OSGi modules/bundles granularity

When I first started looking at OSGi I was under the impression that you could just build a JAR and as-long as it had a manifest file, you could deploy it in a OSGi container. I imagined building my modules in a classic way (maven), and maybe use some plugin or something of the sort to write the manifest, I could then have my module that would basically be a standalone application communicating with other modules through OSGi.
Further reading about OSGi, I'm beginning to see more examples of it being used at a more low-level and basically replacing dependency injection and providing cross-cutting concern services like logging. And seems that using things like hibernate or others, is a problem... (or maybe I'm just missing something).
At least for me, I don't really see the point of having a such fine-gained level of modularity and integration to OSGi, I would much rather have a separate modules, each one of them having its own set of technologies and frameworks, and possibly a web resources and persistence layer. Is this achievable with OSGi? If yes, can you point me in the right direction, examples etc.?
edit, added some more details of how I'm trying to use OSGi:
I'm just envisioning the possibility of having a more than one-class module, that might have a more higher-level responsibility.
Like say agenda module. In this case I want to have things like, persistence of the events, add events, list events with filters, etc...
This agenda might have several internal classes, and might even need a persistence layer. So I would like to use something like Guice to DI those classes, and some JPA to persist my data.
I can understand that some X-cutting concerns like server or logging can have a bundle, but the data model is specific to the agenda bundle. So I think my question was at the end What is and what is not possible to do inside a bundle? And what should and shouldn't be done inside as a general practice?
Thanks!
Mauricio
You can use OSGi without forcing any dependencies on OSGi on the application code. However, since OSGi provides modularity, the middleware (your layers) need to have some knowledge of OSGi. The problem is that in a modular world you want to hide implementation details, that is the whole purpose. However, things like Spring and Hibernate tend to assume the classpath has no boundaries and they run head on into the fences. Fortunately, more and more middleware is becoming prepared for this, I heard Hibernate now has an effort and JPA is also available in OSGi.
OSGi is many things to many people, and you can almost pick and choose what parts of it you want to use:
Do you have a plain library that doesn't use any other dependencies? Sweet, just put up a minimal MANIFEST.MF listing the public packages, use maven to build your JAR and you're done.
Do you have dependencies? Same as (1), you just add the imported packages in your manifest.
Do you need to perform some initialization? Write an Activator, and mention it in your manifest.
Services? Just put the dependencies and descriptions of those in XML files and add them in the manifest.
And so on - just use the level where you are comfortable.
On the other hand, if you want to do web applications you really need to consider the architectural interplay between OSGi, the libraries you use, your application manager and the servlet/jee/whatever container. At what level will OSGi reside? In a general sense, there are OSGi->container->app, container->OSGi->app and container->app->OSGi solutions, and each has their own idiosyncrasies.
Concerning building with maven, you can use the Maven-Bundle-Plugin it helps you to build OSGi bundles without having to write the manifest on your own. All the required meta information will be in your POM.
Dependency injection can be achieved on top of the module layer. One possible solution would be Declarative Services which enables you to inject via an XML description or code annotations. It strongly reflects the dynamic nature of OSGi Services (dynamic binding unbinding of services).
The alternative is Blueprint which is based upon spring and features a very similar syntax. One key feature is that it can abstract the nature of binding and unbinding of services. If you think about using Spring, use Blueprint.
OSGi only implies how you structure your modules. You get a well defined graph of module interactions (who imports/exports a package? Who exports Services and who uses it?)
therefore you can build an enterprise architecture on top of it by building cohesive bundles for every task.
OSGi is sometimes referred to as a service-oriented architecture for the JVM. Looking at bundles as modular units that provide services helps define the right granularity: you'll usually have API bundles which are just here to provide java packages that define APIs, service bundles that provide implementations of these APIs, and utility/auxiliary bundles that provide the cross-cutting services that you mention.
You can use some dependency injection frameworks on top of OSGi, but from my experience (with Apache Sling and Adobe CQ5) keeping things simple is often better. The OSGi Service Component Runtime and Configuration Admin provide all I need to manage services, dependencies and configurations, especially if you design your system for that from the beginning.
You can find a bit more about our experience with OSGi in designing Adobe CQ5 in my "tales from the OSGi trenches" slides at http://www.slideshare.net/bdelacretaz/tales-from-the-osgi-trenches-2012-short-form-edition - that might help get a better feel for how OSGi is used in building complex systems.

Using Spring without exposing the dependencies to the Client app

I'm writing a Java API for several clients, and would internally like to use Spring and it's several features, but I don't want to expose to the client my dependencies.
Is this possible?
So if my client uses a different version of spring would they be insulated from my internal Spring dependencies.
If so, would my spring dependencies be bundled internally inside my jar? As well as would a custom class loader be required by my client application?
I have heard you can use this through OSGI bundles, but I'm wondering if this would satisfy my requirement.
The clients of my API wouldn't be OSGI enabled or we have no current environment that utilizes OSGI bundles.
It is not really feasible, or desirable to do so. Why would you want to "hide" the dependencies? Would you also want to hide a dependency on whatever logging package you may be using (for example)?
If you have the dependencies in your implementation, then they are best published as it will cause a lot less grief on the part of users of your API since they will know what conflicts may exist before they even attempt to use your code.
Don't forget, your users are actually developers and I am sure that they would rather be aware of any landmines or requirements up front.
Edit - Regarding OSGi:
OSGi will definitely take care of your conflicting dependencies issues, but it also would rely on deploying in an OSGi environment, which you haven't mentioned is the case for your clients. In addition, it is still not recommended to "hide" those dependencies in a bundle. The very nature of OSGi allows those conficting depencies to cooexist in the same application.

Java IoC : distributed configuration

I'm building a J2EE application in which I want to allows plugins. I'm fairly convince of the goodness of IoC framework, and so the application will have one to manage services.
Now, I want to allows plugins to be added as simple JAR dropped in the classpath + perhaps a simple configuration file to edit to activate them, in no way something looking like Spring XML config files.
Most of the plugin architecture will be base around strategy/pipeline/chain of command patterns: for example the best plugin for an action is chosen by strategy, several plugins add filtering actions to an user input thanks to a pipeline, and so one.
So, I want to be able to:
define service interfaces in the core application,
set-up core implementation for extensible services with the chosen pattern in the main application,
let third party plugins register themselves in these hooks.
The first 2 points are quite easy, with or without IoC. The last one seems more complex without support at the IoC container level, or at least there is a lot of plumbing to do (how to manage classpath/sevice discovery, how to manage service orders in pipeline when the context change (new plugins), how to manage service overriding, etc).
I do know that Tapestry5 is great in that regards[1], but I can't find anything really relevant for Spring and Guice. And my company is more a String/Guice one than a T5 one (well, if I'm able to show that it's the best solution...)
So I'm wondering:
if I missed some obvious documentation;
if my requirement are so specials;
if an IoC container is not the right tool for that, and I should look for OSGi or something else.
Thanks for any tips !
[1] http://tapestry.apache.org/tapestry5.1/tapestry-ioc/configuration.html
I'm not sure how this would work with exactly what you're looking to do, but Guice's basic mechanic for handling plugins is Multibindings. How you handle discovery of plugins is up to you, but there are a variety of choices including scanning the classpath for implementations of plugin interfaces, having plugins provide a Module that adds their implementation(s) to the multibinder(s), using a config file that lists the plugin implementation classes, etc.
As the link mentions, you'd need OSGi if you need plugins to be addable at runtime with no restart.
Have you considered having a look at the Java EE 6 solution - CDI, implementation is named Weld based on JBoss Seam - which might be useful?
Once you start dropping in jars and their dependencies and then go though a couple of iterations of this with different plugins and different dependency versions, then you will start to feel the pain that many "application host containers" succumb to.
One possible solution to this problem is OSGi, although I did note a Tapestry blog highlighting the pitfalls of the OSGi approach:
http://blog.tapestry5.de/index.php/2010/01/19/tapestry-ioc-modularization-of-web-applications-without-osgi/

Categories

Resources