Java 提供程序不是docker容器中的子类型

Java 提供程序不是docker容器中的子类型,java,docker,urlclassloader,serviceloader,Java,Docker,Urlclassloader,Serviceloader,形势 我正在开发一个应用程序,它使用Java的URLClassLoader和ServiceLoader来加载jar文件。在这些jar文件中是实现我的接口的提供者。文件夹结构如中所述,意味着: 接口与插件中实现接口的类(com.x.projectname.plugin.IInterface.java)位于同一目录中。在插件中,接口和实现它的类都位于com.x.projectname.plugin文件夹中 插件中有一个resources.META-INF.services目录,其中有一个文件:co

形势

我正在开发一个应用程序,它使用Java的URLClassLoader和ServiceLoader来加载jar文件。在这些jar文件中是实现我的接口的提供者。文件夹结构如中所述,意味着:

  • 接口与插件中实现接口的类(com.x.projectname.plugin.IInterface.java)位于同一目录中。在插件中,接口和实现它的类都位于com.x.projectname.plugin文件夹中
  • 插件中有一个resources.META-INF.services目录,其中有一个文件:com.x.projectname.plugin.i与以下内容的接口:com.x.projectname.plugin.classthatpimplementsiinterface
在我的本地机器上运行时(使用Oracle JDK 1.8 162和OpenJDK 1.8 171进行测试),插件加载良好,应用程序可以根据需要使用插件

问题

在docker容器中运行主应用程序时,它无法加载所需的插件。Docker容器中有一个安装在机器上的文件夹,插件位于其中。应用程序的docker映像使用openjdk:8-jdk-alpine,但无论我是否使用alpine版本,问题仍然存在

尝试使用Serviceloader.load()加载插件时(请参阅

它因以下错误而崩溃: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运行命令:

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

事实证明,答案正如Saqib在一篇评论中所说:构建一个胖罐子。我使用shadowJar来实现这一点:。

你可以上传你用来构建图像的docker文件,然后使用
docker run
命令或
docker compose.yml
来启动容器。@SaqibAhmed当然,添加了它!如果你运行这个命令的话使用
java-jar..
在您的本地系统上安装jar文件,它能工作吗?刚刚测试过,没有。这看起来很奇怪,因为通过intelliJ运行它确实能工作。这并不奇怪。这一直是个问题。这不是docker相关的问题。您必须创建一个java代码库,以便它包含所有依赖项一边
docker run -d -v /home/folder/pluginfolder:/pluginfolder -p=50505:50505 image-name