Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何编写OSGI命令行应用程序_Java_Osgi_Embedded Osgi - Fatal编程技术网

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

Java 如何编写OSGI命令行应用程序,java,osgi,embedded-osgi,Java,Osgi,Embedded Osgi,我现在正在尝试OSGI,并决定使用一个稍微非典型的OSGI用例。我想在命令行应用程序中使用它。我想要一个main(…)方法,它接受一些标志和参数,执行一些操作并再次关闭。我不想启动ApacheKaraf(或类似的)并在OSGI控制台中运行命令(尽管这可能成为可选功能) 为什么OSGI首先用于命令行应用程序?应用程序应该使用同一库的不同版本(即)。当然,这只是因为它很糟糕 我应该在包内还是包外使用服务?你会怎么做?会出现什么问题?回答我自己的问题():我目前认为最好 启动(清洁) 启动容器 导出A

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

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

我应该在包内还是包外使用服务?你会怎么做?会出现什么问题?

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

  • 启动(清洁)
  • 启动容器
  • 导出API包(
    org.osgi.framework.system.packages.extra
  • 安装并启动所需的捆绑包
  • 关闭容器
  • 退出应用程序

  • 启动所有捆绑包后,可以安全地假设所需的服务可用。这也避免了将配置传递给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是完整的,它包含所有包、框架、启动器和运行它的属性。没有外部依赖关系

    诀窍是获取主线程(其中调用了static main)。您唯一需要做的就是使用属性
    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");
         }
     }
    
    @Component(immediate=true,property=“main.thread=true”)
    公共类主实现可运行{
    字符串[]args;
    公共无效运行(){…}
    @引用(target=“(launcher.arguments=*)”)
    void setArgs(对象服务、地图道具){
    this.args=(String[])props.get(“launcher.arguments”);
    }
    }
    
    最好的方法是使用bndtools,因为它可以轻松地测试/调试代码。那么您可能想要使用bndrun文件


    另外,在最新的bnd中,您可以使用Callable而不是Runnable。然后,返回值是进程的退出代码。但是,这可能还没有出现在bndtools中。

    谢谢您的回答。听起来确实很容易。您知道maven bundle plugin是否公开了
    package
    命令吗?您所说的
    Object.class
    是什么意思?应该简单地删除它,使其成为常规setter,对吗?我认为它应该是一个对象参数。不幸的是,您不能仅仅删除它,即使它只是您感兴趣的Map参数。包commnand仅在(bnd)工具中可用。这是一个有趣的问题,如果您想让包使用可发现的命令行选项(这是我们的用例),这就更难了。唉,我们的最终解决方案相当重,我还没有时间将其提炼成其他人可以使用的东西…