понедельник, 11 мая 2009 г.

Введение в OSGi. Декларативные сервисы - первое знакомство


Суровый челябинский программист вновь вышел на тропу войны. В WindowMaker запущена Opera, рядом mpd+sonata играет музло, но самое главное - запущен Eclipse, что как бы намекает. Намекает на то, что пришла пора рассказать читателям про замечательную вещь - декларативные сервисы в OSGi.

Понятно, что прежде чем один бандл будет использовать сервис, другой бандл должен его выставить. Чтобы сервис выставить, бандлу необходимо стартовать - т.е. перейти в состояние ACTIVE. Но зависимости между бандлами могут быть очень сложными (а самое худшее - циклическими), что приводит к очевидным проблемам. Для решения этих проблем некто Humberto Cervantes вместе с Richard Hall написали утилиту под названием Service Binder, которая и предназначалась для автоматического разрешения зависимостей между бандлами. Впоследствии данная утилита развилась в то, что называется Declarative Services (DS). Сами DS являются частью стандарта OSGi 4.0 и выше.


Суть DS в том, что создается дескриптор сервиса: XML-файл, который описывает сервис. Затем данный файл регистрируется в манифесте бандла. Соответственно, OSGi-среда после ресолвинга зависимостей данного бандла автоматически стартует описанные сервисы и переводит бандл в состояние ACTIVE. Естественно, что активатор бандла при этом выполняется.

Давайте разберем простейший пример бандла, регистрирующего декларативный сервис. Выполняться бандл будет в окружение equinox. Основные бандлы можно взять из вашей инсталяции Eclipse, но бандлы, поддерживающие декларативные сервисы в Eclipse не входят (пока не входят, судя по мэйл-листу разработчиков equinox в 3.5 войдут). Поэтому вот отсюда необходимо скачать org.eclipse.equinox.ds_x.x.x.vxxx.jar и org.eclipse.equinox.util_x.x.x.vxxx.jar.

Далее создаем в Eclipse PDT/Plug-in Project с названием org.beq.equinox.ds.intro. Сразу же создадим примитивный сервис - класс, который будет реализовывать интерфейс Runnable. Код сервиса будет следующим:

package org.beq.equinox.ds.intro;



/**

 *  

 * @author psamolisov

 * @since  11.05.2009

 */


public class SampleRunnable implements Runnable

{

    @Override

    public void run()

    {

        System.out.println("Hello from SampleRunnable");

    }

}


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

package org.beq.equinox.ds.intro;



import org.osgi.framework.BundleActivator;

import org.osgi.framework.BundleContext;



/**

 *  

 * @author psamolisov

 * @since  11.05.2009

 */


public class SampleActivator implements BundleActivator

{

    @Override

    public void start(BundleContext arg0) throws Exception

    {

        System.out.println("Hello, SampleActivator!");

    }



    @Override

    public void stop(BundleContext arg0) throws Exception

    {

        System.out.println("stop SampleActivator!");

    }

}

 


Теперь самое главное - необходимо сделать так, чтобы сервис регистрировался в реестре сервисов OSGi. Для этого необходимо создать дескриптор сервиса. В нашем случае описание заключается лишь в указании реализуемого интерфейса и реализующего класса. В корне проекта создаем каталог /OSGI-INF/, а в нем - файл samplerunnable.xml, следующего содержания:

<?xml version="1.0"?>

<component name="samplerunnable">

    <implementation class="org.beq.equinox.ds.intro.SampleRunnable"/>

    <service>

        <provide interface="java.lang.Runnable"/>

    </service>

</component>


Все файлы - дескрипторы сервисов - должны быть описаны в манифесте бандла. Для этого служит директива Service-Component: . В нашем случае манифест бандла будет следующим:

Manifest-Version: 1.0

Bundle-ManifestVersion: 2

Bundle-Name: Intro Plug-IN

Bundle-SymbolicName: org.beq.equinox.ds.intro

Bundle-Version: 1.0.0

Bundle-Activator: org.beq.equinox.ds.intro.SampleActivator

Require-Bundle: org.eclipse.equinox.ds;bundle-version="1.0.0",

 org.eclipse.osgi;bundle-version="3.4.3",

 org.eclipse.equinox.util;bundle-version="1.0.0"

Service-Component: OSGI-INF/samplerunnable.xml

 


Теперь необходимо все это запустить. Запускать будем через меню Run As -> OSGi Framework. Но сначала создадим конфигурацию для запуска. В конфигурации надо выбрать наш бандл org.beq.equinox.ds.intro, галочки с остальных бандлов (если они есть в вашем workspace) надо снять. Затем необходимо настроить Target Platform. Сделать это очень просто - снимаем галочки со всех бандлов, затем находим в списке бандл org.eclipse.equinox.ds, отмечаем его галочкой и нажимаем кнопку Add Required Bundles. Нажимаем Run - запускается OSGi-платформа, в консоли Eclipse появляется приглашение командной строки OSGi, а через некоторое время стартуют все необходимые бандлы, в том числе и наш, выставляющий декларативный сервис:

osgi>

Hello, SampleActivator!


Выполним команду ss:

...

1178    <<LAZY>>    org.eclipse.equinox.simpleconfigurator_1.0.0.v20080604

2865    ACTIVE      org.eclipse.equinox.util_1.0.0.v20080414

3610    ACTIVE      org.beq.equinox.ds.intro_1.0.0



osgi>


Как видим - бандл успешно стартован. Ну и самое главное - посмотрим, есть ли наш сервис в списке зарегистрированных в реестре? Выполним команду services:

osgi> services



...



{java.lang.Runnable}={component.name=samplerunnable, component.id=0, service.id=96}

  Registered BY bundle: initial@reference:file:../../../home/pavel/develop/java/_learn_equinox_workspace/org.beq.equinox.ds.intro/ [3610]

  No bundles USING service.



osgi>


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

Оставайтесь на связи!

Понравилось сообщение - подпишитесь на блог или читайте меня в twitter

1 комментарий:

Саша комментирует...

Спасибо за статью, кратко и по делу.

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

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