从OSGi bundle访问命令行参数

7
我有一个作为OSGi捆绑包集合运行的应用程序。我使用嵌入Felix框架的非常小的包装器启动它。那个包装器的必要性让我有点恼火,因为它依赖于Felix(而应用程序本身可以在Equinox等环境下同样运行),所以我想摆脱它,使用默认的Felix启动器。
包装器真正做的唯一一件事情是将命令行参数传递到已启动的OSGi框架中,以便其中的捆绑包可以对其做出反应。请注意,它实际上不解析参数,只是将String[]推送到我的应用程序中。
有没有一种标准的方式(或至少是Felix标准的方式)从一个捆绑包中访问命令行参数,以便我可以摆脱自定义的启动器?

这个问题解决了吗?最终你选择了框架启动选项还是使用了 -D JVM 参数?如果是前者,能否分享一些关于你的解决方案的信息?谢谢。 - Chris
4个回答

9
如果您使用bnd(tools),您可以使用其启动器。它将命令行参数注册为服务属性“launcher.arguments”。
当您将其与bnd包命令结合使用时,它非常有效。此命令需要一个描述运行环境(捆绑包、属性、框架)的bnd项目或bndrun文件,并将其转换为独立的主jar。因此,您在bndtools中进行开发和调试,当您满意时将其转换为单个可执行的jar。例如:
@Component
public class MyApp {
   String[] args;

   @Activate
   void activate() { 
      System.out.println("Args: " + Arrays.toString(args));
   }

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

转换为可执行文件的方法:

bnd package myapp.bnd
java -jar myapp.jar -a somearg *.file

这个很好用,但我认为 map.get("launcher.arguments") 应该转换为 String[] - Jmini

2
晚了一些,但也许有人会觉得有用。我遇到了相似的问题。我的应用程序在OSGi中运行,但我需要遵守外部接口,这意味着需要读取命令行参数。
关键在于新的OSGi规范4.2中定义的东西,即框架启动。您可以在Life Cycle Layer部分的Draft spec(在www.osgi.org的Draft下找到)中阅读相关内容。
这是一种从独立的Java应用程序启动OSGi框架(任何支持OSGi 4.2的实现)的标准方法。好处在于,只要在CLASSPATH中找到它,您就不需要知道启动哪个实现(Felix、Equinox等)。
这样,您的启动器应用程序读取命令行参数,实例化并启动一个OSGi框架,并将参数传递给您的bundle(任何您想要的方式)。在启动器应用程序中,您得到的是一个上下文,可以与您的bundles通信。
截至Equinox 3.5M6(我想,至少是M6),已经支持了这一点。最新版本的Apache Felix也支持此功能。

3
我愿意支付一百万美元,以便在这个答案中添加一些链接。 - Andriy Drozdyuk
1
OSGI框架的启动已经被描述得非常好了,我同意这一点,但是“将参数传递给您的bundle”并没有那么清晰明了。 - Dan Gravell

1

可能不行。我认为标准的Felix启动器会进行一些命令行验证,并仅接受包缓存目录作为参数。若传递多个参数,启动器将退出。

您可以使用系统属性在命令行中传递信息,我认为不仅在Felix中,在其他OSGi容器中也可以使用,但这可能会使您的应用程序不太用户友好。


1

我知道你只搜索了Felix。那么,这个仅限于Equinox的解决方案可能不会有用。我还是把它留在这里,因为其他人可能会偶然遇到这个问题并且正在使用Equinox。

从任何bundle和任何framework中,这可能会很困难。如果您使用org.eclipse.core.runtime.applications扩展点,那么应该很容易。前提条件:您不要将-console作为参数传递。

public class Application implements IApplication {

    @Override
    public Object start(IApplicationContext context) throws Exception {
        String[] args = (String[])context.getArguments().get("application.args");
        // args.length == 0 if no arguments have been passed
    }
}

在plugin.xml中的参考

 <plugin>
    <extension
          id="myApp"
          point="org.eclipse.core.runtime.applications">
        <application>
          <run class="package.Application" />
        </application>  
    </extension>
 </plugin>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接