Архитектура сервисов OSGi: создание сервиса по запросу потребителя

Я разрабатываю приложение в Eclipse RCP. Мне нужна помощь с дизайнерским решением относительно дизайна услуги.

У меня есть несколько пакетов, которые используются для предоставления объекта REngineдругим модулям. REngine— это интерфейс к механизму вычислений, который может быть реализован несколькими способами. Пакеты предоставляют экземпляры REngine путем подключения к удаленному серверу или запуска локального потока вычислений. Некоторые пакеты требуют настройки с помощью графического интерфейса (но также должны быть доступны на безголовой платформе). Клиентский пакет может запросить несколько объектов REngineдля параллельных вычислений.

В настоящее время я регистрирую эти модули для предоставления службы REngine. Служба создается ServiceFactory, которая либо запускает локальный экземпляр расчета, либо удаленный (серверный) экземпляр. Клиент несет ответственность за опробование всех регистраций службы класса REngineи выбор правильной.

Код для этого можно резюмировать следующим образом:

class API.REngine { ... }

class REngineProvider.Activator {
    public void start(BundleContext ctx) {
      ctx.registerService(REngine.class.getName(), new REngineFactory(), null);
    }
}
class REngineProvider.REngineFactory implements ServiceFactory {
    public Object getService(Bundle bundle, ServiceReference reference) {
      return new MyREngineImplementation();
    }
    public void ungetService(REngine service) {
       service.releaseAssociatedResources();
    }
}

class RConsumer.Class {
    REngine getREngine() {
        ServiceReference[] references = bundleContext.getAllServiceReferences(REngine.class.getName(), null);
        for(ServiceReference ref: references) {
            try {
            return bundleContext.getService(ref);
            } catch (Exception e) {} // too bad, try the next one
        }
    }
}

Я хотел бы сохранить эту модель. Приятно, что спецификация службы OSGi соответствует моему бизнес-требованию, согласно которому объекты REngine являются живыми объектами, которые следует освобождать, когда они больше не нужны.

Однако зарегистрированная услуга может предоставлять только один экземпляр услуги на пакет.При втором запросе службы возвращается кэшированный экземпляр (вместо создания нового). Это не соответствует моему требованию; пакет должен иметь возможность получать несколько объектов REngine от одного и того же поставщика.

Я уже просмотрел другие классы фреймворка OSGi, но ничего не помогает. Альтернативой является модель доски, но кажется странным регистрировать REngineRequestService, который используется пакетом REngineProvider для выдачи живого REngine.

Как реализовать это в OSGi? Напомню, вот мой список требований:

  1. Легкое включение и отключение пакетов REngineProvider. Вместо этого клиентский код будет использовать другого поставщика.
  2. Конфигурация пакетов REngineProvider.
  3. Несколько экземпляров REngineна клиентский комплект.
  4. Явный выпуск экземпляров REngine
  5. Создание REngineможет завершиться ошибкой. Клиентский модуль должен знать причину.

Просто добавлю решение, которое я выбрал в качестве ссылки на будущее. Кажется, что платформа OSGi Services не предназначена для «запроса услуги». Именно пакет провайдера создает сервис, а пакет клиента может находить и использовать сервисы. Невозможно предоставить автоматическую «Фабрику» услуг по запросу пользователя.

Выбранное решение включает в себя модель доски OSGi. На первый взгляд это может показаться очень сложным, но Blueprintможет очень помочь!

Схема поставщика.xml:


  
              
  

Класс REngineRequest— это общий класс API, позволяющий провайдеру вводить свой объект REngine или устанавливать исключение, объясняющее, почему создание не сработало.

Для клиента использовать REngine теперь так же просто, как и делать:

REngineRequest req = new REngineRequest();
ServiceRegistration reg = bundleContext.registerService(req, REngineRequest.class.getName(), engineCreationProperties);
req.getEngine().doSomeStuff();
reg.unregister();

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

5
задан parasietje 29 March 2012 в 10:52
поделиться