如何编写OSGI命令行应用程序



我目前正被OSGI弄湿,并决定使用一个稍微非典型的OSGI用例。我想在命令行应用程序中使用它。我想要一个main(..)方法,它接受一些标志和参数,执行一些操作并再次关闭。我不想启动ApacheKaraf(或类似的)并在OSGI控制台中运行命令(不过这可能会成为一个可选功能)。

为什么OSGI首先用于命令行应用程序?应用程序应该使用同一库的不同版本(即弹性搜索)。当然,这只是因为它很糟糕。

我应该在捆绑包内还是在外部使用服务?一个人会怎么做?可能会出现什么问题?

使用bnd时,有一种非常简单的方法可以编写命令行应用程序。bnd有一个用package命令创建可执行jar的功能:

 $ 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是完整的,它包含所有的bundle、框架、启动器和运行它的属性。没有外部依赖关系。

诀窍是获取主线程(在其中调用静态main)。您只需要注册一个具有属性main.thread=true的Runnable服务。然后,启动器将在此服务上调用run(),然后退出(您可以在运行中停留多久)。

要获取命令行参数,可以获取具有launcher.arguments属性的Object服务。此属性将包含您的命令参数。或者使用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文件。

附言:在最新的bnd中,您可以使用Callable<整数>而不是Runnable。返回值就是进程的退出代码。然而,这可能还没有出现在bndtools中。

回答我自己的问题(问答风格):我目前认为最好是

  1. 启动嵌入的OSGI(clean)
  2. 启动容器
  3. 导出API程序包(org.osgi.framework.system.packages.extra
  4. 安装并启动所需的捆绑包
  5. 使用OSGI之外的服务
  6. 关闭容器
  7. 退出应用程序

在所有捆绑包启动后,可以放心地假设所需的服务可用。这也避免了将配置传递到OSGI中,而OSGI实际上只是服务调用的参数。

相关内容

  • 没有找到相关文章

最新更新