There is a very easy way to write command line apps when you use bnd. bnd has a function to create an executable jar with the package command:
$ 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
Note that this jar is complete, it contains ALL the bundles, the framework, the launcher, and the properties to run it. There are no external dependencies.
The trick is to get the main thread (where static main is called in). The only thing you have to do is register a Runnable service with a property main.thread=true
. The launcher will then call run() on this service and then exit (you can stay in the run as long as you want).
To get the command line arguments, you can get the Object service with the launcher.arguments
property. This property will have your command arguments. Or to do this with a DS component:
@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");
}
}
The best way to do this is with bndtools since it makes it easy to test/debug your code. You likely want to use bndrun files then.
P.S. In the latest bnd you can use a Callable<Integer> instead of a Runnable. The return value is then the exit code of the process. This might, however, not yet be present in bndtools.