3

I am trying to implement a simple modular application with a self written plugin loader. For that I created a gradle multiproject build. The main project is going to be the started application. In the subproject spi is a module containing the Plugin interface, while in the subproject simple-plugin I wanted to create a plugin to test the plugin loading.

The Plugin interface is very simple:

package io.github.zeroneca.orgascreen.spi;

public interface Plugin {
    String getId();
}

module-info.java:

module io.github.zeroneca.orgascreen.spi {
    exports io.github.zeroneca.orgascreen.spi;
}

SimplePlugin.java:

package io.github.zeroneca.orgascreen.plugins.simple;

import io.github.zeroneca.orgascreen.spi.Plugin;

public class SimplePlugin implements Plugin {
    private final String id = "SimplePlugin";

    @Override
    public String getId() { return id; }
}

module-info.java

module io.github.zeroneca.orgascreen.plugins.simple {
    requires io.github.zeroneca.orgascreen.spi;
    provides io.github.zeroneca.orgascreen.spi.Plugin with io.github.zeroneca.orgascreen.plugins.simple.SimplePlugin;
}

Now in the class PluginLoader I'm loading all jars from a directory and want to add all Plugins to a List:

package io.github.zeroneca.orgascreen;

// several imports

public class PluginLoader {
    private static final List<Plugin> PLUGINS = new ArrayList<>();

    public static void load() {
        URL[] pluginURLs = getPluginURLs();  // returns all URLs of jar files in a directory
        URLClassLoader urlClassLoader = URLClassLoader.newInstance(pluginURLs);
        ServiceLoader<Plugin> serviceLoader = ServiceLoader.load(Plugin.class, urlClassLoader);
        for (Plugin plugin : serviceLoader) {
            PLUGINS.add(plugin);
        }
    }
    // some more methods hidden here
}

module-info.java

module io.github.zeroneca.orgascreen {
    requires io.github.zeroneca.orgascreen.spi;
    uses io.github.zeroneca.orgascreen.spi.Plugin;
}

Now after building with gradle and copying the resulting jar simple-plugin-0.1.jar into the directory, I can see, that the URL of the file is in pluginJars but the List PLUGINS remains empty. I'm not sure what I'm doing wrong, online searches didn't help, I cannot see a difference to working solution, but the use of gradle.

gradle 6.5.1 is in use and modularity.inferModulePath is set to true.

Help is greatly appreciated!

Note: when adding META-INF/services/io.github.zeroneca.orgascreen.spi.Plugin to the jar of SimplePlugin it works, so something must be wrong with the module declarations. But I just can't see what.

Zeroneca
  • 31
  • 2
  • I have had the same issue. Very surprised that is not working out of the box with gradle 6.6.1. Adding the meta.inf stuff solved the problem but should IMHO not be required in java modular projects (java >=9) [helpful so q](https://stackoverflow.com/questions/13254620/meta-inf-services-in-jar-with-gradle) – Martin Meeser Sep 30 '20 at 08:21

0 Answers0