When to use ServiceLoader over something like OSGi
Asked Answered
K

2

19

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

Kenzie answered 24/12, 2009 at 22:53 Comment(0)
M
18

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.

Minervamines answered 24/12, 2009 at 23:30 Comment(2)
Thanks - always hard to really know what OSGi is. No I really only need what ServiceLocator has, and I appreciate that it is built in. I was just suspicious, having not heard of it before I thought it must be diseased or something.Kenzie
I use ServiceLoader on a current project, and the only frustrations I've found are 1) with the need to push extensions as Jar files onto the class path (our applications do not encourage end-user fiddling with the class path), and 2) the unspecified order by which sibling providers of the same service interface will be exposed to a consumer. The latter makes it hard to incorporate a "priority", such as that user-provided extensions should be preferable to the application's basic services. Hence, ServiceLoader is best used when providers won't overlap or compete with one another.Minervamines
L
5

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.

Lucid answered 28/7, 2010 at 19:32 Comment(4)
Can you elaborate on a simple abstraction for ServiceLoader that would make it easier to migrate to OSGi later. I currently have a framework that is split into 12 or 13 jar files that uses the serviceloader mechanism for the core component to 'scan' for modules on the classpath. I wish for the framework to play nicely in OSGi in the future but not to depend upon OSGi. So far, I can't see how to achieve the duality. Is it even possible to be half-in and half-out of OSGi when using the ServiceLoader mechanism?Vulture
The best abstraction would be something like dependency injection. In your code that requires some service "Foo", don't try to lookup that service but simply allow it to be injected through a setFoo() method. From some other class, make the call to ServiceLoader to get an instance of Foo and inject it into the code that needs it. If you later move to OSGi, simply scrap the second class and use Declarative Services or Blueprint to handle injection of OSGi Services.Lucid
What do you mean by "global visibility"? How can the lookup mechanism break in such a situation, for example in Java EE environment?Trustworthy
@Trustworthy This refers to the application classpath. If you use more than one class loader then services may not be visible from one module to another, depending on how you setup those classloaders.Lucid

© 2022 - 2024 — McMap. All rights reserved.