3

I am trying to run sample application using ServiceLoader. For this, I have created two JARs:

JAR 1) number-service.jar
  META-INF/
  META-INF/MANIFEST.MF
  ok/
  ok/service/
  ok/service/NumberService.class
  ok/main/
  ok/main/App.class
  META-INF/services/
  META-INF/services/ok.service.NumberService

META-INF/services/ok.service.NumberService has single line: ok.service.impl.NumberServiceImpl

META-INF/MANIFEST.mf has Main-Class: ok.main.App entry

And ok.main.App loads the providers of ok.service.NumberService

JAR 2) number-service-impl.jar
  META-INF/
  META-INF/MANIFEST.MF
  ok/
  ok/service/
  ok/service/impl/
  ok/service/impl/NumberServiceImpl.class

Contains implementation of ok.service.NumberService

When command is run as:

java -cp lib/number-service-impl.jar -jar lib/number-service.jar
java -cp ".:lib/number-service-impl.jar" -jar lib/number-service.jar

OR (both JARs in same directory)

java -jar number-service.jar

the provider is not found.

Exception in thread "main" java.util.ServiceConfigurationError: ok.service.NumberService: Provider ok.service.impl.NumberServiceImpl not found
    at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:588)
    at java.base/java.util.ServiceLoader.access$200(ServiceLoader.java:390)
    at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.nextProviderClass(ServiceLoader.java:1206)
    at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1215)
    at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1259)
    at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1294)
    at java.base/java.util.ServiceLoader$ProviderSpliterator.tryAdvance(ServiceLoader.java:1478)
    at java.base/java.util.Spliterator.forEachRemaining(Spliterator.java:326)
    at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:591)
    at ok.main.App.main(App.java:9)

Not able to figure out how the provider class is not getting located. Please help!

Thanks in advance.

Onkar Kamatkar
  • 212
  • 2
  • 10
  • 3
    For starters, META-INF/services/ok.service.NumberService should be in JAR file with the service provider implementation (number-service-impl.jar in this case). Next up is that you need both number-service.jar and number-service-impl.jar on the class path. You'll find that `java -cp number-service.jar:number-service-impl.jar ok.main.App` should work. – Alan Bateman Mar 01 '18 at 13:15
  • Thanks @AlanBateman, this works, also moved the META-INF/services in number-service-impl.jar – Onkar Kamatkar Mar 01 '18 at 13:21

1 Answers1

1

[This is from Alan Bateman]

For starters, META-INF/services/ok.service.NumberService should be in JAR file with the service provider implementation (number-service-impl.jar in this case). Next up is that you need both number-service.jar and number-service-impl.jar on the class path.

You'll find that

java -cp number-service.jar:number-service-impl.jar ok.main.App 

...should work.

Cheeso
  • 189,189
  • 101
  • 473
  • 713