OSGi: как обеспечить согласованность пути к классам? - PullRequest
9 голосов
/ 19 сентября 2011

Согласно документации OSGi, OSGi предназначена для предотвращения проблем ClassPath.

Например, из «OSGi в действии»:

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

Однако, поскольку мы переключили наше java-приложение на OSGi, я вижу больше ClassNotFoundExceptions и особенно NoClassDefFoundErrors, чем когда-либо. Классы, которые ранее загружались нормально, больше не обнаруживаются загрузчиком классов OSGI, и еще хуже: вы получаете ошибку во время выполнения, а это значит, что вы не можете легко ее проверить, кроме как вручную проверяя каждый угол вашего приложения.

Например, наше приложение успешно работало под OSGi, но мы получили сообщения от бета-тестеров, что они больше не могут экспортировать документы в PDF. Действительно, когда я посмотрел на нее, я обнаружил, что эта функция вызвала исключение для регистрации:

java.lang.NoClassDefFoundError: org/w3c/dom/Node

Итак, создает ли OSGi больше проблем с classpath, чем решает?

и, что более важно: как я могу проверить, что мой путь к классам согласован со всеми необходимыми операторами Import-Package и т. Д. до Я читал о них в отчетах об ошибках?

Ответы [ 3 ]

13 голосов
/ 19 сентября 2011

Приложение OSGi не будет не выдавать ClassNotFoundExceptions и NoClassDefFoundErrors , если ваш манифест правильный.То есть вы должны указать OSGi, какие пакеты использует ваш пакет;если вы не сделаете это правильно или честно, то OSGi не сможет вам помочь.Другими словами: GIGO (Garbage In, Garbage Out).

Например, вы используете пакет org.w3c.dom, но не перечисляете его в своем выражении Import-Package.Поэтому OSGi не знает, что вам нужен доступ к этому пакету, и поэтому, когда вы действительно пытаетесь загрузить классы из этого пакета, они недоступны.

Итак, вам нужно убедиться, что ваш оператор Import-Packageточный в отношении пакетов, которые фактически используют ваши пакеты.Хорошей новостью является то, что инструмент «bnd» может сделать это для вас, сгенерировав манифест пакета, используя анализ байт-кода для поиска всех статически связанных пакетов.

Обновление: Ваш последний вопрос задаеткак проверить, что ваши пакеты совместимы, прежде чем обнаруживать проблемы во время выполнения.Bnd имеет функцию проверки, которая делает именно это.На самом деле, если вы используете Bnd для генерации манифеста, вам не понадобится функция проверки.Тем не менее, я ничего не знаю о вашем процессе сборки, поэтому вам может быть сложно перейти на сборку на основе Bnd в краткосрочной перспективе ... в этом случае было бы относительно просто добавить задачу проверки какшаг обработки после сборки.Тем не менее, я бы по-прежнему рекомендовал использовать Bnd ранее в процессе сборки.

2 голосов
/ 19 сентября 2011

Я думаю, что проблема в том, что вы не указываете правильный набор пакетов / классов, используемых вашим пакетом (используя директиву Import-Packages в вашем MANIFEST). Если OSGi не знает об этом, это действительно не может помочь!

Не уверен, как вы собираете свои OSGi-комплекты, но вы должны проверить Maven bundle plugin, который решает проблемы явного указания Import-Packages (по крайней мере для пакетов компиляции). Смотри http://wso2.org/library/tutorials/develop-osgi-bundles-using-maven-bundle-plugin#Importing%20packages.

1 голос
/ 11 октября 2016

Я не отвечаю на центральный вопрос, но предоставляю свое решение для аналогичной проблемы.

В моем случае у меня была такая структура классов:

  • interface javax.script.ScriptEngineFactory
  • class pkga.A implements ScriptEngineFactory
  • class pkgb.B extends A

Мой основной код проекта был в классе B, а этот расширенный класс A в зависимом Jar. Использование

<Export-Package>pkgb.*</Export-Package> 

было недостаточно, я получил ошибку с жалобой на отсутствие javax.script.ScriptEngineFactory. Это странно, так как является частью стандартного JDK 8, обратите внимание, что код в пакете pkgb явно не ссылка javax.script.*; возможно, автор Манифеста не знал, что этот интерфейс необходимо экспортировать?

Я обнаружил, что это дополнение к директиве Export-Package решило проблему

<Export-Package>pkgb.*,javax.script.*</Export-Package>
...