Не удается запустить пакет программно

Примечание: в моем случае я использую 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() если посчитал это необходимым).

Я оставляю эту информацию, так как есть несколько запутанных вещей:

  1. Официальная документация для Apache Felix иметь информацию о встраивании фреймворка в хост-приложение. К сожалению, есть только один пример, который используют Apache Felix пользовательские механизмы, которые делают его не переносимым на другие реализации. Что сбивает с толку, так это предупреждение, которое, если вы хотите создать портативное решение, вы должны использовать init() а также getBundleContext(), Целая нота, цитируемая ниже:

ВНИМАНИЕ felix.systembundle.activators Свойство конфигурации зависит от реализации инфраструктуры Felix. Если вы хотите, чтобы ваш код работал с другими реализациями фреймворка, вам следует вызвать init() на экземпляре платформы и использования getBundleContext() непосредственно. В противном случае подход был бы очень похожим.

  1. JavaDoc для версии без параметров init() Метод, не упоминающий об инициализации, отличается от запуска фреймворка, хотя init(FrameworkListener...) есть такая информация.

Эта платформа на самом деле не будет запущена, пока не будет вызван запуск.

Другие вопросы по тегам