Search code examples
javamodularserviceloader

ServiceLoader cannot find service loaded from path


I have been trying to do a kind of plugin-system using the ServiceLoader. There are 2 modules, the first provides the abstract class LoadedRealmPlugin. The second one extends this class. I have added the file corresponding to the full name of the ServiceProvider and added the service-class to it. IntelliJ does not find any errors (but when changing the filename or classname it does). Here is the structure:

MainModule
   src
     main
       java
          com.interestingcompany.mainmodule
             LoadedRealmPlugin
  MainModule.iml

Plugin
  META-INF
      services
          com.interestingcompany.mainmodule (-> Content: "PluginExtension")
  src
     PluginExtension
  Plugin.iml

(This is simplified, I left out classes that (I think) are not important to the ServiceLoader. I can post a screenshot of the actual structure if anyone needs it)

Here is the code I use to load the Service:

File file = new File("Plugins/Plugin.jar");
URLClassLoader c = new URLClassLoader(new URL[]{file.getAbsoluteFile().toURI().toURL()});
ServiceLoader<LoadedRealmPlugin> loader = ServiceLoader.load(LoadedRealmPlugin.class, c);
LoadedRealmPlugin p = loader.iterator().next(); // Throws a java.util.NoSuchElementException
p.Initialize(RealmPath); // Abstract method implemented in the service
return p;

When trying to run it, I always get an empty ServiceLoader. I looked at this post, but I was not quite sure about how to apply that answer since I am trying to load my plugin from a file. In addition, I found this post. Yet, there was no answer, just some comments that did not seem to have answered the question.

As you might have been able to tell, this is my first time working with classloaders. If there is any additional information needed, just ask me. Thank you for reading through my beginner troubles.


Solution

  • package-less classes are in the unnamed package, which is inaccessible to rather a lot of code, notably including here.

    Put PluginExtension.java in a package, make sure the content of your META-INF/services/com.ic.mainmodule file reflects this (content should be pkg.PluginExtension), and it'll work fine.