java.util.ServiceConfigurationError Provider не является подтипом при использовании пакета OSGi
Я создаю комплект Liferay 7.1 OSGi, в котором есть некоторые внешние зависимости. Из соображений времени мы решили добавить внешний JAR-файл в наш OSGi Bundle. Мне удалось создать файл 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 - это файл asticsearch-x-content-6.5.0.jar, класс XContentElasticsearchExtension, включенный в файл asticsearch-6.5.0.jar. Оба являются Включенными Ресурсами и были помещены в путь к классам.
Метод Activate инициализирует TransportClient в моем другом банке, следовательно, это происходит при активации;).
Редактировать:
Я заметил, что эта ошибка НЕ возникает при первой установке или при перезапуске портала. Так что это происходит только когда я удаляю и переустанавливаю пакет. (Это функциональность, которую я действительно предпочитаю иметь!). Может быть, глупая мысль... Но может ли быть какая-то "висящая нить"? Что пакет не установлен правильно или что TransportClient все еще жив? Я проверяю это. Любые намеки приветствуются!
Изменить 2:
Я боюсь, что это несовместимость между SPI и OSGi? Я проверил: клиент высокого уровня отдыха имеет ту же проблему. (Но потом с другим расширением). Я собираюсь попробовать Low-Level Rest Client. Это должно работать, так как, я думаю, есть минимальные зависимости. Мне все еще очень любопытно, почему существует несовместимость. Я, конечно, не эксперт по OSGi и SPI. (Время изучать новые вещи!)
2 ответа
Похоже на случай, когда OSGi использует ваш пакет для решения зависимости от другого пакета, вероятно, тот, который использовал ваш пакет для решения пакета при запуске системы.
Глядя на симптомы: это не происходит при загрузке или перезагрузке. И это не подтип.
Когда OSGi использует этот пакет для решения зависимости, он будет хранить копию, даже когда вы ее удаляете. Когда пакет возвращается, пакет, который ранее использовался другим пакетом, все еще может присутствовать, и у вас может возникнуть ситуация, когда используемый класс имеет две версии самого себя из разных загрузчиков классов, что означает, что они не являются одним и тем же классом и, следовательно, не подтип.
Выставляйте только необходимое, чтобы минимизировать последствия этого. Импортировать только если необходимо импортировать. Если вы используете конфигурацию Liferay Gradle, чтобы включить пакет внутри, остановитесь - это ужасный способ включить, так как он много раскрывает. Если вы используете файл bnd для включения ресурса и создания записи для местоположения дополнительного пути к классам, не открывайте его, если в этом нет необходимости. Если у вас есть несколько пакетов, использующих один в качестве зависимости, убедитесь в том, что они используют версию и, если они обмениваются объектами проблемного класса, если это так, требуется дополнительная осторожность.
PS: вы можете включать атрибуты при экспорте и / или импорте, чтобы быть более конкретными и избегать использования пакетов из неправильного происхождения.
Вы можете иметь 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.