News: Using the ServiceLoader API to build modular applications
Talios has written "Using the ServiceLoader API to build modular applications," discussing how he used a facility in Java 6 - the ServiceLoader API - to build a modular application without OSGi, Guice, or other third-party module systems. The ServiceLoader API has been in Java since 1.2, although it was defined as part of the Jar file specification as the Service Provider API. The Java 6 version looks far easier to use - and Talios says that he still has to look at OSGi or alternatives since he's stuck on Java 1.4.
- Posted by: Joseph Ottinger
- Posted on: March 12 2007 11:12 EDT
- Re: Using the ServiceLoader API to build modular applications by Marius Danciu on March 13 2007 07:17 EDT
- Re: Using the ServiceLoader API to build modular applications by Michael Dowling on March 13 2007 12:53 EDT
- Successes with the pattern by Brian Sayatovic on March 13 2007 12:57 EDT
- ServiceLoader vs Spring lightweight plug-ins by Bryant Harris on March 13 2007 14:07 EDT
- ServiceLoader API considered harmful by random fletch on March 14 2007 07:01 EDT
This is a very thin concept of pseudo-plugin. Once JSR 277 is finalized and included in Java 7 people would probably forget about ServiceLoader.
I'm hard-pressed to convince the tech-junkies that this will work instead of adding a bunch of Spring dependencies and writing an XML file that does the same thing. Problem is for alot of people that you have to have the CLASSPATH in control and understand a bit of Classloaders with sun.misc.Service. Also, the API and the Implementation JARs must be seperated - requiring good design and that surely is a reason for the majority of projects to forget such a smiple and elegent solution to Runtime bindings.
Huh? This is a problem solved 20,000 times before. And why are we wanting to revert back to pre-dependency injection days with a built-in Service Factory pattern? I don't get how this is innovative in the least. Maybe helpful for very small apps, but even so, Guice or Spring can also be used (more effectively) for those very small apps that will almost always grow to be huge. It's so irritating to see Sun put really useless crap into Java, while not doing much to innovate the language. Closures? Built-in DI? /rant
I've had several successes using the ServiceLoader API pattern even before Java 6. I've used it to find implementations of a service at runtime for processing ACORD XML, loading board game strategies, loading POP3 Proxy filters, etc. I 'm glad that Sun has finally formalized the other half of it. Yes, Spring (and now Google Guice) solve dependency injection in other ways. I'm curious to see what others here have to say.
Shortly after I wrote an article on using Spring as the basis for a lightweight plug-in environment. http://www.devx.com/Java/Article/31835 A colleague directed me to this spec wondering how my ideas differed from this built in capability. There's clearly lots of overlap but one thing that jumps out is that it is not clear if it supports multiple implementation for a service running at once, where as a plug-in approach often times allows multiple plug-ins to extend an existing extension point. As for OSGi, everything I've read sounds promising, my only experience with it is tinkering around with Eclipse plug-ins which have been reworked to use OSGi. If the tools supporting Eclipse plug-ins also work well with general purpose OSGi then it is probably a pretty painless environment. Bryant
The ServiceLoader API is going to cause no end of pain. Please don't use it. I'm talking to you, Sun. Here's why: The ServiceLoader API assumes that you will only ever need one implementation of an interface. From the docs:
If a particular concrete provider class is named in more than one configuration file, or is named in the same configuration file more than once, then the duplicates are ignoredExcellent. Now, if, under different circumstances I told you that you could only ever have a single implementation of an interface, I'd hope your reaction would be suitably severe. "But this is for global providers" you say, "Surely you'd never need more than one implementation of a codec, SOAP library or secure sockets layer in your project". Bollocks. It's happened to me and it'll happen to you. What's worse is that the API doesn't even specify which of the implementations gets chosen, so you could suddenly find your SSL layer switching by just including another jar in your project that happens to have an alternate implementation under META-INF. "But we can just specify the implementation explicity then". Theoretically yes but unlike some smarter DI frameworks out there, the ServiceLoader encourages people to write code that looks like this: MessageFactory.getInstance(); "But we can usually override them with System properties". Excellent. Still a global variable, single implementation problem and now you've got to add random things to your startup script. "But Sun made this, it's a standard, it must be good". java.util.Date. So, please quietly ignore the ServiceLoader. If you know anyone at Sun, ask them to quietly deprecate the ServiceLoader. I suspect it's probably too late, though.
The ServiceLoader API is going to cause no end of pain. Please don't use it. I'm talking to you, Sun. Here's why:I had this same concern as well, but it looks to me like the conclusion isn't correct, and I think it is caused by the confusing documentation cited.
The ServiceLoader API assumes that you will only ever need one implementation of an interface. From the docs:
If a particular concrete provider class is named in more than one configuration file, or is named in the same configuration file more than once, then the duplicates are ignored...
To wit: It looks to me like you can have as many implementations of the interface (or subclasses of the abstract class) as you want. What you can't have is the same concrete class implementation of the interface specified in more than one service. Since the concrete classes are created with a no-arg constructor and there's no context (other than classloader), this seems like a natural restriction. If you need the same concrete class instantiated twice, use a different named subclass of that concrete for each service jar.