Как написать приложение командной строки OSGI

В настоящее время я намочил ноги от OSGI и решил пойти на слегка нетипичный сценарий использования OSGI. Я хотел бы использовать его в приложении командной строки. я хочу main(..) метод, который принимает некоторые флаги и аргументы, что-то делает и снова выключается. Чего я не хочу, так это запускать Apache Karaf (или аналогичный) и запускать команды в консоли OSGI (хотя это может стать дополнительной функцией).

Почему OSGI для приложения командной строки в первую очередь? Предполагается, что приложение будет использовать разные версии одной и той же библиотеки (то есть эластичного поиска). И просто потому, что это плохо, конечно.

Должен ли я использовать услугу в комплекте или снаружи? Как можно это сделать? Какие проблемы могут возникнуть?

2 ответа

Решение

Существует очень простой способ написания приложений командной строки при использовании bnd. В bnd есть функция для создания исполняемого файла jar с помощью команды package:

 $ bnd run xyz.bnd
 .... whatever your app does
 $ bnd package xyz.bnd
 $ ls
   xyz.jar  xyz.bnd .....
 $ java -jar xyz.jar ...
 .... whatever your app does

Обратите внимание, что этот файл jar завершен, он содержит ВСЕ пакеты, фреймворк, модуль запуска и свойства для его запуска. Нет внешних зависимостей.

Хитрость заключается в том, чтобы получить основной поток (где вызывается статический основной). Единственное, что вам нужно сделать, это зарегистрировать сервис Runnable со свойством main.thread=true, После этого программа запуска вызовет run() для этой службы и завершит работу (вы можете оставаться в беге столько времени, сколько захотите).

Чтобы получить аргументы командной строки, вы можете получить сервис Object с launcher.arguments имущество. Это свойство будет иметь аргументы вашей команды. Или сделать это с помощью компонента DS:

 @Component(immediate=true, property="main.thread=true")
 public class Main implements Runnable {
     String[] args;

     public void run(){ ... }

     @Reference(target="(launcher.arguments=*)")
     void setArgs(Object service, Map<String,Object> props) {
        this.args = (String[]) props.get("launcher.arguments");
     }
 }

Лучший способ сделать это - использовать bndtools, поскольку он позволяет легко тестировать / отлаживать ваш код. Вы, вероятно, хотите использовать файлы bndrun.

PS В последней версии bnd вы можете использовать Callable вместо Runnable. Тогда возвращаемое значение является кодом выхода процесса. Это может, однако, еще не присутствовать в bndtools.

Чтобы ответить на мой собственный вопрос ( стиль вопросов и ответов): в настоящее время я считаю, что было бы лучше

  1. запустить OSGI встроенный (чистый)
  2. запустить контейнер
  3. пакет API экспорта (org.osgi.framework.system.packages.extra)
  4. установить и запустить необходимые пакеты
  5. потреблять услуги за пределами OSGI
  6. закрыть контейнер
  7. выйти из приложения

После запуска всех пакетов можно с уверенностью предположить, что необходимые сервисы доступны. Это также позволяет избежать передачи конфигурации в OSGI, который фактически является только аргументами для вызова службы.

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