понедельник, 16 марта 2009 г.

Введение в OSGi. Работаем с Equinox - реализацией OSGi R4 от Eclipse Foundation.


В предыдущей статье цикла мы говорили про спецификацию OSGi и ее реализации. В данной заметке попробуем написать простой бандл и поработаем с системой Equinox, которую разрабатывают парни из Eclipse Foundation.

Начнем с разработки нашего первого бандла. Бандл будет состоять из класса-активатора и манифеста. Код класса-активатора следующий:

package org.beq.equinox.hello;



import org.osgi.framework.BundleActivator;

import org.osgi.framework.BundleContext;



public class Activator implements BundleActivator

{

    @Override

    public void start(BundleContext context) throws Exception

    {

        System.out.println("Start plugin activator");

    }



    @Override

    public void stop(BundleContext context) throws Exception

    {

        System.out.println("Stop plugin activator");

    }

}

 


Активатор бандла состоит из двух методов: start(BundleContext context) и stop(BundleContext context). Когда бандл стартует (переходит из состояния RESOLVED в состояние ACTIVE) выполняется метод start. Соответственно, предполагается, что в данном методе будет происходить регистрация сервисов, которые выставляет данный бандл и подключение к сервисам, выставляемым другими бандлами.


Понятно, что метод stop используется для освобождения ресурсов и отключения от используемых бандлом сервисов.

Гораздо интереснее в данном примере манифест бандла. Манифест бандла представляет собой файл META-INF/MAINFEST.MF, синтаксис которого полностью совпадает с синтаксисом манифеста jar-архива. Основными полями манифеста являются следующие:

  • Bundle-Activator - имя класса-активатора

  • Bundle-Classpath - содержит имена используемых бандлом jar-файлов и каталогов, содержащих классы и иные ресурсы. По-умолчанию значение равно (.)

  • Bundle-ContactAddress - содержит контактный адрес разработчика бандла

  • Bundle-Copyright - содержит условия использования бандла

  • Bundle-DocURL - URL, по которому расположена документация по бандлу

  • Bundle-Localization - содержит путь к используемым бандлам файлам локализации. По умолчанию - OSGI-INF/l10n/bundle

  • Bundle-ManifestVersion - определяет используемую бандлом спецификацию OSGi (R3 или R4)

  • Bundle-Name - имя бандла, должно быть человекочитабельным

  • Bundle-SymbolicName - обязательное поле. Определяет имя бандла в OSGi-шине. Именно по этому имени шина будет обращаться к бандлу

  • Bundle-Vendor - имя разработчика бандла

  • Bundle-Version - версия бандла. Значение по умолчанию - 0.0.0

  • Export-Package - перечисление экспортируемых бандлом java-пакетов

  • Fragment-Host - определяет Host-бандл для данного Fragment-бандла

  • Import-Package - определяет какие пакеты извне будут доступны данному бандлу

  • Require-Bundle - список бандлов от которых зависит данный



Манифест нашего бандла будет выглядеть следующим образом:

Manifest-Version: 1.0

Bundle-ManifestVersion: 2

Bundle-Name: OSGi Demo Bundle

Bundle-SymbolicName: org.beq.equinox.hello

Bundle-Version: 1.0.0

Bundle-Activator: org.beq.equinox.hello.Activator

Require-Bundle: org.eclipse.osgi


