Простой ServiceLoader — поставщик java.util.ServiceConfigurationError не найден

Я пытаюсь запустить пример приложения с помощью ServiceLoader. Для этого я создал два JAR:

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 имеет одну строку: ok.service.impl.NumberServiceImpl

META-INF/MANIFEST.mf имеет Main-Class: ok.main.App запись

И ok.main.App загружает провайдеров 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

Содержит реализацию ok.service.NumberService

Когда команда запускается как:

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

ИЛИ (оба JAR в одном каталоге)

java -jar number-service.jar

провайдер не найден.

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)

Не удалось понять, как класс провайдера не находится. Пожалуйста помоги!

Заранее спасибо.


person Onkar Kamatkar    schedule 01.03.2018    source источник
comment
Для начала META-INF/services/ok.service.NumberService должен находиться в файле JAR с реализацией поставщика услуг (в данном случае number-service-impl.jar). Далее вам понадобятся как number-service.jar, так и number-service-impl.jar на пути к классам. Вы обнаружите, что java -cp number-service.jar:number-service-impl.jar ok.main.App должно работать.   -  person Alan Bateman    schedule 01.03.2018
comment
Спасибо @AlanBateman, это работает, также переместил META-INF/services в number-service-impl.jar.   -  person Onkar Kamatkar    schedule 01.03.2018


Ответы (1)


[Это от Алана Бейтмана]

Во-первых, META-INF/services/ok.service.NumberService должен быть в JAR-файле с реализацией поставщика услуг (в данном случае number-service-impl.jar). Далее вам понадобятся как number-service.jar, так и number-service-impl.jar на пути к классам.

Вы обнаружите, что

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

...должно сработать.

person Cheeso    schedule 07.11.2018