提供者不是Docker容器内的子类型 [英] Provider not a subtype inside docker container

查看:155
本文介绍了提供者不是Docker容器内的子类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

情况

我正在开发一个使用Java的 URLClassLoader ServiceLoader 加载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容器中运行主应用程序时,它无法加载所需的插件. Docker容器在其内部安装的计算机上有一个文件夹,该插件位于该文件夹中.该应用程序的docker映像使用openjdk:8-jdk-alpine,但是无论是否使用alpine版本,问题仍然存在.

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

docker run命令:

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

事实证明,答案就如萨奇布(Saqib)在评论中所说:建立一个胖罐子.我为此使用了shadowJar: http://imperceptiblethoughts.com/shadow/#configuring_shadow .

Situation

I'm developing an application that uses Java's URLClassLoader and ServiceLoader to load jar files. Inside these jar files is the provider that implements my interface. The folder structure is as described in this post by oracle meaning that:

  • The interface is in the same directory as the class that implements the interface in the plugin (com.x.projectname.plugin.IInterface.java). In the plugin, both the interface and the class that implements it are in the com.x.projectname.plugin folder.
  • In the plugin there's a resources.META-INF.services directory with one file in it: com.x.projectname.plugin.IInterface with the following content: com.x.projectname.plugin.ClassThatImplementsIInterface.

When running on my local machine (tested with Oracle JDK 1.8 162 and OpenJDK 1.8 171) the plugin is loaded in fine and the application can use the plugin as desired.

The problem

When running the main application in a docker container it cannot load the desired plugin. The Docker container has a folder on the machine mounted inside it, where the plugin resides. The docker image of the application uses openjdk:8-jdk-alpine, but the problem persists whether I use the alpine version or not.

Upon trying to load the plugin using Serviceloader.load() (See ServiceLoader.load(InterfaceName.class, ClassLoader loader)

it crashes with the following error: Provider com.x.projectname.plugin.InterfaceImplementingClass not a subtype.

Here's the relevant part of the 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]

Any ideas why it won't load plugins when ran inside a Docker container?

EDIT 1: Dockerfile and docker run command

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"]

The docker run command:

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

解决方案

As it turns out, the answer was as Saqib said in a comment: build a fat jar. I used shadowJar for this: http://imperceptiblethoughts.com/shadow/#configuring_shadow.

这篇关于提供者不是Docker容器内的子类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