在执行某些代码后关闭 OSGi 容器(以创建命令行工具)

Shutdown an OSGi container after some code has been executed (to create a command-line tool)

我想创建一个启动 OSGi 框架的命令行工具,以便重用依赖于 OSGi 的代码。

在答案 accessing command-line arguments from OSGi bundle 中,我了解了如何读取命令行参数:

@Component
public class Example {

    String[] args;

    @Activate
    void activate() {
        System.out.println("Hello World");
        System.out.println(args.length + " args:");
        for (String s : args) {
            System.out.println(" - " + s);
        }
    }

    @Reference(target = "(launcher.arguments=*)")
    void args(Object object, Map<String, Object> map) {
        if (map.containsKey("launcher.arguments")) {
            args = (String[]) map.get("launcher.arguments");
        } else {
            args = new String[] {};
        }
    }
}

但现在当我 运行 组装好的 jar (bnd-export-maven-plugin) 像这样时:

java -jar <path-to>/application.jar lorem ipsum

我得到了预期的输出,但应用程序没有终止。

看完4.2.6 Stopping a Framework后,我在想我需要在系统包上调用stop()。我试图将我的代码更改为:

@Activate
void activate(BundleContext bundleContext) {
    System.out.println("Hello World");
    System.out.println(args.length + " args:");
    for (String s : args) {
        System.out.println(" - " + s);
    }
    try {
        bundleContext.getBundle().stop();
    } catch (BundleException e) {
        e.printStackTrace();
    }
}

但是好像不是这样的

如果你想让系统包停止,你必须做(注意 0):

 bundleContext.getBundle(0).stop();

要正确执行此 hyper,您应该在另一个线程中执行此操作。

@Component
public class ServiceComponent {

    @Activate
    void activate(BundleContext c) {
        CompletableFuture.runAsync( ()-> {
            try {
                c.getBundle(0).stop();
            } catch (BundleException e) {
                e.printStackTrace();
            }
        } );        
    }
}

这当然是自杀成分...