META-INF/services in JAR with Gradle

gradle, jar, java, plugins

Solution

You place `META-INF/services/org.example.plugins.PluginService` in `src/main/java`, but it's not a source, it's a resource file, therefore it should be placed in resources folder according to Maven directory layout convention, that is

src/main/resources/META-INF/services/org.example.plugins.PluginService

In this case everything should work out of the box.

Problem

I wanted to build a plugin module that can be loaded with a `ServiceLoader`. This requires adding a file to the `META-INF/services` directory, that is named after the service interface and that contains the qualifying path to the class that implements it. Then you can load these services by calling `ServiceLoader.load()`. Here is an example: Say we want to provide a plugin interface called `org.example.plugins.PluginService`. We then provide an implementation of this service in the class `org.example.plugins.impl.ExamplePlugin`. If we want to have some sort of plugin mechanism, we could create a JAR file, that contains the implementation. This JAR file must also contain the file `META-INF/services/org.example.plugins.PluginService`. This file must contain one line ``` org.example.plugins.impl.ExamplePlugin ``` to enable the `ServiceLoader` to find the implementation. If that JAR file is in the build path, you can load the plugin by calling ``` Iterator<PluginService> it = ServiceLoader.load(PluginService.class).iterator(); ``` That iterator will give you access too all plugins that are found by the `ServiceLoader`. For some reason Gradle doesn't include files into the `META-INF` directory by default. Is there a way to let the resulting JAR contain such a file? I already found the method `metaInf` in class `Jar`. But I don't know groovy good enough to find the solution on my own.

Original source

Related problems