Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is something similar to ServiceLoader in Java 1.5?

How do I discover classes at runtime in the classpath which implements a defined interface?

ServiceLoader suits well (I think, I haven't used it), but I need do it in Java 1.5.

like image 802
Telcontar Avatar asked Oct 30 '08 19:10

Telcontar


People also ask

What is ServiceLoader in Java?

A service provider (or just provider) is a class that implements or subclasses the well-known interface or class. A ServiceLoader is an object that locates and loads service providers deployed in the run time environment at a time of an application's choosing.

How does a service loader work?

A service loader maintains a cache of the providers that have been loaded so far. Each invocation of the iterator method returns an iterator that first yields all of the elements of the cache, in instantiation order, and then lazily locates and instantiates any remaining providers, adding each one to the cache in turn.


3 Answers

There's nothing built into Java 1.5 for this. I implemented it myself; it's not too complicated. However, when we upgrade to Java 6, I will have to replace calls to my implementation with calls to ServiceLoader. I could have defined a little bridge between the app and the loader, but I only use it in a few places, and the wrapper itself would be a good candidate for a ServiceLoader.

This is the core idea:

public <S> Iterable<S> load(Class<S> ifc) throws Exception {
  ClassLoader ldr = Thread.currentThread().getContextClassLoader();
  Enumeration<URL> e = ldr.getResources("META-INF/services/" + ifc.getName());
  Collection<S> services = new ArrayList<S>();
  while (e.hasMoreElements()) {
    URL url = e.nextElement();
    InputStream is = url.openStream();
    try {
      BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8"));
      while (true) {
        String line = r.readLine();
        if (line == null)
          break;
        int comment = line.indexOf('#');
        if (comment >= 0)
          line = line.substring(0, comment);
        String name = line.trim();
        if (name.length() == 0)
          continue;
        Class<?> clz = Class.forName(name, true, ldr);
        Class<? extends S> impl = clz.asSubclass(ifc);
        Constructor<? extends S> ctor = impl.getConstructor();
        S svc = ctor.newInstance();
        services.add(svc);
      }
    }
    finally {
      is.close();
    }
  }
  return services;
}

Better exception handling is left as an exercise for the reader. Also, the method could be parameterized to accept a ClassLoader of the caller's choosing.

like image 88
erickson Avatar answered Oct 23 '22 02:10

erickson


javax.imageio.spi.ServiceRegistry is the equivalent with prior Java versions. It's available since Java 1.4.

It does not look like a general utility class, but it is. It's even a bit more powerful than ServiceLoader, as it allows some control over the order of the returned providers and direct access to the registry.

See http://docs.oracle.com/javase/7/docs/api/index.html?javax/imageio/spi/ServiceRegistry.html

like image 6
Marco Hunsicker Avatar answered Oct 23 '22 01:10

Marco Hunsicker


ServiceLoader is quite basic, and has been in use (informally) within the JDK since 1.3. ServiceLoader just finally made it a first class citizen. It simply looks for a resource file named for your interface, which is basically bundled in the META-INF directory of a library jar.

That file contains the name of the class to load.

So, you'd have a file named:

META-INF/services/com.example.your.interface

and inside it is a single line: com.you.your.interfaceImpl.

In lieu of ServiceLoader, I like Netbeans Lookup. It works with 1.5 (and maybe 1.4).

Out of the box, it does the exact same thing as ServiceLoader, and it's trivial to use. But it offers a lot more flexibility.

Here's a link: http://openide.netbeans.org/lookup/

Here's a article about ServiceLoader, but it mentions Netbeans Lookup at the bottom: http://weblogs.java.net/blog/timboudreau/archive/2008/08/simple_dependen.html

like image 1
Will Hartung Avatar answered Oct 23 '22 00:10

Will Hartung