У меня есть служба, требующая настройки
@Component(service=InstrumenterService.class ,configurationPid = "InstrumenterService", configurationPolicy = ConfigurationPolicy.REQUIRE, scope = ServiceScope.PROTOTYPE)
public class InstrumenterService
На эту службу ссылается другая служба:
@Component(service = SampleService.class, scope = ServiceScope.PROTOTYPE)
public class SampleService {
@Reference(cardinality = ReferenceCardinality.OPTIONAL, scope = ReferenceScope.PROTOTYPE_REQUIRED, policyOption = ReferencePolicyOption.GREEDY)
InstrumenterService coverageInstrumenter;
public boolean hasInstrumenter() {
if(coverageInstrumenter == null)
return false;
return true;
}
}
Этот SampleService используется внутри класса Main, подключенного к основному потоку osgi. Я использую ComponentServiceObjects, так как хочу создавать SampleServices по требованию.
@Component(immediate = true, property = "main.thread=true")
public class Main implements Runnable {
@Reference
ConfigurationAdmin cfgAdm;
@Reference(scope = ReferenceScope.PROTOTYPE_REQUIRED)
private ComponentServiceObjects<SampleService> sampleServices;
public void run() {
if (cfgAdm != null) {
Configuration configuration;
try {
configuration = cfgAdm.getConfiguration("InstrumenterService", "?");
Hashtable<String, Object> props = new Hashtable<>();
props.put("some_prop", "some_value");
configuration.update(props);
} catch (IOException e1) {
e1.printStackTrace();
}
}
SampleService servicess = sampleServices.getService();
System.out.println(servicess.hasInstrumenter());
}
}
У меня проблема в том, что конфигурация, установленная ConfigurationAdmin, не отображается в InstrumenterService, если я не поставлю Thread.sleep(500); команда после вызова configuration.update.
Мне не очень удобно использовать команду Thread.sleep, чтобы убедиться, что обновление конфигурации видно. Есть ли API для проверки того, что конфигурация была обновлена и доступна для использования?
Благодаря Нилу я смог найти работоспособное решение. Я использовал ServiceTracker после того, как конфигурация была настроена на ожидание службы:
BundleContext bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext();
ServiceTracker serviceTracker = new ServiceTracker(bundleContext, InstrumenterService.class.getName(), null);
serviceTracker.open();
try {
serviceTracker.waitForService(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
serviceTracker.close();
Причина, по которой мне понадобился ConfigurationAdmin, в первую очередь заключается в том, что существует интерфейс IInstrumenter, который может быть реализован многими различными классами. Имя этого инструментера задается в ConfigurationAdmin, а затем в других сервисах требуемый сервис инструмента извлекается "автоматически".
Таким образом, в приложение можно добавить любое количество приборов, и для его использования необходимо знать только имя прибора.
Я также хочу упомянуть, что с OSGI нам удалось разделить наше монолитное унаследованное приложение на большее количество модулей (~ 15), и они не зависят напрямую друг от друга, а используют слой API.
Еще раз спасибо за хорошую работу, которую вы делаете с OSGI.