Не удается запустить пакет программно
Примечание: в моем случае я использую Apache Felix
реализация, если это имеет значение.
Я написал пакет, который я использую в качестве теста. Это очень простой пакет "Hello World", который не делает ничего, кроме печати сообщения stdout
когда начался / остановился:
public class Activator implements BundleActivator {
@Override
public void start(BundleContext context) throws Exception {
System.out.println("Hello, World.");
}
@Override
public void stop(BundleContext context) throws Exception {
System.out.println("Goodbye, World.");
}
}
Существует также MANIFEST
файл, который довольно бессмысленно публиковать, так как при развертывании выше связки через Apache Felix
Консоль из стандартного дистрибутива ( которую можно скачать здесь) запускается в комплекте и распечатывает сообщение.
Следующий шаг, который я пытаюсь сделать, это развернуть тот же пакет, используя программный подход. К сожалению, это не работает для меня. Мой код выглядит следующим образом:
public static void main(String[] args) throws Exception {
FrameworkFactory frameworkFactory = getFrameworkFactory();
Framework framework = frameworkFactory.newFramework(null);
System.out.println("BundleID = " + framework.getBundleId());
System.out.println("State = " + getState(framework.getState()));
framework.init();
System.out.println("BundleID = " + framework.getBundleId());
System.out.println("State = " + getState(framework.getState()));
BundleContext bundleContext = framework.getBundleContext();
bundleContext.addBundleListener((event) -> {
System.out.println("Bundle Changed Event");
});
bundleContext.addFrameworkListener((event) -> {
System.out.println("Framework Event");
});
bundleContext.addServiceListener((event) -> {
System.out.println("Service Changed Event");
});
Bundle bundle = bundleContext.installBundle("file://<absolute-path-to-bundle-jar-same-as-above");
System.out.println("BundleID = " + bundle.getBundleId());
System.out.println("State = " + getState(bundle.getState()));
bundle.start();
System.out.println("BundleID = " + bundle.getBundleId());
System.out.println("State = " + getState(bundle.getState()));
}
private static FrameworkFactory getFrameworkFactory() throws IllegalStateException {
ServiceLoader<FrameworkFactory> loader = ServiceLoader.load(FrameworkFactory.class);
FrameworkFactory factory = null;
for (FrameworkFactory iterator : loader) {
if (factory != null) {
throw new IllegalStateException("Ambiguous SPI implementations.");
}
factory = iterator;
}
return factory;
}
private static String getState(int state) {
switch (state) {
case Bundle.UNINSTALLED:
return "UNINSTALLED";
case Bundle.INSTALLED:
return "INSTALLED";
case Bundle.RESOLVED:
return "RESOLVED";
case Bundle.STARTING:
return "STARTING";
case Bundle.STOPPING:
return "STOPPING";
case Bundle.ACTIVE:
return "ACTIVE";
default:
throw new IllegalStateException("Unknown state");
}
}
Вывод выглядит следующим образом:
BundleID = 0
State = INSTALLED
BundleID = 0
State = STARTING
Bundle Changed Event
BundleID = 1
State = INSTALLED
BundleID = 1
State = INSTALLED
Насколько я понимаю, пакет был установлен, но последние 4 строки показывают, что bundle.start()
был проигнорирован по какой-то причине.
Не могли бы вы указать мне, что мне не хватает, чтобы сделать эту работу?
1 ответ
После часа отладки и чтения javadoc
более тщательно это происходит, потому что фреймворк был только инициализирован, а не запущен. Чтобы пример работал, нужно просто добавить framework.start()
после framework.init()
(или просто позвоните framwork.start()
какие звонки framework.init()
если посчитал это необходимым).
Я оставляю эту информацию, так как есть несколько запутанных вещей:
- Официальная документация для
Apache Felix
иметь информацию о встраивании фреймворка в хост-приложение. К сожалению, есть только один пример, который используютApache Felix
пользовательские механизмы, которые делают его не переносимым на другие реализации. Что сбивает с толку, так это предупреждение, которое, если вы хотите создать портативное решение, вы должны использоватьinit()
а такжеgetBundleContext()
, Целая нота, цитируемая ниже:
ВНИМАНИЕ
felix.systembundle.activators
Свойство конфигурации зависит от реализации инфраструктуры Felix. Если вы хотите, чтобы ваш код работал с другими реализациями фреймворка, вам следует вызватьinit()
на экземпляре платформы и использованияgetBundleContext()
непосредственно. В противном случае подход был бы очень похожим.
- JavaDoc для версии без параметров
init()
Метод, не упоминающий об инициализации, отличается от запуска фреймворка, хотяinit(FrameworkListener...)
есть такая информация.
Эта платформа на самом деле не будет запущена, пока не будет вызван запуск.