Simple plugin systems via ServiceLoader's
Jun 29, 2019
1 minute read

Since Java 6 the jdk brings a lightweight mechanism to write plugin systems. The class we are going to use is the ServiceLoader.

A ServiceLoader takes the class of an interface or an abstract class and loads all registered implementations during runtime.

Further we will explore a sample implementation of a plugin system based on this machanism.

First define your plugin interface:

package api

interface Plugin {
    // specification details
}

Next we need to register our implementation in a file called src/main/resources/META-INF/services/api.Plugin:

This file contains just impl.MyPlugin. Out implementation implements the Plugin interface.

package impl

class MyPlugin : Plugin {
    // implementation details
}

Package up our implementation into a jar by calling for example gradle jar if we build our project with Gradle.

Our PluginManager now loads all implementations of the Plugin interface by inspecting given paths which should lead to jar files.

import java.util.ServiceLoader
import java.net.URLClassLoader

class PluginManager(val pluginPaths: Array<URL>) {

    fun loadPlugins(): List<Plugin> {
        val loader = URLClassLoader(pluginPaths, PluginManager::class.java)
        return ServiceLoader.load(Plugin::class.java, loader).toList()
    }
}

The usage of ServiceLoader is simple and provides us all the necessary tools to dynamically extend our program. My projects like detekt and ksh make heavy use of it.