Суровый челябинский программист вновь вышел на тропу войны. В 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");
}
}
/**
*
* @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!");
}
}
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>
<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
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!
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>
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>
...
{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 комментарий:
Спасибо за статью, кратко и по делу.
Отправить комментарий
Любой Ваш комментарий важен для меня, однако, помните, что действует предмодерация. Давайте уважать друг друга!