java.util.ServiceLoader not loading my provider class

java, serviceloader

Solution

The answer appears to be in the sensitivity to exactly how this is configured. I had been placing my provider name resource file (the one named com.example.handler.Handler) directly in the top level project directory, i.e., /resources/META-INF/services/com.example.handler.Handler. I had configured my build.gradle to pull the file out and put it into the jar:

jar { from('resources') { include 'META-INF/services/*.*' } }

When I inspected the jar file, the file was there, right where I expected it to be, so I thought all was well. On a kick, I happened to move the resources folder from down under src/main, and presto! it works. I inspected the jar file and it appears identical to one built the previous way, but for some reason this one works. I will update further if I can determine a difference, but at least my test case works now.

Problem

I am trying to put together a basic SPI-based registry of Handlers, which I lookup from a HandlerRegistry. When I use the ServiceLoader.load(Handler.class) to initialize the providers, and then iterate the list to lazily load them, I am not seeing any instances of the class. Keeping this as simple as possible, my HandlerRegistry class is: ``` public class HandlerRegistry { private static HandlerRegistry registry; private ServiceLoader<Handler> handlerLoader; private HandlerRegistry() { handlerLoader = ServiceLoader.load(Handler.class); } public static synchronized HandlerRegistry getRegistry() { if (registry == null) { registry = new HandlerRegistry(); registry.init(); } return registry; } private void init() { System.out.println("HandlerRegistry.init()"); } public Handler lookup(String item) { System.out.println("lookup("+item+")"); try { Iterator<Handler> it = handlerLoader.iterator(); while (it.hasNext()) { Handler handler = it.next(); System.out.println("found handler "+handler); } } catch (ServiceConfigurationError err) { err.printStackTrace(); } return null; } } ``` I have a com.example.handler.Handler interface (empty for now for simplicity), and a com.example.handler.handlers.DummyHandler class which implements that interface. I have created a file in my jar called META-INF/services/com.example.handler.Handler, which contains the single line ``` com.example.handler.handlers.DummyHandler ``` according to the javadoc. My unit test simply calls the lookup() method to verify looking up the handler for an item. Of course there will eventulaly need to be a check of some kind to see if this is the right handler for this item, but at this point I am not even seeing my DummyHandler class get loaded by the registry. Am I doing something wrong here? Thanks!

Original source