5

我目前正在接触 OSGI,并决定使用一个稍微不典型的 OSGI 用例。我想在命令行应用程序中使用它。我想要一种main(..)方法,它需要一些标志和参数,做一些事情并再次关闭。我不想要的是启动 Apache Karaf(或类似的)并在 OSGI 控制台中运行命令(虽然这可能成为一个可选功能)。

为什么首先将 OSGI 用于命令行应用程序?该应用程序应该使用同一库的不同版本(即elasticsearch)。仅仅因为它当然很糟糕。

我应该在捆绑包内还是在外部使用服务?如何做到这一点?可能会出现什么问题?

4

2 回答 2

7

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

诀窍是获取主线程(调用静态 main 的地方)。您唯一需要做的就是使用属性注册 Runnable 服务main.thread=true。然后,启动器将在该服务上调用 run() 并退出(您可以根据需要一直保持运行状态)。

要获取命令行参数,您可以使用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<Integer> 而不是 Runnable。然后返回值是进程的退出代码。但是,这可能还没有出现在 bndtools 中。

于 2013-07-19T12:42:34.090 回答
1

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

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

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

于 2013-07-19T09:44:12.880 回答