Logo Computer scientist,
engineer, and educator
• Articles • Articles about computing • Articles about software development • Apache integration software

Using the fabric8 Maven plugin to deploy a Camel route to a fabric

In the article Implementing an Apache Camel route in an OSGi Java bundle using Maven from the ground up I described how to use Maven to build and package a simple Camel route as an OSGi bundle, ready to be deployed on Apache Karaf. This article goes a step further, and explains how to use Maven to deploy the same simple Camel route to one or more containers hosted by Apache fabric8 (or RedHat Fuse 6.1). These containers may be on distributed hosts, so this process gives a starting point for the development of a failure-tolerant application. fabric8 provides a Maven plugin (available from the public repository) that largely automates the deployment process.

This article assumes that you know in outline how fabric8 works, and that you understand the principles of containers and profiles. If that isn't the case, you might like to read the article Deploying an OSGi application on Apache Fabric8, from the ground up first.

If you are unfamiliar with Camel, then it might help to read Creating an Apache Camel route in Java from the ground up. The basics of the OSGi model are dealt with in Creating OSGI bundles and services from the ground up using Apache Karaf; however, if you use the Maven plugin, and define your Camel route in XML, you don't need to know much about OSGi to follow this example (although fabric8, like Karaf, is primarily an OSGi container.)

Because fabric8 is supplied with Camel support and Camel OSGi integration built in, you won't need to install any additional software into the fabric8 container. However, there are subtleties about ensuring that the necessary Camel bits get propagated if you're using distributed containers, which I'll discuss in more detail below.

Setting up fabric8

To recap, the unit of deployment in a fabric8 installation is the profile. A profile defines a set of OSGi bundles, which may be grouped into features, and links to repositories from which the bundles can be obtained. Deployment amounts to associating the profile with one or more containers.

To run this example, you'll need to start fabric8, and ensure that there is at least one container running, ideally with no other code. As in the previous article on fabric8, I'm going to assume that the container has the unimaginative name 'test1.'

Creating and deploying the application

We will use the same "Hello World" application as in the previous article >Implementing an Apache Camel route in an OSGi Java bundle using Maven from the ground up. The application is generated automatically when a project is created using the camel-archetype-blueprint. The only change necessary to use the fabric8 plugin is a few lines added to pom.xml. To avoid this article mixed up with the previous one, I'm working on a new copy of the test appliation, generated as follows:
$ mvn archetype:generate \
  -DarchetypeGroupId=org.apache.camel.archetypes \
  -DarchetypeArtifactId=camel-archetype-blueprint \
  -DarchetypeVersion=2.8.0 \
  -DgroupId=net.kevinboone.apacheintegration \
  -DartifactId=camefabrictest -Dversion=0.0.0.1
The name camelfabrictest will not only be the name of the directory created by Maven, and the OSGi bundle created by the build process, it will become part of the name of the fabric8 profile that gets deployed. The rest of the name will come from the groupId: net.kevinboone.apacheintegration. These two eleemnts are combined to form the profile name net.kevinboone.apacheintegration-camelfabrictest. This, at least, is the default; you can change the profile name in the pom.xml file if necessary.

The section that must be added to pom.xml is:

    <plugins>
      <plugin>
        <groupId>io.fabric8</groupId>
        <artifactId>fabric8-maven-plugin</artifactId>
      </plugin>
    ...
    <plugins>
Easy, no? As a reminder, this simple Camel application connects a timer to a log message; the only way to know it is running is to look in the log of the container to which it is assigned.

To build the application, make it available in the fabric8 Maven repository, and assign its code to a profile, all we need do is:

$ mvn fabric8:deploy
The first time you do this, Maven will download a huge pile of software, and you'll be prompted for the fabric8 repository password (default is 'admin'.)

Provisioning the application to a fabric8 container

Assuming that the application built successfully, you should see a new profile in the fabric8 console:
Fabric8:karaf@root> profile-list |grep kevin
net.kevinboone.apacheintegration-camelfabrictest 2 karaf
karaf is the name of the profile that is the parent of ours; remember than all profiles must carry enough code to allow for proper synchronization between containers. karaf is a sub-profile of default that has certain extra software repositories enabled; default would have been sufficient in this case.

Take a look at the profile contents:

Fabric8:karaf@root> profile-display net.kevinboone.apacheintegration-camelfabrictest

...
Container settings
----------------------------
Bundles : 
	mvn:net.kevinboone.apacheintegration/camelfabrictest/0.0.0.1
...
This profile has no repositories defined, as it inherits the internal Maven repository from its parent profiles. It defines one bundle, which is in the Maven repository with a certain URI.

To deploy the application, we assign its profile to a container. However, if that's all we do, we'll see the following spiteful error message in the karaf.log file of the container (not the console):

65 - io.fabric8.fabric-agent - 1.1.0.Beta4 | Unable to update agent
org.osgi.service.resolver.ResolutionException: 
Unable to resolve dummy/0.0.0: missing requirement 
  [dummy/0.0.0] osgi.identity; osgi.identity=camelfabrictest; 
    type=osgi.bundle; version="[0.0.0.1,0.0.0.1]" 
    [caused by: Unable to resolve camelfabrictest/0.0.0.1: 
      missing requirement [camelfabrictest/0.0.0.1] osgi.wiring.package; 
      filter:="(osgi.wiring.package=org.apache.camel.osgi)"]
The problem here is that, although the necessary Camel support is in the fabric's Maven server, it is not installed in the container hosting our application. When deploying an application in the form of OSGi bundles, there is no run-time resolution of missing dependencies of this sort. We can get around the problem by adding to the container the profile feature-camel; there may be other alternatives. There really seems to be no automated way to resolve dependency problems like this, other than intution, experience, and trial-and-error. Anyway, to assign the profiles to the container 'test1', do this:
Fabric8:karaf@root> container-change-profile test1 net.kevinboone.apacheintegration-camelfabrictest feature-camel
The change takes effect immediately and, if you look in the log for the test1 container, you should see the messages produced by our application.

Summary

We've seen how easy it is to use the Maven fabric8 plugin to deploy an Camel route to a container hosted by fabric8. Because the application code is held in a Maven repository, the route could also be deployed on multiple containers on different hosts. Of course, Maven obscures a lot of the technical detail, some of which needs to be understood for troubleshooting purposes. However, the benefit of using a Maven repository to host the application code does make Maven a natural choose for building it.
Copyright © 1994-2013 Kevin Boone. Updated May 03 2014