I recently needed a simple example of an SPI implementation I could send around as copy and paste template. After some looking around I found some tutorials, but most of them were rather heavy in the implementation and are thereby loosing the point of being a simple extension system within the JDK. If you’re looking for a more complete introduction into SPI, just go for the oracle tutorial.
So what I wanted to build was a simple service (HelloService), which defines an interface but looks for its implementation in the classpath at runtime (something SPI was built for).
So i needed two projects to start with.
Project 1 HelloService
HelloService.java is the interface that has to be implemented.
package com.apimeister.spi;
public interface HelloService {
public void sayHello();
}
Start.java is the starting point for running this jar.
package com.apimeister.spi;
import java.util.Iterator;
import java.util.ServiceLoader;
public class Start {
public static void main(String[] args) {
ServiceLoader<HelloService> loader =ServiceLoader.load(HelloService.class);
Iterator<HelloService> iter = loader.iterator();
while(iter.hasNext()){
iter.next().sayHello();
}
System.out.println("done");
}
}
Running this project (after exporting it as jar file) leads to the following output.
C:\Temp>java -cp helloService.jar com.apimeister.spi.Start
done
Now lets add some implementation.
Project 2 HelloGermany
The project consists of 2 files. HelloService.java implements the service.
package com.apimeister.spi.germany;
public class HelloService implements com.apimeister.spi.HelloService{
@Override
public void sayHello() {
System.out.println("hello Germany");
}
}
Second file (com.apimeister.spi.HelloService) is the service definition manifest.
com.apimeister.spi.germany.HelloService
The name of the file defines the service that has to be hooked into. The content of the file is the classpath of the implementation.
After exporting this project as separate JAR-file, I can re-run my project with both jar in the classpath in the command prompt.
C:\Temp>java -cp helloGermany.jar;helloService.jar com.apimeister.spi.Start
hello Germany
done
Now the external implementation is called without changing any of the original code.