提供者不是docker容器内的子类型

时间:2018-04-26 10:03:26

标签: java docker urlclassloader serviceloader

场合

我正在开发一个使用Java的 URLClassLoader ServiceLoader 来加载jar文件的应用程序。在这些jar文件中是实现我的接口的提供者。文件夹结构如this post by 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容器中运行主应用程序时,无法加载所需的插件。 Docker容器在其内部安装了一个文件夹,该插件位于该文件夹中。该应用程序的docker镜像使用的是openjdk:8-jdk-alpine,但问题仍然存在,无论我是否使用alpine版本。

尝试使用 Serviceloader.load()加载插件时(请参阅ServiceLoader.load(InterfaceName.class, ClassLoader loader)

崩溃时出现以下错误: Provider com.x.projectname.plugin.InterfaceImplementingClass 不是子类型。

这是stacktrace的相关部分:

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和泊坞窗运行命令

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命令:

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

1 个答案:

答案 0 :(得分:1)

事实证明,答案是Saqib在评论中所说:建造一个胖罐子。我使用shadowJar:http://imperceptiblethoughts.com/shadow/#configuring_shadow