Все, бандл написан. Теперь его можно экспортировать в jar-архив (средствами Eclipse или Ant'ом). Убедитесь, что манифест получившегося jar-архива содержит приведенный выше код.

Теперь можно попробовать запустить наш бандл. Для этого нам необходим так называемый системный бандл - org.eclipse.osgi. Системным называется бандл, который содержит в себе OSGi шину и осуществляет управление ею.

Разместим наши бандлы следующим образом:

\demo
---org.eclipse.osgi.3.4.0.v20080605-1900.jar
---org.beq.equinox.hello_1.0.0.jar

Теперь из командной строки выполняем:


java -jar org.eclipse.osgi.3.4.0.v20080605-1900.jar -console


Стартует консоль Equinox и сама шина. К шине у нас сейчас подключен всего один бандл - тот самый системный, который эту шину нам и предоставляет. В консоли Equinox можно использовать следующие команды:

  • ss - посмотреть текущее состояние шины

  • install bundleURL - установить бандл. bundle URL - путь, идентифицирующий бандл. В качестве пути может использоваться конструкция вида: file:\ПОЛНЫЙ ПУТЬ К ФАЙЛУ БАНДЛА, например: file:\C:\@User\Java\bundle_1.0.0.jar

  • start bundleId или bundleName - стартует бандл. После установки каждому бандлу назначается идентификатор (bundleId). bundleName - значение параметра Bundle-SymbolicName из манифеста бандла

  • stop bundleId или bundleName - останавливает бандл.

  • update bundleId или bundleName - обновляем бандл.

  • diag bundleId или bundleName - выводит диагностику по бандлу. Например - какие ресурсы из необходимых бандлу недоступны.

  • headers bundleId или bundleName - выводит список свойств, определенных в манифесте бандла и их значений

  • uninstall bundleId или bundleName - удаляет бандл из системы



Для начала выполним команду ss. Как видим установлен и активен только один бандл:



Давайте установим наш бандл на шину:


install file:/D:/@Pavel/Develop/Java/_learn_equinox_workspace/org.beq.equinox.hello/org.beq.equinox.hello_1.0.0.jar


Equinox с радостью нам сообщит, что бандл установлен:



Убедимся в этом, введя команду ss:



Теперь самое время стартовать бандл. Выполним команду:


start 3




Мы видим текст, выведенный на консоль активатором бандла. Наш бандл успешно стартовал и находится в состоянии ACTIVE.



Понятно, что управлять бандлами через консоль можно только вот в таких вот демках. Реальное приложение должно уметь само стартовать шину и загружать нужные ему бандлы. К счастью, Equinox предлагает гибкую систему конфигурации, в которой можно описать какие бандлы в какое состояние необходимо перевести после старта шины.

Создадим следующую структуру каталогов:

\demo
---\configuration
-------config.ini
---org.eclipse.osgi_3.4.0.jar
---org.beq.equinox.hello_1.0.0.jar

Файл config.ini должен иметь следующее содержание:


osgi.bundles=org.beq.equinox.hello_1.0.0.jar@start
eclipse.ignoreApp=true


Переменная osgi.bundles - перечисление через запятую бандлов и требуемых состояний. Переменная eclipse.ignoreApp указывает шине игнорировать несущественные пока для нас ошибки.

Запускаем Equinox:


java -jar org.eclipse.osgi.3.4.0.v20080605-1900.jar -console


Наблюдаем следующую картину:



Как видим, наш бандл не только был загружен в Equinox, но и успешно стартовал.

В реальных приложениях могут быть сотни бандлов (как, например, в Eclipse SDK). Неправильно перечислять все бандлы в директиве osgi.bundles. Хочется устанавливать бандлы, просто помещая файлы с ними в соответствующий каталог. Также хочется автоматически обновлять бандлы. К тому же не всегда обязательно стартовать бандл сразу после его загрузки (если бандлов много это может занять существенное время). Тем более, OSGi - динамическая плагинная шина и позволяет реализовать сколь угодно сложные стратегии управления жизненными циклами бандлов.

В состав Equinox входят компоненты, позволяющие автоматически инсталировать и обновлять бандлы, находящиеся в каталоге plugins. Это: org.eclipse.equinox.common и org.eclipse.update.configurator. Посмотрим как они работают. Для этого создадим следующую структуру каталогов:

\demo
---\configuration
------config.ini
---org.eclipse.osgi_3.4.0.jar
---org.equinox.common_3.4.0.jar
---org.eclipse.update.configurator_3.2.200.jar
---\plugins
-------org.beq.equinox.hello_1.0.0.jar

Файл config.ini должен иметь следующее содержание:


osgi.bundles=org.eclipse.equinox.common@2:start,org.eclipse.update.configurator@3:start
eclipse.ignoreApp=true


Когда update configurator стартует он ищет бандлы в директории plugins и устанавливает их в систему. Важно понимать, что configurator не стартует данные бандлы. Состояние шины после старта update configurator'а показано на рисунке:



И, наконец, начиная с версии Eclipse 3.3 в состав Equinox входит платформенно-зависимый launcher. Launcher состоит из трех частей: нативный загрузочный модуль (eclipse.exe), разделяемая библиотека (eclipse_xxxx.dll) и jar-архив с ява-кодом launcher'а (org.eclipse.equinox.launcher_1.0.100.jar). Файл eclipse.exe должен находится в корне программы, launcher.jar и разделяемая библиотека - в каталоге plugins:

\demo
---\configuration
------config.ini
---eclipse.exe
---\plugins
------\org.eclipse.equinox.launcher.win32.win32.x86_1.0.100
---------eclipse.dll
------org.beq.equinox.hello_1.0.0.jar
------org.eclipse.equinox.launcher_1.0.100.jar
------org.eclipse.osgi_3.4.0.jar
------org.equinox.common_3.4.0.jar
------org.eclipse.update.configurator_3.2.200.jar

Запускается все это дело естественно с помощью eclipse.exe. Если фреймворк не находит никакого приложения - equinox автоматически останавливается, а все бандлы выгружаются. Чтобы этого избежать в config.ini необходимо добавить строку:


osgi.noShutdown=true


Чтобы стартовать приложение с Equinox-консолью необходимо выполнить


eclipse -console


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

Оставайтесь на связи! Всегда буду рад вашим вопросам или просто комментариям.

Понравилось сообщение - подпишись на блог

З.Ы. Если Вы есть во Вконтакте - вступайте в группу Russian Eclipse Community.

12 комментариев:

Анонимный комментирует...

Очень познавательно, буду ждать продолжения!!

tamerlan комментирует...

Павел, статья супер! Впечатлен :-)
Скажи, пожалуйста, как ты нашел информацию, чтобы во всем этом разобраться? Может быть книга или статьи? Можешь дать ссылки или информацию, где можно об этом почитать?

