ServiceTracker не находит существующий сервис - PullRequest
2 голосов
/ 20 марта 2011

Я использую ServiceTracker для размещения зарегистрированных сервисов в нашей среде OSGi. Я получил этот код в методе запуска Bundle Activator:

    logger.debug("looking for MyService");
    tracker = new ServiceTracker(ctx, MyService.class.getName(), null);
    tracker.open();
    MyService = ((MyService)tracker.getService());
    if (MyService != null)
    {
        logger.debug("found MyService");
    }

Проблема заключается в следующем:

  • Если я установлю и запу сервис можно найти и использовать.
  • Если я полностью перезапущу OSGi, MyService не сможет найден моим пакетом (то есть NULL), хотя это мой пакет находится в состоянии ACTIVE.
  • Если я остановлю / начну свой пакет MyService можно найти и использовать снова.

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

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

Это указывает на то, что если я перечислю доступные службы, используя

ServiceReference[] ref = tracker.getServiceReferences();

он не находит сервисы после перезапуска OSGi, но находит MyService после того, как я остановил / запустил свой пакет, который его ищет.

Я пытался установить ссылку Require-Bundle на пакет, в котором находится MyService, надеясь, что платформа OSGi распознает зависимость, но это не помогло.

Есть идеи ...?

Ответы [ 3 ]

4 голосов
/ 20 марта 2011

Если вы используете ServiceTracker из BundleActivator, вы фактически замораживаете весь фреймворк (поэтому другие пакеты не могут быть запущены одновременно). Если пакет, который предоставляет вашу услугу, запускается после пакета с трекером, вы не увидите службу. Это объясняет, почему остановка и запуск вашего комплекта позже дает вам ваши услуги.

Теперь, если вы хотите отслеживать и использовать сервис, я бы создал новый поток для этого и использовал бы waitForService вместо getService.

2 голосов
/ 21 марта 2011

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

Другая идея - рассмотреть возможность использования декларативных сервисов для управления зависимостями сервисов.

1 голос
/ 02 апреля 2011

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

Класс ServiceTracker принимает ServiceTrackerCustomizer (и сам по себе), который уведомляется, когда службы приходят и уходят.

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

// In BundleActivator.start:
this.serviceTracker = new ServiceTracker(bundleContext, MyService.class.getName(), null) {
    public Object addingService(ServiceReference reference) {
        // Get the service
        final MyService service = (MyService)this.context.getService(reference);

        // Do something with the service (e.g. inject it somewhere)
        // ...

        // Return the service to track it
        return service;
    }

    public void removedService(ServiceReference reference, Object service) {
        // Stop using the service (e.g. notify the objects that use it)
        // ...

        // Unget the service (very important!)
        this.context.unget(reference);
    }
}

Обратите внимание, что мы отслеживаем только сервисы MyService и не используем настройщик (мы передаем null кактретий параметр для конструктора), но вместо этого переопределите два важных метода.Другим важным методом является modifiedService;пожалуйста, прочитайте Javadoc для получения дополнительной информации.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...