OSGi: допустимо ли регистрировать сервисы в рамках декларативного метода активации сервисного компонента? - PullRequest
3 голосов
/ 19 апреля 2011

Это дубликат другого вопроса, но копируется из другого:

Я столкнулся с проблемой с SCR Феликса, где я получаю сообщение:

ServiceFactory.getService () результатом был цикл

Причина, по которой это происходит, заключается в том, что в методе активации, называемом ServiceAImpl (который предоставляет ServiceA), служба регистрирует другую службу, называемую ServiceB.У меня есть другой компонент службы, назовите его ServiceCImpl, который зависит как от ServiceA, так и от ServiceB.Благодаря ServiceAImpl, регистрирующему ServiceB, ServiceCImpl удовлетворяется, и в рамках одного и того же вызова для активации ServiceAImpl вызываются методы привязки ServiceCImpl.Когда вызывается метод привязки для ServiceA, цикл обнаруживается, и компонент не может инициализироваться.

Может быть, есть способ позволить SCR ждать, чтобы связать ServiceCImpl, или, возможно, мне нужно зарегистрировать ServiceB по-другому?

Я думаю, что не имеет смысла, почему Felix SCR будет активировать ServiceCImpl в рамках метода активации ServiceAImpl.Я не думаю, что ServiceCImpl будет считаться удовлетворенным до тех пор, пока не завершится метод активации.Возможно, это проблема использования декларативных сервисов при одновременной регистрации сервисов непосредственно в платформе?

Не пробовали другие реализации SCR, такие как версия Equinox, но я мог бы попробовать это, чтобы увидеть, есть ли разница, номожет, кто-нибудь знает, является ли это OSGi или Felix?

Дополнительная информация: почему ServiceB не является компонентом службы ... ServiceA фактически имеет ссылку на службу 0..n для другой службы,Назовите это ServiceD.Каждый раз, когда компонент ServiceD предоставляет интерфейс, ServiceB регистрируется с использованием одного и того же объекта службы.Обычно один и тот же поставщик ServiceD может предоставлять ServiceB, но идея состоит в том, чтобы сделать общий интерфейс для разработчиков более упрощенным, чтобы им не приходилось предоставлять несколько интерфейсов служб (кроме того, ServiceB имеет некоторые свойства, которые устанавливаются автоматически, что должно бытьсделано вручную и, возможно, может быть сделано неправильно).

Ответы [ 2 ]

2 голосов
/ 22 апреля 2011

Причина, по которой это происходит, заключается в том, что ServiceAImpl является отложенным компонентом, который уже был загружен, поэтому ServiceA фактически уже зарегистрирован до того, как компонент будет активирован.Однако, когда появляется другой компонент, которому требуется ServiceA, это приводит к активации ServiceAImpl.Частью процесса активации ServiceAImpl является регистрация ServiceB, которая немедленно вызывает активацию ServiceCImpl.В FELIX-2368 было внесено изменение, чтобы немедленно активировать компонент, сделав большинство операций SCR синхронными.

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

0 голосов
/ 21 апреля 2011

Я попытался воссоздать этот сценарий с небольшим набором тестовых пакетов и ProSyst OSGi FW. Однако, если я регистрирую сервис в DS, я не могу зарегистрировать другой сервис из метода activ (). Если я просто использую DS для получения услуг, я могу зарегистрировать службы как обычно. Так что, вероятно, действительно проблема с DS / SCR ...

Пример:

public class ServiceAImpl implements ServiceA, ServiceB, ManagedService {

public void activate(ComponentContext _context) {
    _context.getBundleContext().registerService(
            ManagedService.class.getName(),
            this,
            null);
    _context.getBundleContext().registerService(
            ServiceB.class.getName(),
            this,
            null);
}


@Override
public void doA() {
    System.out.println("Doing A Stuff");

}


@Override
public void doB() {
    System.out.println("Doing B Stuff");
}


@Override
public void updated(Dictionary arg0) throws ConfigurationException {

}

} Этот класс зарегистрирует 2 службы (ServiceB, ManagedService) с этим bnd. файл:

Private-Package: org.test.impl
Service-Component: org.test.impl.ServiceAImpl
Bundle-Category: test

, но только 1 услуга (ServiceA) с этим образцом: #

Private-Package: org.test.impl
Service-Component: org.test.impl.ServiceAImpl;provide:=org.test.ServiceA
Bundle-Category: test

Так что, вероятно, вам следует / нужно попытаться зарегистрировать сервисы либо через DS / SCR, либо «классическим способом» через контекст пакета.

...