ServiceLoader – modularization for free

Another outcome of NetBeans training I was mention in previous post was information about java.util.ServiceLoader class. Current application are very large, and to provide maintenance and easy of development we can build it from modules. There are so much information about Dependency Injection, that probably everyone knows about it, frameworks such as Spring Framework, Google Guice, Pico Container etc.  OSGi with  Equinox, Apache Felix and Knopflerfish implementation and NetBeans Module API and even maven and ivy tool. This frameworks and tools help us to keep our application modular. But … Did you know that by using Java version 6 we have DI for free. ServiceLoader class allows that, and now we can write modular application without using framework with many megabytes of classes. So how it works. Assume that we have business interface :

public interface BusinessInterface {
    void businessMethod(String data);
}

And we have two implementation in different modules.

public class BusinessFirstImpl implements BusinessInterface {
   public void businessMethod(String data) {
     System.out.println("First processing " + data);
   }
}
public class BusinessAnotherImpl implements BusinessInterface {
   public void businessMethod(String data) {
     System.out.println("A pnother processing " + data);
   }
}

Two make this working, every jar must have META-INF/services directory which contains file which names is exactly the same as FQN of the interface.

metainf1

In this file we should have single line per contract implementation

info.pietrowski.first.BusinessFirstImpl
info.pietrowski.another.BusinessAnotherImpl
...

We can discover our service using ServiceLoader class. This is the main class.

public class DependencyMain {
  public static void main(String[] args) {
    ServiceLoader implementation = ServiceLoader.load(BusinessInterface.class);
    for (BusinessInterface impl : implementation) {
       impl.businessMethod(impl.getClass().getName());
    } 
  } 
}

Depending on which jars you have in classpath we can have one of  outcome.

>java -cp main.jar info.pietrowski.DependencyMain
>java -cp main.jar;first.jar info.pietrowski.DependencyMain
First processinginfo.pietrowski.first.BusinessFirstImpl
>java -cp main.jar;another.jar info.pietrowski.DependencyMain
Another processinginfo.pietrowski.another.BusinessAnotherImpl
>java -cp main.jar;another.jar;first.jar info.pietrowski.DependencyMain
Another processinginfo.pietrowski.another.BusinessAnotherImpl
First processinginfo.pietrowski.first.BusinessFirstImp

Download full code source and jar files has also sources. Next time you can use this mechanism in simple and light application.