Поставщик java.util.ServiceConfigurationError не является подтипом при использовании пакета OSGi

Я создаю пакет OSGi Liferay 7.1, в котором есть некоторые внешние зависимости. Учитывая время, мы решили встроить внешний 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 инициализирует TransportClient в другой моей банке, следовательно, это происходит при активации;).

Редактировать:

Я заметил, что эта ошибка НЕ ​​возникает при первой установке или при перезапуске портала. Так что это происходит только тогда, когда я удаляю и переустанавливаю пакет. (Это функциональность, которую я действительно предпочитаю!). Может быть, глупая мысль.. Но может быть, есть какая-то «висящая нить»? Что пакет установлен неправильно или что TransportClient все еще жив? Я проверяю это. Любые подсказки приветствуются!

Редактировать 2:

Я боюсь, что это несовместимость между SPI и OSGi? Я проверил: у клиента отдыха высокого уровня такая же проблема. (Но тогда с другим расширением). Я собираюсь попробовать низкоуровневый клиент отдыха. Это должно работать, так как я предполагаю, что есть минимальные зависимости. Мне все еще очень любопытно, почему существует несовместимость. Я, конечно, не эксперт ни в OSGi, ни в SPI. (Время учиться новому!)


person Kornelito Benito    schedule 04.02.2019    source источник
comment
Вопрос: почему вы встраиваете код в собственный пакет, который уже доступен в liferay? см. i.imgur.com/Rra4dAa.png   -  person Daniele Baggio    schedule 04.02.2019
comment
Поскольку моя внешняя зависимость изначально использует ElasticSearch. Liferay не экспортирует эластичные пакеты. Эластичные пакеты недоступны через OSGi. Но поправьте меня, если я ошибаюсь. :)   -  person Kornelito Benito    schedule 04.02.2019
comment
Я не мастер osgi, но почему бы не взять существующую связку portal-search-elasticsearch6-impl, сделать копию, изменить bdn.bdn и экспортировать то, что вы хотите, дать ему новую версию и развернуть банку. . ?   -  person Daniele Baggio    schedule 04.02.2019
comment
Ну, это именно то, что я не хочу делать. Коснитесь внутренних комплектов Liferay, чтобы исправить мои. Это действительно очень плохая практика, и я советую вам никогда этого не делать. В вашем случае всякий раз, когда пакет будет обновляться, вы должны вручную обновлять классы. И кроме Elastic Dependency, наш пакет имеет 0 сходств с существующим порталом-поиска-elasticsearch6-impl. Весь смысл OSGi в том, что пакеты имеют свой собственный путь к классам, и что можно даже иметь несколько развернутых версий такая же зависимость. Я не собираюсь злоупотреблять существующим пакетом для своего...   -  person Kornelito Benito    schedule 04.02.2019
comment
Хорошо, Корнелито, понятно.   -  person Daniele Baggio    schedule 06.02.2019


Ответы (2)


Похоже на случай, когда OSGi использует ваш пакет для решения зависимости от другого пакета, возможно, того, который использовал ваш пакет для решения пакета при запуске системы.

Глядя на симптомы: не возникает при загрузке или перезагрузке. Также это не подтип.

Когда OSGi использует этот пакет для устранения зависимости, он сохранит копию, даже если вы ее удалите. Когда пакет возвращается, пакет, который ранее использовался другим пакетом, может все еще существовать, и может возникнуть ситуация, когда используемый класс имеет две версии самого себя, от разных загрузчиков классов, что означает, что они не являются одним и тем же классом и, следовательно, не являются подтип.

Выставляйте только необходимое, чтобы свести к минимуму последствия этого. Импортируйте только в случае необходимости импорта. Если вы используете конфигурацию Liferay Gradle для включения пакета внутрь, остановитесь — это ужасный способ включения, поскольку он раскрывает многое. Если вы используете файл bnd для включения ресурса и создания записи для дополнительного пути к классам, не раскрывайте его, если в этом нет необходимости. Если у вас есть несколько пакетов, использующих один в качестве зависимости, убедитесь в том, какую версию они используют, и если они обмениваются объектами из проблемного класса, то требуется дополнительная осторожность.

PS: вы можете включать атрибуты при экспорте и/или импорте, чтобы быть более конкретным и избегать использования пакетов из неправильного источника.

person Victor    schedule 11.02.2019

У вас может быть 2 эластичных поисковых соединения внутри одного Java-приложения, и Liferay по умолчанию не раскрывает соединение, которое у него есть.

Обойти это можно, перестроив разъем Liferay ES. Это не имеет большого значения, потому что вам не нужно менять код, а только дескриптор OSGi, чтобы открыть больше сервисов.

Я сделал это в одном проекте POC и работал нормально. Сложность состоит в том, чтобы восстановить банку Liferay, но Петртри объяснил это своими сообщениями в блоге Google, похожими на поиск. https://community.liferay.com/blogs/-/blogs/creating-a-google-like-search (это серия, но в новых блогах Liferay довольно сложно ориентироваться, но Google, вероятно, поможет) В любом случае, все это хорошо задокументировано здесь https://github.com/peerkar/liferay-gsearch

единственное, что тогда нужно сделать, это добавить org.elasticsearch.* в файл bnd.bnd в разделе экспорта. После этого вы сможете работать с собственным эластичным API.

person Miroslav Ligas    schedule 07.02.2019
comment
Это почти тот же ответ, что и Даниэле Баджо в разделе комментариев. Я знаю, что это возможно, но я бы предпочел сохранить изменения в своем собственном коде. Я не хочу перестраивать стандартный коннектор Liferay ES. Каждое изменение, которое они вносят, я буду нести ответственность за перестройку этого модуля. Кстати, повторное развертывание этого соединителя также требует перезагрузки системы, и, по моему мнению, это как-то связано с несовместимостью SPI и OSGi. Я добавил вознаграждение, потому что мне нужно было больше информации о том, ПОЧЕМУ это не работает, поскольку я реализовал это на данный момент. Почему это исключение происходит? - person Kornelito Benito; 07.02.2019
comment
Я думаю, что проблема больше связана с разъемом ES, чем с Liferay или OSGi, хотя я также был удивлен, когда в прошлый раз, когда я играл с ним, он не работал. Проблема со старым клиентом заключалась в том, как ES подключается к кластеру. Но я бы ожидал, что HLRC для меня будет более отсоединен от реального сервера ES. Вы смотрели в исходный код ES? - person Miroslav Ligas; 09.02.2019
comment
Вы, безусловно, правы. Я заметил, что у разъема Liferay тоже есть эта проблема. Всякий раз, когда происходит повторное развертывание соединителя, я получаю сообщение журнала о том, что соединитель будет установлен при следующем запуске. (Вероятно, чтобы обойти эти проблемы.). Пакет HLRC также содержит некоторые SPI. И пусть именно это будет проблемой. - person Kornelito Benito; 11.02.2019