Develop OSGi applications using karaf

Apache Karaf is a good platform for deploying OSGi based applications. Karaf is also a good platform for testing and debugging these applications. This article describes how to test and debug OSGi bundles and OSGi applications with karaf and eclipse.

The basic flow of development, is:

  1. Build the application with maven
  2. Start karaf as your own user in a way that makes it listen for remote debug connections
  3. Install the application from the karaf console
  4. Connect eclipse to karaf for a remote debug session
  5. Make karaf listen to updates to bundles with SNAPSHOT versions, and automatically load the updated bundles
  6. Make a change in eclipse
  7. Run a maven build of the project
  8. Observe that the change appears in karaf or in the debugger

For more detail, read on.

Preparations

Do the following:

  1. Install eclipse
    1. Open a web browser on https://www.eclipse.org/downloads/ and download the installer for your system
    2. Run the installer to the end, using defaults for everything
  2. Install apache maven
    1. On debian GNU/linux, just do
      apt-get install maven
  3. Download and unpack the binary karaf distribution. In bash on GNU/linux (or in git bash on Windows), do:
    mkdir -p ~/karaf
    cd ~/karaf/
    wget http://apache.uib.no/karaf/4.1.4/apache-karaf-4.1.4.tar.gz
    tar --strip-components=1 -xf apache-karaf-4.1.4.tar.gz

Clone and build the sample application

  1. Clone and build the sample application
    mkdir -p ~/workspaces/ws01
    cd ~/workspaces/ws01/
    git clone https://github.com/steinarb/hello-karaf-demo.git
    cd ~/workspaces/ws01/hello-karaf-demo/
    mvn clean install
  2. Import the sample application into eclipse:
    1. Start eclipse
    2. Open the workspace at ~/workspaces/ws01
    3. Import the existing maven project hello-karaf-demo into the workspace (File->Import… then select Maven->Existing Maven Projects and click the wizard through to the end)

Install the application into karaf

  1. Open a command line window and start karaf with an argument that makes karaf listen for remote debug connections
    cd ~/karaf/
    bin/karaf debug
  2. From the karaf console prompt:
    1. Install the run-time requirements for the test application
      feature:repo-add mvn:no.priv.bang.osgi.service.adapters/service-adapters-karaf/1.0.0/xml/features
      feature:install adapter-for-osgi-logservice
      feature:install pax-http-whiteboard
    2. Install the sample application with the following commands
      bundle:install mvn:no.priv.bang.demos/hello-karaf-demo/1.0.0-SNAPSHOT
      bundle:start mvn:no.priv.bang.demos/hello-karaf-demo/1.0.0-SNAPSHOT
  3. Open a web browser on the following URL http://localhost:8181/hello

Debug into the application running in karaf

  1. Set up a remote debug connection in karaf
    1. Open the menu Run->Debug Configurations…
    2. In the debug configurations dialog:
      1. Select “Remote Java Application”
      2. Click the “New launch configuration”
      3. In the Name field, write
        Remote karaf debug
      4. In the Port field, write
        5005
      5. Select the “Source” tab
      6. Click the button “Add…”
      7. In the “Add Source” dialog:
        1. Select “Java Project”
        2. Click the button “OK”
        3. In the “Project Selection” dialog
          1. Click the checkbox of “hello-karaf-demo”
          2. Click the button “OK”
      8. Click the button “Debug”
  2. Set a breakpoint in the code
    1. Open the HelloServlet.java file (press Ctrl-Shift-t to open the “Open Type” dialog, type HelloServlet and select the HelloServlet class)
    2. Go to line 60 (press Ctrl-l, then type 60, and press Enter), i.e. this line
                  response.setStatus(200);
    3. Press Ctrl-Shift-b to set a breakpoint on line 61
  3. Reload the web page in the web browser
  4. Observe that the debugger stops at the breakpoint
  5. Press F8 to make the code continue to run

Make a modification in the code, picked up by karaf

    1. In the karaf console, give the following command to make karaf listen in the local repository for new versions of bundles with SNAPSHOT version
      bundle:watch *
    2. Modify the code in eclipse
      1. In the HelloServlet.java file, change
            private static final String TITLE = "Hello world!";
            private static final String PARAGRAPH = "This is sent via PAX Web Whiteboard Extender.";
        

        to

            private static final String TITLE = "Hello karaf world!";
            private static final String PARAGRAPH = "Powered by Apache Karaf.";
        
      2. Save the HelloServlet.java file
    3. Build the project with maven
      1. In eclipse, select the menu Run->Run Configurations…
      2. In the dialog Run Configurations:
        1. Select “Maven Build” in the list on the left
        2. Click the “New launch configuration” icon (top left in the dialog)
        3. In the “Name:” field, type:
          mvn install hello-karaf-demo
        4. In the “Base directory” field, type:
          ${project_loc:hello-karaf-demo}
        5. In the “Goals” field, type:
          install
        6. Click the button “Run”
    4. Reload the web page in the web browser and observe that the change now is present

Installing with a karaf feature

In the installation example earlier in this article the runtime requirements of the sample application were first installed into karaf (pax-http-whiteboard and adapter-for-osgi-logservice).

