使用OSGi捆绑包时,java.util.ServiceConfigurationError提供程序不是子类型

时间:2019-02-04 12:13:18

标签: elasticsearch liferay osgi osgi-bundle embedded-osgi

我正在创建一个Liferay 7.1 OSGi捆绑软件,其中包含一些外部依赖项。考虑到时间,我们选择将外部JAR嵌入OSGi捆绑包中。我设法创建了一个bnd文件,其中包括所有ElasticSearch依赖项,并将它们放在包类路径中。我使用了来自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方法会在我的另一个jar中初始化一个TransportClient,因此它会在激活时发生)。

编辑:

我注意到,第一次安装此门户或门户重新启动时,不会发生此错误。因此,仅当我卸载并重新安装捆绑软件时才会发生。 (这是我真正喜欢的功能!)。也许是一个愚蠢的想法。但是,是否可能有一些“挂线”?捆绑软件未正确安装,或者TransportClient仍然有效?我正在检查这个。欢迎任何提示!

编辑2:

我担心这是SPI与OSGi之间的不兼容吗?我已经检查过:高级休息客户端也有同样的问题。 (但是再加上另一个扩展名)。我将尝试低级Rest Client。我猜这应该起作用,因为最小的依赖项。我仍然对为什么存在这种不兼容感到非常好奇。我当然不是OSGi的专家,也不是SPI的专家。 (该学习新东西了!)

2 个答案:

答案 0 :(得分:1)

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

一种解决方法是重建Liferay ES连接器。没什么大不了的,因为您不需要仅更改OSGi描述符的代码即可公开更多服务。

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

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

答案 1 :(得分:1)

好像OSGi使用您的软件包来解决来自另一个软件包的依赖关系的情况一样,可能是在系统启动时使用您的软件包来解决软件包的依赖。

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

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

仅暴露必要的信息以最小化其影响。仅在需要导入时导入。如果您使用Liferay Gradle配置在其中包含捆绑软件,请停止-这是一种糟糕的方法,因为它暴露了很多东西。如果使用bnd文件包含资源并为辅助类路径位置创建条目,则在不需要时不要公开。如果您有多个捆绑软件使用一个捆绑软件作为依赖项,请确保它们使用的版本以及问题类的交换对象(如果有)是否需要额外的照顾。

PS:在导出和/或导入时,您可以包括属性,以使其更加具体并避免使用错误来源的软件包。