java.util.ServiceConfigurationError提供程序在使用OSGibundle时不是子类型



我正在创建一个Liferay 7.1 OSGi捆绑包,其中有一些外部依赖项。考虑到时间,我们选择将外部JAR嵌入OSGi捆绑中。我已经创建了一个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.50.jar,XContentElasticsearchExtension类包含在elasticsearch-6.5.0.jar中。这两个类都是included Resources,并且已经放在类路径中。

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

编辑:

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

编辑2:

我担心这是SPI和OSGi之间的不兼容?我已经检查过:高级休息客户端也有同样的问题。(但随后是另一个扩展)。我将尝试低级别休息客户端。这应该是可行的,因为我猜有最小的依赖性。我仍然很好奇为什么会出现这种不兼容性。我当然不是OSGi方面的专家,也不是SPI方面的专家。(是时候学习新东西了!)

看起来像是OSGi使用您的捆绑包来解决来自另一个捆绑包的依赖关系的情况,可能是在系统启动时使用您的绑定包来解决包的情况。

查看症状:在启动或重新启动时不会出现这种情况。而且它不是一个子类型。

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

只暴露必要的,以尽量减少这种影响。仅在需要导入时导入。如果您正在使用Liferay Gradle配置将捆绑包包含在内,请停止——这是一种糟糕的包含方式,因为它暴露了很多。如果使用bnd文件来包含资源并为基本类路径位置创建条目,则在不必要的情况下不要公开。如果有多个捆绑包使用一个作为依赖项,请确保它们使用的版本,以及是否有问题类中的交换对象,如果有,则需要格外小心。

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

在一个Java应用程序中可以有两个弹性搜索连接,Liferay默认情况下不公开它所拥有的连接。

解决方法是重建Liferay ES连接器。这没什么大不了的,因为您不需要只更改OSGi描述符来公开更多的服务。

我在一个POC项目中做到了这一点,并且做得很好。棘手的事情是重建Liferay罐子,但Pettry通过他类似谷歌的搜索博客文章解释了这一点。https://community.liferay.com/blogs/-/blogs/creating-a-google-like-search(这是一个系列,但在新的Liferay博客中导航有点困难,但谷歌可能会提供帮助)不管怎样,这里都有很好的记录https://github.com/peerkar/liferay-gsearch

那么唯一需要做的就是在导出部分的bnd.bnd文件中添加org.elasticsearch.*。然后您就可以使用原生弹性API了。

相关内容

  • 没有找到相关文章

最新更新