It is possible to install this example application in a way that also pulls in the dependencies:

  1. The first thing to do, is to remove the existing installation in karaf:
    1. Stop karaf
      logout
    2. Remove the “data” subdirectory
      rm -rf data
    3. Start karaf
      bin/karaf debug
  2. Removing the data directory removes all state in karaf, and karaf is back to a fresh installation, this can be verfied by:
    1. listing the bundles in the karaf console
      bundle:list
    2. Verifying that http://localhost:8181/hello results in a 404 Not Found
  3. The first thing to do, is to add the feature repository for the hello world application. The feature repository is an XML file containing one or more “karaf features”. A karaf feature can be a list of bundles to load, and it can also contain references to other features.  The feature file for the hello world application is attached to the maven bundle artifact and can be installed with the following command:
    feature:repo-add mvn:no.priv.bang.demos/hello-karaf-demo/1.0.0-SNAPSHOT/xml/features

    Note: This is the same karaf commando as the first command of the dependencies install. The pax-http-whiteboard feature is built-in to karaf and doesn’t require a feature repository install

  4. Now the feature for the hello world application can be installed
    feature:install hello-karaf
  5. Verify that the feature install has pulled in dependencies
    bundle:list
  6. Verify that the application is running on http://localhost:8181/hello

Some things to try on your own:

  1. Remove the data directory again and try installing the bundle without the dependencies and see what happens
  2. Start karaf watching for bundle modifications in the local maven repository
  3. List bundles on different levels with the bundle:list command with the threshold argument (hint: all karaf commands take the “–help” argument)
  4. Try launching the “mvn install” for the bundle using eclipse hotkeys after modifying the java file and observe that karaf loads the rebuilt module

4 thoughts on “Develop OSGi applications using karaf”

  1. Using above example, I tried start camel context using init method of servlet but it is gibving below error:-
    org.apache.camel.RuntimeCamelException: java.lang.ClassNotFoundException: org.apache.camel.converter.stream.StreamCacheConverterLoader
    at org.apache.camel.RuntimeCamelException.wrapRuntimeException(RuntimeCamelException.java:68)
    at org.apache.camel.support.service.ServiceSupport.start(ServiceSupport.java:112)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:71)
    at org.apache.camel.impl.engine.AbstractCamelContext.internalAddService(AbstractCamelContext.java:1407)
    at org.apache.camel.impl.engine.AbstractCamelContext.doAddService(AbstractCamelContext.java:1357)
    at org.apache.camel.impl.engine.AbstractCamelContext.doAddService(AbstractCamelContext.java:1352)
    at org.apache.camel.impl.engine.AbstractCamelContext.doAddService(AbstractCamelContext.java:1348)
    at org.apache.camel.impl.engine.AbstractCamelContext.setTypeConverter(AbstractCamelContext.java:1699)
    at org.apache.camel.impl.engine.AbstractCamelContext.getTypeConverter(AbstractCamelContext.java:1691)
    at org.apache.camel.impl.engine.AbstractCamelContext.doStartStandardServices(AbstractCamelContext.java:3306)
    at org.apache.camel.impl.AbstractModelCamelContext.doStartStandardServices(AbstractModelCamelContext.java:283)
    at org.apache.camel.impl.engine.AbstractCamelContext.forceLazyInitialization(AbstractCamelContext.java:3296)
    at org.apache.camel.impl.engine.AbstractCamelContext.doStartCamel(AbstractCamelContext.java:2550)
    at org.apache.camel.impl.engine.AbstractCamelContext.lambda$doStart$2(AbstractCamelContext.java:2439)
    at org.apache.camel.impl.engine.AbstractCamelContext.doWithDefinedClassLoader(AbstractCamelContext.java:2456)
    at org.apache.camel.impl.engine.AbstractCamelContext.doStart(AbstractCamelContext.java:2437)
    at org.apache.camel.support.service.ServiceSupport.start(ServiceSupport.java:99)
    at org.apache.camel.impl.engine.AbstractCamelContext.start(AbstractCamelContext.java:2346)
    at co.hotwax.initializers.CamelService.init(CamelService.java:56)
    at javax.servlet.GenericServlet.init(GenericServlet.java:244)

  2. Hi, there isn’t anything in the https://github.com/steinarb/hello-karaf-demo that pulls in stuff from camel so that’s not surprising. 🙂

    Here’s a karaf exampe that uses camel with OSGi blueprint (which is a different dependency injection method to SCR aka. DS (“Declarative Services”) that the hello-karaf example uses): https://github.com/apache/karaf/tree/master/examples/karaf-camel-example

    Here’s some dated (4 year old) documentation that describes how to use camel with SCR/DS: https://cwiki.apache.org/confluence/display/CAMEL/Camel+and+SCR

    (all maven references are probably dated, but the SCR annotations like e.g. @Component looks current)

    Unfortunately I don’t use camel myself so that’s the best I can do. But it might be an idea to as the karaf-users list for tips: https://cwiki.apache.org/confluence/display/KARAF/Mailing+Lists

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.