我目前正在尝试使用OSGI并决定采用稍微不典型的OSGI用例。我想在命令行应用程序中使用它。我想要一个main(..)
方法,它接受一些标志和参数,做一些事情并再次关闭。我不想要的是启动Apache Karaf(或类似的)并在OSGI控制台中运行命令(这可能会成为一个可选功能)。
为什么OSGI首先应用于命令行应用程序?应用程序应该使用同一个库的不同版本(elasticsearch)。而且仅仅因为它当然是坏事。
我应该在捆绑服务中还是在服务范围内使用服务?如何做到这一点?可能会出现什么问题?
答案 0 :(得分:6)
使用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文件。
P.S。在最新的bnd中,您可以使用Callable&lt; Integer&gt;而不是Runnable。然后返回值是进程的退出代码。但是,这可能还没有出现在bndtools中。
答案 1 :(得分:1)
回答我自己的问题(Q&A style):我目前认为最好
org.osgi.framework.system.packages.extra
)在启动所有捆绑包之后,可以安全地假设所需的服务可用。这也避免了将配置传递到OSGI中,而OSGI实际上只是服务调用的参数。