OSGI: становятся ли декларативные сервисы доступными после запуска пакета

Вопрос простой, но я не могу найти ответ - Могу ли я утверждать, что все декларативные сервисы в пакете А становятся доступными после запуска пакета А? Например,

bundle=context.installBundle("file:bundleA-1.0.0.jar");
bundle.start();
//In this point are declarative services of bundle A 100% available?

P.S. Я использую apache felix, но я думаю, что это должно быть определено в спецификациях, а не в реализации.

EDIT:
Я предполагаю, что среда выполнения DS запущена, присутствует конфигурация и присутствуют все обязательные ссылки.


person Pavel_K    schedule 07.08.2016    source источник
comment
Это множество предположений, которые вы действительно не в состоянии сделать.   -  person Neil Bartlett    schedule 08.08.2016


Ответы (2)


Ответ на ваш вопрос очень прост: НЕТ. Нет никаких гарантий доступности в OSGi, когда-либо основанных ни на времени, ни на порядке. Единственные гарантии указываются в сервисных событиях.

Делать допущения о времени/порядке в вашем коде — одна из самых больших причин сложности, потому что они всегда нарушаются самым непонятным образом.

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

В вашем примере просто полагайтесь на услугу, которая вам нужна. Если эта служба доступна, вы уверены, что вся инициализация выполнена.

Если вы придерживаетесь сервисных зависимостей, жизнь в OSGi довольно проста и очень надежна.

ОБНОВЛЕНО с примером после вопросов

Одна сторона, не поддерживающая OSGi:

 systemBundleContext = ... create framework
 systemBundleContext.registerService( 
    BundleActivator.class, 
    new BundleActivator() {
        public void start(BundleContext c) {
           // start non-OSGi code
        }
        public void stop(BundleContext c) {
           // stop non-OSGi code
        }
     },
     null );

Компонент ДС:

 @Component
 public class Initiator {
    @Reference
    BundleActivator ba;

    @Referenc
    MyService myService;

    @Activate void activate(BundleContext context) throws Exception {
      ba.start(context);
    }

    @Deactivate void deactivate(BundleContext context) throws Exception {
      ba.stop(context);
    }
 }      
person Peter Kriens    schedule 08.08.2016
comment
Допустим, у меня есть только один декларативный сервис - сервис А. И мне нужно использовать этот сервис в обычном коде, а не в других osgi-сервисах. Я правильно понимаю, что в такой ситуации единственный выход - использовать сервис-трекер? - person Pavel_K; 08.08.2016
comment
ServiceTracker может работать, но есть гораздо более простое решение. Проблема заключается в контроле (который я считаю одним из самых интересных и наименее обсуждаемых аспектов написания кода). Что я, вероятно, сделал бы, так это зарегистрировал службу BundleActivator на стороне, отличной от OSGi, а затем создал непосредственный компонент DS на стороне OSGi с соответствующими зависимостями. Этот компонент вызывает стороннюю службу платформы при активации/деактивации. Таким образом, вы получаете контроль на стороне DS, а сторона, не поддерживающая OSGi, следует за ним. - person Peter Kriens; 08.08.2016
comment
Я несколько раз читал ваш комментарий... но... не могли бы вы привести пример в коде, что вы имеете в виду? - person Pavel_K; 08.08.2016
comment
Большое спасибо, теперь мне нужно понять ваш код. Извините за мои вопросы... После вашего кода я думаю, что вообще не знаю osgi. Что такое фреймворк? Какой это класс? - person Pavel_K; 08.08.2016
comment
Тогда я мог неправильно понять ваш вопрос. Я так понял, вы запускаете код как пакеты и код, который работает вне фреймворка. Если весь ваш код работает как пакет, то почему бы просто не использовать DS? - person Peter Kriens; 08.08.2016
comment
Ok. Я дам подробности. У меня код не osgi. Этот код без osgi запускает инфраструктуру osgi (felix), после чего устанавливает и запускает один пакет — пакет A. В пакете A есть DS. Как я могу вне фреймворка osgi (в моем коде, отличном от osgi) быть уверенным, что DS из пакета A доступный ? - person Pavel_K; 08.08.2016
comment
Так что мой пример кода делает именно это. Объект фреймворка — это контекст пакета, который вы получаете для системного пакета при создании фреймворка Felix OSGi. - person Peter Kriens; 08.08.2016
comment
Большое спасибо. Это то, что мне нужно (но я еще не проверял). Я предлагаю вам отредактировать свой ответ и вместо framework написать BundleContext systemBundleContext - person Pavel_K; 08.08.2016

Нельзя предполагать, что все компоненты DS будут доступны как службы после запуска пакета. Во-первых, должна быть запущена среда выполнения DS. Тогда компоненты DS по умолчанию активируются лениво. Это означает, что они активны только тогда, когда какой-либо другой пакет требует такой службы, и, что не менее важно, компоненты активируются только после того, как присутствуют все их обязательные ссылки. Ну ... и пока я не забыл, вы также можете определить, что компонент активируется только в том случае, если для него присутствует конфигурация.

person Christian Schneider    schedule 07.08.2016
comment
В этом случае причиной остается только ленивая загрузка. Вы используете немедленно = true? - person Christian Schneider; 08.08.2016
comment
Я думаю, что есть разница между доступным сервисом и сервисом с созданным экземпляром. Когда я говорю «доступно», я имею в виду, что если эта служба необходима, то структура OSGI создаст ее экземпляры. - person Pavel_K; 08.08.2016
comment
Честно говоря, я немного смущен тем, что вы действительно спрашиваете. Это просто теоретический вопрос или у вас есть конкретная служба, которая, похоже, не запускается. - person Christian Schneider; 08.08.2016