9

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!

1 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Another key was making sure to use UTF-8 encoding without the byte-order mark for the resource file. When the BOM was included, it got interpreted as part of the class name and caused build problems.
In case anyone else revisits this, I have it working in one Java project, but if I bundle it up in a utility jar and try to use it in another project, java.nio.Files#probeContentType() doesn't find my implementation of java.nio.file.spi.FileTypeDetector. The service provider goes off looking for my META-INF/java.nio.file.spi.FileTypeDetector service implementation list, but doesn't find it.
Hi @bachman, I'm having the same problem. I have a Provider (super class), and there are three child classes. One from axis2-jaxws jar, second from jdk's rt.jar and the third one is from jaxws-rt.jar. I want the child from axis2-jaxws.jar but the ServideLoader is returning the one from jaxws-rt.jar. When I remove the jaxws-rt.jar, everything works fine. But I'm not sure if this is a good idea, as SOAP webservice require some jars during the runtime only. Do you or anyone remember a solution for this?
Hi Saravana- I suspect simply removing jaxws-rt.jar may have other consequences you might not want, and they could be subtle and take time to show up, making them harder to diagnose and/or correct. As you mention, your SOAP web services might encounter a problem during runtime. Sorry I don't recall any further details on how we got this working, and we're not using it any longer anyway.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.