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

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

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

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


person sfussenegger    schedule 19.07.2013    source источник
comment
Это интересная проблема, которая становится еще сложнее, если вы хотите разрешить пакетам использовать обнаруживаемые параметры командной строки (что было нашим вариантом использования). Увы, наше окончательное решение было довольно тяжеловесным, и у меня еще не было времени превратить его во что-то полезное для других…   -  person Donal Fellows    schedule 22.07.2013


Ответы (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-файл завершен, он содержит ВСЕ пакеты, фреймворк, средство запуска и свойства для его запуска. Внешних зависимостей нет.

Хитрость заключается в том, чтобы получить основной поток (где вызывается static main). Единственное, что вам нужно сделать, это зарегистрировать службу 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.

P.S. В последнем bnd вы можете использовать Callable‹Integer› вместо Runnable. Возвращаемое значение является кодом выхода процесса. Однако этого может еще не быть в bndtools.

person Peter Kriens    schedule 19.07.2013
comment
Спасибо за Ваш ответ. Это действительно звучит довольно просто. Вы случайно не знаете, открыта ли команда package плагином maven-bundle-plugin? - person sfussenegger; 19.07.2013
comment
Что вы имеете в виду под Object.class? Его нужно просто удалить, сделав его обычным сеттером, верно? - person sfussenegger; 19.07.2013
comment
Я думаю, что это должен быть параметр объекта. К сожалению, вы не можете просто удалить его, хотя вас интересует только параметр карты. - person Neil Bartlett; 19.07.2013
comment
Команда package доступна только в (bnd)tools - person Peter Kriens; 22.07.2013

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

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

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

person sfussenegger    schedule 19.07.2013