410013796724260
• Webmoney
R335386147728
Z369087728698
Felix Framework в OSGi приложенииСоздание OSGi приложения начинается с Framework'a. Сначала создается и инициализируется объект Framework, после чего можно загружать в автоматическом (запрограммированном) или ручном (по команде) режиме плагины/сервисы, именуемые согласно спецификации OSGi бандлы (Bundle). Объект Framework, иначе называемый также System Bundle, наследует свойства Bundle, описанные на странице спецификации OSGi. Для создания объекта Framework используется класс FrameworkFactory. Ниже представлен код создания Felix Framework'a и загрузки бандлов. private ServiceLoader<FrameworkFactory> serviceLoader; private Framework framework; private File[] bundles; ... serviceLoader = ServiceLoader.load(FrameworkFactory.class); FrameworkFactory factory = serviceLoader.iterator().next(); if (factory != null) { Map<String, String> props = new HashMap<String, String>(); props.put("org.osgi.framework.storage", "bundles-cache"); props.put("org.osgi.framework.storage.clean", "onFirstInit"); // props.put("org.osgi.framework.storage.clean", "none"); framework = factory.newFramework(props); } if (framework != null) { // Прежде чем фреймворк можно будет использовать // его необходимо инициализировать framework.init(); // После инициализации framework может предоставить // Bundle Context для регистрации бандлов и сервисов BundleContext context = framework.getBundleContext(); // Инсталляция бандлов for (File bundle : bundles ) context.installBundle(bundle.toURL().toString()); framework.start(); } Для создания фреймворка используется метод newFramework класса FrameworkFactory. Метод в качестве параметра получает коллекцию Map<String, String> для определения конфигурации фреймворка. В примере определяется свойство "org.osgi.framework.storage" со значением "bundles-cache". При инсталляции фреймворк создаст директорию "bundles-cache"" с набором поддиректорий, которая будет использоваться в качестве хранилища бандлов. Свойство "org.osgi.framework.storage.clean" позволяет определить режим инсталляции. Если в качестве значения выбрать "onFirstInit", то фреймворк будет стартовать как в первый раз и поддиректория "bundles-cache" будет обновляться, в противном случае при значении "none" будут использоваться настройки от предыдущего старта. По умолчанию Felix Framework создаёт директорию "felix-cache" для хранилища бандлов, если не определить параметр метода FrameworkFactory, т.е. передать значение props=null. Примечание : фреймворк Equinox от IDE Eclipse для работы с бандлами использует директорию "configuration". Жизненный цикл OSGi FrameworkOSGi Framework от момента создания и до окончательного останова проходит определенные стадии жизненного цикла, диаграмма состояний которого представлена на следующем рисунке. Сразу же после создания Framework попадает в состояние INSTALLED. В этом состоянии Framework не активный и не может «предоставить» Bundle Context для регистрации bundle. С этого момента можно изменить состояние Framework'а с использованием различных методов :
Метод waitForStopOSGi Framework функционирует в multi-threaded окружении. После своего старта он инсталлирует и стартует бандлы. Активированный бандл стартует поток Thread или «отвечает» на запрос другого бандла после завершения метода start, т.е. находясь в состоянии ACTIVE. Для остановки фреймворка вместе с бандлами необходимо использовать метод waitForStop(long), который содержит обработчик очистки загрузчика после того, как фреймворк будет полностью остановлен. Данный метод блокирует фреймворк до полной его остановки и возвращает одно из событий, показывающего причину остановки :
Пример Framework'a в OSGi приложенииРассмотрим пример создания фреймворка Apache Felix и перевод его в различные состояния от создания и до останова. Для разработки OSGi приложения будет использован фреймворк Maven. Структура приложения представлена на следующем скриншоте. Согласно представленной структуре приложение включает классы FrameworkExample.java, FrameworkTest.java и проектный файл pom.xml, в котором определены все необходимые зависимости для разработки, тестирования и сборки. Основным классом приложения является FrameworkExample.java, в котором создается фреймворк и инсталлируются бандлы. Приложение будет работать в консольном варианте и вся информация будет выводиться в консоль. FrameworkTest.java используется для тестирования фреймворка. В поддиректории "bundles" размещены два бандла, рассмотренные на странице ресурсов OSGi. После создания фреймворка они будут инсталлированы в контейнер. Создание фреймворкаFramework framework = null; String cache = "bundles-cache"; private void createFramework() { ServiceLoader<FrameworkFactory> serviceLoader; ServiceLoader.load(FrameworkFactory.class); FrameworkFactory factory = serviceLoader.iterator().next(); try { if (factory != null) { Map<String, Stringg> props = new HashMap<String, String>(); props.put("org.osgi.framework.storage", cache); props.put("org.osgi.framework.storage.clean","onFirstInit"); framework = factory.newFramework(props); if (framework != null) { System.out.println ("framework is created"); printBundleParams(framework, "Framework"); } } } catch(Exception e){ System.err.println ("Create Framework Exception : " + e.getMessage()); } } В результате выполнения процедуры createFramework будет создан фреймворк и хранилище бандлов "bundles-cache", в котором framework создаст свою поддиректорию bundle0. После создания фреймворка инициализируем его методом init и стартуем (метод start). Таким образом фреймворк переходит в состояние ACTIVE. Инсталляция бандловПри нахождении фреймворка в состояние ACTIVE можно инсталлировать бандлы, описанные в переменной files (см. код ниже). Процедура загрузки бандлов loadBundles в цикле проверяет наличие соответствующего файла, формирует адрес url и инсталлирует бандл в контейнер с использованием метода installBundle объекта BundleContext. String[] files = {"bundles/bundle-locale-1.0.0.jar", "bundles/bundle-resource-1.0.0.jar"}; private void loadBundles() { BundleContext ctx = framework.getBundleContext(); Bundle bundle; String MSG_TEMPL = "Bundle <%s> installed"; try { for (int i = 0; i < files.length; i++) { File file = new File (files[i]); if (file.exists()) { String location = file.toURI().toURL().toString(); bundle = ctx.installBundle(location); if (bundle != null) { String msg=String.format(MSG_TEMPL,file.getName()); System.out.println (msg); printBundleParams(bundle, "Bundle"); } } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (BundleException e) { e.printStackTrace(); } } Для каждого инсталлируемого в контейнер бандла фреймворк создает в хранилище отдельную поддиректорию (bundle1, bundle2). Определение зависимостей в pom.xmlВ проектном файле pom.xml необходимо определить зависимости фреймворка Apache Felix, который используется в приложении. Обратите внимание, что подключается версия фреймворка 5.6.1 и все связанные (необходимые для его функционирования) библиотеки. <dependencies> <dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.core</artifactId> <version>6.0.0</version> </dependency> <dependency> <groupId>org.apache.felix</groupId> <artifactId>org.apache.felix.framework</artifactId> <version>5.6.1</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.apache.felix</groupId> <artifactId>org.apache.felix.resolver</artifactId> <version>1.12.0</version> </dependency> <dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.annotation</artifactId> <version>6.0.0</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> Сообщения в консолиВ результате работы приложения в консоль будет выведена следующая информация о состояниях фреймворка и инсталляции бандлов. Create framework ... framework is created Framework state : INSTALLED Version = 5.6.1 SymbolicName = org.apache.felix.framework Location = System Bundle BundleId = 0 Framework state : INSTALLED Wait for stop event expected frameworkEvent = STOPPED Framework init ... Framework state : STARTING framework.getBundleContext() not NULL Framework start ... framework.getBundleContext() not NULL Framework state : ACTIVE Load bundles ... Bundle <bundle-locale-1.0.0.jar> installed Bundle state : INSTALLED Version = 1.0.0 SymbolicName = com.osgi.bundle.locale Location = file:/D:/framework-example/bundles/bundle-locale-1.0.0.jar BundleId = 1 Bundle <bundle-resource-1.0.0.jar> installed Bundle state : INSTALLED Version = 1.0.0 SymbolicName = com.osgi.resources.resource Location=file:/D:/framework-example/bundles/bundle-resource-1.0.0.jar BundleId = 1 Enter exit : exit Framework stop ... Framework state before stop Framework state : ACTIVE FrameworkEvent STOPPED framework.getBundleContext() is NULL Framework state : RESOLVED Framework update ... Framework state : RESOLVED Wait for stop event expected frameworkEvent = STOPPED После инсталляции бандлов приложение останавливается и просит ввести «exit», чтобы завершить работу. Скачать исходный кодИсходный код рассмотренного примера создания фреймворка Felix Framework, перевода его в различные состояния и инсталляции бандлов в OSGi контейнер можно скачать здесь (938 Кб). На странице Механизм publish/subscribe в OSGi представлен пример использования публикации/подписки с использованием фреймворка Felix. В разделе JaBricks представлено описание многомодульного OSGi-приложения с фреймворком Felix. |