У меня есть служба, которая требует настройки
@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.