Java 9 module
Wiring and Finding
Java has a ServiceLoader class for long time. It was introduced in 1.6 but a similar technology was in use since around Java 1.2. Some software components used it, but the use was not widespread. It can be used to modularize the application (even more) and to provide a mean to extend an application using some kind of plug-ins that the application does not depend on compile time. Also, the configuration of these services is very simple: just put it on the class/module path. We will see the details.
Browsing the classpath
This section is a little detour, but it is important to understand why ServiceLoader works the way it does, even before we discuss how it does.
A Java code cannot query the classloader to list all the classes that are on the classpath. You may say I lie because Spring does browse the classes and finds automatically the implementation candidates. Spring actually cheats. I will tell you how it does.
For now, accept that the classpath cannot be browsed. If you look at the documentation of the class ClassLoader you do not find any method that would return the array, stream or collection of the classes. You can get the array of the packages but you cannot get the classes even from the packages.
How does ServiceLoader Find a Class
The ServiceLoader can find and instantiate classes that implement a specific interface. When we call the static method ServiceLoader.load(interfaceKlass), it returns a “list” of classes that implement this interface.
I used “list” between quotes because technically it returns an instance of ServiceLoader, which itself implements Iterable so we can iterate over the instances of the classes that implement the interface. The iteration is usually done in a for loop invoking the method load() following the (:) colon.
You can download a multi-module maven project from https://github.com/verhas/module-test.
This project contains three modules Consumer, Provider and ServiceInterface. The consumer calls the ServiceLoader and consumes the service, which is defined by an interface javax0.serviceinterface.ServiceInterface in the module ServiceInterface and implemented in the module Provider. The structure of the code can be seen in the following picture:
Here I will tell you some of the stupid mistakes I made while I created this very simple example so that you can learn from my mistakes instead of repeating the same. First of all, there is a sentence in the Java 9 JDK documentation in the ServiceLoader that reads
In addition, if the service is not in the application module, then the module declaration must have a requires directive that specifies the module which exports the service.
I do not know what it wants to say, but what it means to me is not true. Maybe I misinterpret this sentence, which is likely.