Конечно же буду ждать продолжение!

Samolisov Pavel комментирует...

Рад что вам понравилось, обязательно буду продолжать.

По поводу ссылок. Часть ссылок приведено в первом посте серии и коментах к нему.

Так же интересный материал есть на сайте eclipse: http://eclipse.org и eclipse zone: http://www.eclipsezone.com/

Так же интересный цикл статей Getting Started with OSGi: http://neilbartlett.name/blog/osgi-articles/

Samolisov Pavel комментирует...

tamerlan, у вас блоги пустые это так надо или нужен доступ?

Alexander Lipatov комментирует...

Спасибо за ссылки! Я написал первый пост в своем блоге http://jamerlan.blogspot.com/2009/03/equinox.html

Анонимный комментирует...

Отлично написано! Буду много думать…

Анонимный комментирует...

Да.. Детали это главное.

D комментирует...

Отличная статья. Хочется по-больше о настройках. Например:
вынести папку plugins в другое место как и папку configurations

Nikita Eshkeev комментирует...

Я скачал новый org.eclipse.osgi_3.10.0.v20140606-1445.jar запустил его java -jar org.eclipse.osgi_3.10.0.v20140606-144jar -console, но osgi консоль не появилась, команда просто висит, сама ничего не печатает в консоль, но и не завершается, в чем может быть проблема? JDK 1.8. библиотку скачал отсюда http://download.eclipse.org/equinox/drops/R-Luna-201406061215/index.php из раздела "Framework Only"

Pavel Samolisov комментирует...

В Equinox 3.8 функциональность консоли была по-умолчанию отключена в системном бандле, однако ее можно было задействовать с помощью указания системного свойства -Dosgi.console.enable.builtin=true. В Eclipse Luna функциональность консоли окончательно удалена из системного бандла. Чтобы подключить консоль нужно сделать следующее:

1. Скопировать бандлы
- org.apache.felix.gogo.command_0.10.0.v201209301215.jar
- org.apache.felix.gogo.runtime_0.10.0.v201209301036.jar
- org.apache.felix.gogo.shell_0.10.0.v201212101605.jar
- org.eclipse.equinox.console_1.1.0.v20140131-1639.jar
в тот же каталог, в котором расположен системный бандл.

2. Создать в корне данного каталога подкаталог configuration.

3. Создать в подкаталоге configuration файл config.ini со следующим содержимым:

osgi.bundles=org.apache.felix.gogo.command_0.10.0.v201209301215.jar@start,org.apache.felix.gogo.runtime_0.10.0.v201209301036.jar@start,org.apache.felix.gogo.shell_0.10.0.v201212101605.jar@start,org.eclipse.equinox.console_1.1.0.v20140131-1639.jar@start
eclipse.ignoreApp=true

Теперь консоль можно запускать как и прежде (команда выполняется из каталога, содержащего системный бандл):

# java -jar org.eclipse.osgi_3.10.0.v20140606-1445.jar -console -consoleLog

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

Pavel Samolisov комментирует...

Да, совсем забыл. Скачать новый Equinox SDK со всеми необходимыми модулями можно по ссылке: http://www.eclipse.org/downloads/download.php?file=/equinox/drops/R-Luna-201406061215/equinox-SDK-Luna.zip

Nikita Eshkeev комментирует...

Спасибо, все ясно

Отправить комментарий

Любой Ваш комментарий важен для меня, однако, помните, что действует предмодерация. Давайте уважать друг друга!