java.util.ServiceConfigurationError使用OSGi包时,Provider不是子类型

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java.util.ServiceConfigurationError使用OSGi包时,Provider不是子类型相关的知识,希望对你有一定的参考价值。

我正在创建一个Liferay 7.1 OSGi包,其中包含一些外部依赖项。考虑到时间,我们选择将外部JAR嵌入到OSGi Bundle中。我设法创建了一个bnd文件,其中包含所有ElasticSearch依赖项,并将它们放在bundle类路径中。我使用了github(https://github.com/liferay/liferay-portal/blob/master/modules/apps/portal-search-elasticsearch6/portal-search-elasticsearch6-impl/build.gradle)和bnd.bnd文件的源代码来检查导入的内容。

激活捆绑包时,会抛出异常:

The activate method has thrown an exception 
java.util.ServiceConfigurationError: org.elasticsearch.common.xcontent.XContentBuilderExtension: Provider org.elasticsearch.common.xcontent.XContentElasticsearchExtension not a subtype
    at java.util.ServiceLoader.fail(ServiceLoader.java:239)
    at java.util.ServiceLoader.access$300(ServiceLoader.java:185)
    at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:376)
    at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
    at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
    at org.elasticsearch.common.xcontent.XContentBuilder.<clinit>(XContentBuilder.java:118)
    at org.elasticsearch.common.settings.Setting.arrayToParsableString(Setting.java:1257)

XContentBuilderExtension来自elasticsearch-x-content-6.5.0.jar,XContentElasticsearchExtension类包含在elasticsearch-6.5.0.jar中。两者都是包含的资源,并且已经放在类路径中。

Activate-method初始化我的另一个jar中的TransportClient,因此它在激活时发生;)。

编辑:

我注意到第一次安装或门户重启时不会发生此错误。所以只有当我卸载并重新安装捆绑包时才会发生这种情况。 (这是我真正喜欢的功能!)。也许是一个愚蠢的想法..但可能是有一些“挂线”吗?捆绑包未正确安装,或者TransportClient仍处于活动状态?我正在检查这个。任何提示都是受欢迎的!

编辑2:

我担心这是SPI和OSGi之间的不兼容?我检查过:High Level Rest Client有同样的问题。 (但随后与另一个扩展)。我打算尝试低级休息客户端。这应该有效,因为存在最小的依赖性,我猜。我仍然非常好奇为什么不相容。我当然不是OSGi的专家,也不是SPI。 (学习新东西的时间!)

答案

似乎OSGi使用您的包来解决来自另一个包的依赖关系的情况,可能是在系统启动时使用您的包来解决包的问题。

查看症状:引导或重新启动时不会发生。它也不是一个子类型。

当OSGi使用该包来解决依赖关系时,它会保留一个副本,即使你删除它。当捆绑包返回时,之前由另一个捆绑包使用的包可能仍然存在,并且您可能会遇到这样的情况,即使用的类本身有两个版本,来自不同的类加载器,这意味着它们不是同一个类,因此不是亚型。

只暴露必要的,以尽量减少这种影响。仅在需要导入时导入。如果您正在使用Liferay Gradle配置将捆绑包括在内部,请停止 - 这是一种可怕的方式,因为它暴露了很多。如果使用bnd文件包含资源并为adicional类路径位置创建条目,则不要在不必要时公开。如果你有几个捆绑包使用一个作为依赖项,请确保它们使用的版本以及来自有问题的类的交换对象(如果有的话),而不是需要额外注意。

PS:您可以在导出和/或导入时包含属性,以便更具体,并避免使用来自错误源的包。

另一答案

您可以在一个Java应用程序中拥有2个弹性搜索连接,Liferay默认情况下不会暴露它所拥有的连接。

解决它的方法是重建Liferay ES连接器。这不是什么大问题,因为您不需要仅更改OSGi描述符的代码以暴露更多服务。

我在一个POC项目中做到了并且运行良好。棘手的事情是重建Liferay jar,但Pettry通过谷歌搜索博客文章解释了这一点。 https://community.liferay.com/blogs/-/blogs/creating-a-google-like-search(这是一个系列,但它很难在新的Liferay博客中导航,但谷歌可能会有所帮助)无论哪种方式都很好地记录在这里https://github.com/peerkar/liferay-gsearch

唯一需要做的就是在导出部分的bnd.bnd文件中添加org.elasticsearch.*。然后,您将能够使用本机弹性API。

以上是关于java.util.ServiceConfigurationError使用OSGi包时,Provider不是子类型的主要内容,如果未能解决你的问题,请参考以下文章