Провайдер не подтип внутри контейнера докеров

Ситуация

Я разрабатываю приложение, которое использует URLClassLoader и ServiceLoader Java для загрузки файлов jar. Внутри этих файлов jar находится провайдер, реализующий мой интерфейс. Структура папок описана в этом сообщении oracle, что означает тот:

  • Интерфейс находится в том же каталоге, что и класс, реализующий интерфейс в плагине (com.x.projectname.plugin.IInterface.java). В подключаемом модуле интерфейс и реализующий его класс находятся в папке com.x.projectname.plugin.
  • В подключаемом модуле есть каталог resources.META-INF.services с одним файлом в нем: com.x.projectname.plugin.IInterface со следующим содержимым: com.x.projectname.plugin.ClassThatImplementsIInterface.

При запуске на моем локальном компьютере (протестировано с Oracle JDK 1.8 162 и OpenJDK 1.8 171) плагин загружается нормально, и приложение может использовать плагин по своему усмотрению.

Проблема

При запуске основного приложения в контейнере докеров он не может загрузить нужный плагин. Контейнер Docker имеет папку на машине, смонтированную внутри него, где находится плагин. Образ докера приложения использует openjdk: 8-jdk-alpine, но проблема сохраняется независимо от того, использую я версию alpine или нет.

При попытке загрузить подключаемый модуль с помощью Serviceloader.load () (см. ServiceLoader.load (InterfaceName.class, загрузчик ClassLoader)

происходит сбой со следующей ошибкой: Provider com.x.projectname.plugin.InterfaceImplementingClass не является подтипом.

Вот соответствующая часть трассировки стека:

Caused by: java.util.ServiceConfigurationError: com.x.projectname.plugin.IInterface: Provider com.x.projectname.plugin.ImplementingClass not a subtype
        at java.util.ServiceLoader.fail(ServiceLoader.java:239) ~[na:1.8.0_151]
        at java.util.ServiceLoader.access$300(ServiceLoader.java:185) ~[na:1.8.0_151]
        at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:376) ~[na:1.8.0_151]
        at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404) ~[na:1.8.0_151]
        at java.util.ServiceLoader$1.next(ServiceLoader.java:480) ~[na:1.8.0_151]
        at com.x.projectname.loader.PluginLoader.loadPlugins(PluginLoader.java:118) ~[classes!/:na]
        at com.x.projectname.loader.PluginLoader.initializePluginLoading(PluginLoader.java:67) ~[classes!/:na]
        at com.x.projectname.service.PluginService.<init>(PluginService.java:37) ~[classes!/:na]
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_151]
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_151]
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_151]

Есть идеи, почему он не загружает плагины при запуске внутри контейнера Docker?

ИЗМЕНИТЬ 1. Dockerfile и команда запуска docker

FROM openjdk:8-jdk-alpine
ARG JAR_FILE
ADD ${JAR_FILE} /CICD-dashboard.jar

# Remote debugging port for intelliJ == address
EXPOSE 50505
ENTRYPOINT [ "java", "-Xrunjdwp:transport=dt_socket,address=50505,suspend=n,server=y", "-jar", "/X-project.jar"]

Команда запуска докера:

docker run -d -v /home/folder/pluginfolder:/pluginfolder -p=50505:50505 image-name

person Oromë    schedule 26.04.2018    source источник
comment
Не могли бы вы загрузить свой Dockerfile, который вы использовали для создания образа, и команду docker run или docker-compose.yml в зависимости от того, что вы использовали для запуска контейнера.   -  person Saqib Ahmed    schedule 26.04.2018
comment
@SaqibAhmed Конечно, добавил!   -  person Oromë    schedule 26.04.2018
comment
Если вы запустите этот файл jar в своей локальной системе с java -jar .., он будет работать?   -  person Saqib Ahmed    schedule 26.04.2018
comment
Только что проверил, и нет. Это кажется очень странным, потому что запуск через intelliJ действительно работает.   -  person Oromë    schedule 26.04.2018
comment
Это не странно. Это проблема с самого начала. Это не проблема, связанная с докером. Вам нужно будет создать Uberjar вашего Код Java, чтобы он содержал внутри все зависимости.   -  person Saqib Ahmed    schedule 26.04.2018
comment
Какой инструмент сборки вы используете? Maven, Gradle и т. Д.   -  person Saqib Ahmed    schedule 26.04.2018
comment
Хорошо, я сделал толстый / Uberjar с помощью shadowJar (imperceptiblegotits.com/shadow/#configuring_shadow) и теперь работает локально. Тем не менее, я все еще получаю ту же ошибку при запуске в контейнере докера.   -  person Oromë    schedule 26.04.2018
comment
Чтобы быть уверенным, вы создали новый образ из заданного файла докеров и запустили контейнер из этого образа ?? Также попробуйте удалить изображения с помощью docker rmi и создать новый образ. Если он работает на вашем компьютере с java -jar, он также должен работать в контейнере докера с теми же аргументами.   -  person Saqib Ahmed    schedule 26.04.2018
comment
Приносим извинения за поздний ответ @SaqibAhmed. Как оказалось, я неправильно строил толстую банку; это действительно было решение!   -  person Oromë    schedule 01.05.2018


Ответы (1)


Как выяснилось, ответ был таким, как сказал Сакиб в комментарии: построить толстую банку. Для этого я использовал shadowJar: http://imperceptibleoughtts.com/shadow/#configuring_shadow.

person Oromë    schedule 01.05.2018