Apache Felix GoGo is a really cool
command line interface (
CLI, aka
shell aka
console)
framework that runs in an
OSGi runtime.
Karaf / Felix GoGo Features
A very nice feature of Apache Karaf is it has a
built-in SSH server, so you can literally and practically just ssh to the Karaf server :
ceefour@annafi:/opt/apache-karaf-2.2.0$ ssh -p 8102 karaf@localhost
karaf@localhost's password:
__ __ ____
/ //_/____ __________ _/ __/
/ ,< / __ `/ ___/ __ `/ /_
/ /| |/ /_/ / / / /_/ / __/
/_/ |_|\__,_/_/ \__,_/_/
Apache Karaf (2.2.0)
Hit '<tab>' for a list of available commands
and '[cmd] --help' for help on a specific command.
Hit '<ctrl-d>' or 'osgi:shutdown' to shutdown Karaf.
karaf@bipposhell> erp:hello
Hello Ibrahim!
Default credentials is user=karaf, password=karaf .
And even (this I just found out!) the amazing thing is you can run a command directly from ssh :
$ ssh -p 8102 karaf@localhost erp:hello
karaf@localhost's password:
Hello Ibrahim!
Isn't it amazing? What's more, the Karaf/Felix GoGo command line also supports POSIX/GNU-style option arguments, Tab completion, and UNIX-like pipes! (yes, pipes, where you can do 'grep' and stuff)
The other, and paramountly useful feature, is the ability to hot deploy exploded OSGi bundles! Now hot deploy in itself is really useful, the ability to deploy exploded bundles is even more fantastic. We'll see about that soon.
What About Virgo?
Some of you may (almost) cry that I didn't mention
Eclipse Virgo Kernel. Which is, of course, a direct competitor to Apache Karaf.
I haven't used Virgo yet (but I should try it one day), so because I have used Karaf in the past so for now I'm using Karaf, and I know it has a cool built-in CLI ;-)
I think the steps below can be adapted to Virgo with little (or not so little?) work. Let me know if you have tips, ideas, etc. :-) I will appreciate it a lot.
Developing CLI on Felix GoGo
For my next Bippo Shell project I plan to use Felix GoGo as the CLI framework. I'll share my first steps experience on developing CLI Commands with Karaf and Felix GoGo with you.
Felix GoGo looks for command services exposed by other OSGi bundles. To develop this OSGi bundle, my IDE of choice happens to be... (surprise!) Eclipse IDE. ;-)
Now there are several approaches to develop OSGi bundles in Eclipse IDE, but the path I want to take right now is using Eclipse PDE (Plug-in Development Environment). At least for developing the bundle (i.e. Eclipse plugin) itself, not for running/launching the runtime (yet...)
Creating the Target Platform
The first thing I need to do before developing anything (for you guys familiar with Eclipse RCP would already know this: any Eclipse-based project for that matter) is prepare the target platform.
The target platform contains all the OSGi bundles (Eclipse plugins) that are already in the target runtime environment. In this case: Felix Karaf.
So, copy these files from Apache Karaf distribution (hint: look for lib/ and system/ folders) to another folder. These little commands may help you:
mkdir -vp ~/felix-karaf-target-platform/
cp -v lib/karaf-jaas-boot.jar ~/felix-karaf-target-platform
find system -iname '*.jar' -exec cp -v '{}' ~/felix-karaf-target-platform \;
Then I created a target platform in Eclipse PDE, and add content based on the directory that contains the Karaf JARs, then activate the target platform.
Creating the Eclipse Plugin Project
Although Karaf only needs an OSGi bundle, I decided to create an Eclipse plugin project. Why not, since an Eclipse plugin is always an OSGi bundle anyway! And it might be useful if I want to use my plugin projects in an Eclipse RCP project, for example.
First I create an Eclipse plugin project, then set the Import-Package in META-INF/MANIFEST.MF to:
Import-Package: org.apache.felix.gogo.commands;version="0.6.1",
org.apache.karaf.shell.console;version="2.2.0",
org.osgi.framework;version="1.3.0"
This allows me to refer to the Felix GoGo API classes and interfaces.
Writing the Command Implementation
Thanks to annotations in similar spirit of JAX-RS, writing the CLI command implementation class is simple:
package id.co.bippo.shell;
import org.apache.felix.gogo.commands.Command;
import org.apache.karaf.shell.console.OsgiCommandSupport;
@Command(scope="erp", name="hello", description="Says hello")
public class ErpCommand extends OsgiCommandSupport {
/* (non-Javadoc)
* @see org.apache.karaf.shell.console.AbstractAction#doExecute()
*/
@Override
protected Object doExecute() throws Exception {
System.out.println("Hello Ibrahim!");
return null;
}
}
I think the annotations and what this class does is pretty much self-explanatory.
Registering the Command Service using OSGi Blueprint
To register the command service implementation,
OSGi Blueprint is used (although not mandatory, you can use manual OSGi wiring if you want, but why do it the hard way?)
Apache Karaf uses
Apache Aries Blueprint as the OSGi Blueprint implementation, but I believe it should work with Eclipse Gemini Blueprint as well.
Put this in OSGI-INF/blueprint/myshell.xml (actual filename doesn't matter):
<command name="erp/hello">
<action class="id.co.bippo.shell.ErpCommand"/>
</command>
</command-bundle>
</blueprint>
This registers the command that can be executed by typing: erp:hello
I wondered why the command name is repeated again here. It turns out that the Blueprint declaration actually registers the command under the specified name, and the class annotations are only used for usage help, i.e. when typing: erp:hello --help
Deploying the Command Bundle/Plugin
I'm not yet using fancy launcher PDE feature here, just old-school style:
- Export the plugin as a binary JAR bundle to a folder
- Copy the plugin JAR to Karaf's deploy/ folder
Karaf will detect it and register the command:
karaf@bipposhell> la
START LEVEL 100 , List Threshold: 0
ID State Blueprint Level Name
[ 0] [Active ] [ ] [ 0] System Bundle (3.0.8)
[ 1] [Active ] [ ] [ 5] OPS4J Pax Url - wrap: (1.2.5)
...
[ 40] [Active ] [Created ] [ 30] Apache Karaf :: Deployer :: Blueprint (2.2.0)
[ 41] [Active ] [Created ] [ 30] Apache Karaf :: Shell :: ConfigAdmin Commands (2.2.0)
[ 42] [Active ] [Created ] [ 60] Bippo Shell (1.0.0.qualifier)
karaf@bipposhell> erp:hello
Hello Ibrahim!
karaf@bipposhell> erp:hello --help
DESCRIPTION
erp:hello
Says hello
SYNTAX
erp:hello [options]
OPTIONS
--help
Display this help message
Hot Deploying Eclipse Plugins
Karaf has very useful ability to do hot deploy of OSGi bundles during development. (actually, being OSGi, it can perform hot deployment anytime, not just "during development")
osgi:install and dev:watch Karaf commands will help you on this.
But I prefer the low-tech solution:
ceefour@annafi:~/project/bipponext/workspace/id.co.bippo.shell$ ln -s $PWD/bin /opt/apache-karaf-2.2.0/instances/bipposhell/deploy/id.co.bippo.shell
This creates a symlink to the ${project_loc}/bin folder inside the Karaf's deploy/ folder.
You may want to also copy the META-INF/MANIFEST.MF file. If not, it will still work in most cases, because Karaf is very smart to wrap non-OSGi "bundles" to be OSGi-friendly.
This magic works because Karaf supports "exploded bundles", i.e. OSGi bundles not packaged in a JAR, but exploded as a directory structure.
karaf@bipposhell> erp:hello
Hello Ibrahim!
(......edit the source in Eclipse, then Save...and......)
karaf@bipposhell> erp:hello
Hello Yudha!
No need to restart, nothing! You don't even need to build/package the JAR!
Pretty nifty, eh? :-)
Karaf Tip: If something goes wrong, tail:log, log:set, and dev:show-tree Karaf commands are your friends. :-)
What's Next ?
As demonstrated, OSGi development can be easy and in some cases even easier than "plain" Java.