Apache
 6. Advanced uses 6.2. Building custom distributions

6.1. Extending the console

This chapter will guide you through the steps needed to extend the console and create a new shell. We will leverage Maven, Blueprint and OSGi, so you will need some knowledge of those products.

You may also find some information about the console at RFC 147 Overview.

Create the project using maven

We first need to create the project using maven. Let's leverage maven archetypes for that.

Command line

Using the command line, we can create our project:

mvn archetype:create \
  -DarchetypeArtifactId=maven-archetype-quickstart \
  -DgroupId=org.apache.felix.karaf.shell.samples \
  -DartifactId=shell-sample-commands \
  -Dversion=1.0-SNAPSHOT

This generate the main pom.xml and some additional packages.

Interactive shell

You can also use the interactive mode for creating the skeleton project:

mvn archetype:generate

Use the following values when prompted:

Choose a number:  (1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36) 15: : 15
Define value for groupId: : org.apache.felix.karaf.shell.samples
Define value for artifactId: : shell-sample-commands
Define value for version:  1.0-SNAPSHOT: : 
Define value for package: : org.apache.felix.karaf.shell.samples

Manual creation

Alternatively, you can simply create the directory shell-sample-commands and create the pom.xml file inside it:

pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.apache.felix.karaf.shell.samples</groupId>
  <artifactId>shell-sample-commands<artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>shell-sample-commmands</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Dependencies

We need to tell maven which libraries our project depends on. In the dependencies section of the pom, add the following one:

  <dependency>
    <groupId>org.apache.felix.karaf.shell</groupId>
    <artifactId>org.apache.felix.karaf.shell.console</artifactId>
    <version>1.0.0</version>
  </dependency>

This dependency is needed to have access to the base classes that are used to define commands.

Configuring for Java 5

We are using annotations to define commands, so we need to ensure maven will actually use JDK 1.5 to compile the jar.
Just add the following snippet after the dependencies section.

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
        <target>1.5</target>
        <source>1.5</source>
      </configuration>
    </plugin>
  </plugins>
</build>

Loading the project in your IDE

We can use maven to generate the needed files for your IDE:

Inside the project, run the following command

mvn eclipse:eclipse

or

mvn idea:idea

The project files for your IDE should now be created. Just open the IDE and load the project.

Creating a basic command class

We can now create the command class HelloShellCommand.java

HelloShellCommand.java
package org.apache.felix.karaf.shell.samples;

import org.apache.felix.gogo.commands.Command;
import org.apache.felix.gogo.commands.Option;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.karaf.shell.console.OsgiCommandSupport;

@Command(scope = "test", name = "hello", description="Says hello")
public class HelloShellCommand extends OsgiCommandSupport {

    @Override
    protected Object doExecute() throws Exception {
        System.out.println("Executing Hello command");
        return null;
    }
}

Creating the associated blueprint configuration files

The blueprint configuration file will be used to create the command and register it in the OSGi registry, which is the way to make the command available to Karaf console. This blueprint file must be located in the OSGI-INF/blueprint/ directory inside the bundle.

If you don't have the src/main/resources directory yet, create it.

mkdir src/main/resources

Then, re-generate the IDE project files and reload it so that this folder is now recognized as a source folder.

Inside this directory, create the OSGI-INF/blueprint/ directory and put the following file inside (the name of this file has no impact at all):

shell-config.xml
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

    <command-bundle xmlns="http://felix.apache.org/karaf/xmlns/shell/v1.0.0">
        <command name="test/hello">
            <action class="org.apache.felix.karaf.shell.samples.HelloShellCommand"/>
        </command>
    </command-bundle>

</blueprint>

Compiling the jar

Let's try to build the jar. Remove the test classes and sample classes if you used the artifact, then from the command line, run:

mvn install

The end of the maven output should look like:

[SMX4KNL:INFO] ------------------------------------------------------------------------
[SMX4KNL:INFO] BUILD SUCCESSFUL
[SMX4KNL:INFO] ------------------------------------------------------------------------

Turning the jar into an OSGi bundle

OSGi bundles are jars but they require some manifest headers to be correctly recognized. We will leverage Felix's manven plugin to easily generate those.

Lets turn it into a bundle: modify the line in the pom.xml to adjust the packaging:

  <packaging>bundle</packaging>

Add the following section at the bottom of the pom.xml, in the existing build/plugins section:

      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <version>2.0.1</version>
        <extensions>true</extensions>
        <configuration>
            <instructions>
                <Import-Package>org.osgi.service.command,*</Import-Package>
            </instructions>
        </configuration>
      </plugin>

The Import-Package is required to make sure our bundle will import the org.osgi.service.command package so that the service will be correctly seen in Felix.

Let's compiled it again using the mvn install command.

Test in Karaf

Launch a Karaf instance and run the following command to install the newly created bundle:

karaf@root> osgi:install -s mvn:org.apache.felix.karaf.shell.samples/shell-sample-commands/1.0-SNAPSHOT

Let's try running the command:

karaf@root> test:hello
Executing Hello command

and for the link:

Yeah

top

 6. Advanced uses 6.2. Building custom distributions