Red Hat Training

A Red Hat training course is available for Red Hat Fuse

Chapter 12. Deploying a FAB

Abstract

Apache Karaf provides two different approaches for deploying FABs: hot deployment and manual deployment.

12.1. The FAB Deployment Model

Overview

FABs have a fundamentally different deployment model from standard OSGi bundles. When a FAB is installed, the FAB runtime automatically figures out what dependencies are required, by scanning the Maven metadata, and these dependencies are then installed dynamically.

What is a FAB?

A Fuse Application Bundle (FAB) is any JAR created using Apache Maven, or similar build tools, so that inside the JAR there is a pom.xml file at the following location (where groupId and artifactId are the Maven coordinates of the JAR):
META-INF/maven/groupId/artifactId/pom.xml
Which contains the transitive dependency information for the JAR.
Important
A FAB is not an OSGi bundle. At installation time, however, a FAB results in the creation of one or more bundles, which are constructed dynamically.

Manifest.mf file

It is possible to add some additional (optional) configuration to a FAB by including FAB-specific headers in the JAR's Manifest.mf file. For example, the FAB-Provided-Dependency header can be used to specify whether some or all of the FAB's dependencies are to be shared.
For full details about FAB manifest headers, see Section 11.4, “Configuring a FAB”.

FAB deployment

Depending on how a FAB is configured, there are two basic alternatives for deploying a FAB:

Installing a FAB with private dependencies

Figure 12.1, “FAB Installed with Private Dependencies” shows how a FAB is installed when all of its dependencies are configured to be private.

Figure 12.1. FAB Installed with Private Dependencies

FAB Installed with Private Dependencies
The figure shows the installation of the FAB, Fab, and its private dependencies, which proceeds as follows:
  1. The user explicitly deploys the FAB, Fab, into the OSGi container (either by hot deploying or manually deploying).
  2. The FAB runtime scans the embedded pom.xml file and figures out all of the non-optional and non-test transitive dependencies. In this case, there are five private dependencies: DepA, DepA1, DepB, DepB1, and DepB2. The FAB runtime auto-installs these dependencies by fetching them from the Maven repository.
  3. The dependencies are added to the FAB's private class space and the whole collection is converted into a single OSGi bundle and installed in the OSGi container.
When a FAB is configured to have all of its dependencies private, as in this example, what you end up with is very similar to a WAR deployment (which also tends to keep its dependencies private, by default). An advantage that the FAB has over the WAR, however, is that the FAB does not need to be packaged together with its dependencies. Thus a FAB can be much smaller than a typical WAR package.

Installing a FAB with shared dependencies

At the other extreme, Figure 12.2, “FAB Installed with Shared Dependencies” shows how a FAB is installed when all of its dependencies are configured to be shared.

Figure 12.2. FAB Installed with Shared Dependencies

FAB Installed with Shared Dependencies
The figure shows the installation of the FAB, Fab, and its shared dependencies, which proceeds as follows:
  1. The user explicitly deploys the FAB, Fab, into the OSGi container (either by hot deploying or manually deploying).
  2. The FAB runtime scans the embedded pom.xml file and figures out all of the non-optional and non-test transitive dependencies. In this case, there are five shared dependencies: DepA, DepA1, DepB, DepB1, and DepB2. The FAB runtime then auto-installs these dependencies by fetching them from the Maven repository.
  3. The FAB, Fab, and its dependencies are separately converted into OSGi bundles and the requisite import and export bundle headers are automatically added. This collection of generated bundles is then installed in the OSGi container.
When a FAB is configured to share all of its dependencies, as in this example, what you end up with is very similar to the conventional approach using OSGi bundles and features. The advantage of the FAB approach, however, is that you do not need to write a custom features file to make sure that all of the dependencies are installed at the same time.

Optimising a FAB's shared dependencies

A FAB can have all private dependencies, some shared dependencies, or all shared dependencies. In other words, you can configure a FAB's dependencies anywhere on the spectrum from all-shared to all-private.
By default, a FAB keeps its dependencies private (except for the dependencies with Maven group ID org.apache.camel, org.apache.cxf, or org.apache.activemq). This deployment approach is relatively safe, because it minimizes the risk of version conflicts and so on. But it is also an expensive option, because it uses up a lot of system memory and resources. If you would like to experiment with sharing some of the FAB's dependencies, you can specify which artifacts to share using the FAB-Provided-Dependency: header in the FAB's manifest, Manifest.mf. For example:
FAB-Provided-Dependency: org.apache.camel:* org.apache.cxf:* org.apache.activemq:*
  org.springframework:*
In this way, you can easily optimize the performance of the FAB, while balancing the risk of version conflicts occurring.

Starting a FAB

Figure 12.3, “FAB Start” shows an outline of what happens when you start a FAB, in the case where the FAB shares its dependencies.

Figure 12.3. FAB Start

FAB Start
When you start a FAB using the fab:start console command, the FAB runtime iterates over the FAB's transitive dependencies and starts every single bundle in the tree of dependencies (starting with the leaves). This contrasts with the conventional osgi:start console command, which starts only the specified bundle.

Default install behavior of a FAB

The default install behavior of a FAB is actually more complex than suggested by the all-private dependencies model (as shown in Figure 12.1, “FAB Installed with Private Dependencies”). In reality, the FAB runtime distinguishes between the following types of dependency:
  • Plain FAB dependency (has pom.xml file, but no bundle headers)—by default, the plain FAB dependencies are added to the deployed FAB's private classpath and bundled together with the deployed FAB.
  • OSGi bundle dependency (has pom.xml file and bundle headers)—by default, the OSGi bundle dependencies are deployed as separate bundles (shared dependencies).
Figure 12.4, “Default FAB Install Behavior” shows how a FAB is installed, by default, when some its dependencies are plain FABs (DepA and DepA1) and some of its dependencies are OSGi bundles (Bnd1, Bnd2, and Bnd3):

Figure 12.4. Default FAB Install Behavior

Default FAB Install Behavior
The FAB runtime works on the assumption that whoever built an artifact as an OSGi bundle presumably intended for the artifact to be deployed as a bundle. Another good reason for deploying OSGi bundles separately is that this guarantees that the bundles will be properly activated when you invoke fab:start. If the dependent bundles (Bnd1, Bnd2, and Bnd3) were merely added to the private classpath of the Fab bundle, they would not be activated when fab:start is invoked (in other words, any Spring configuration files or blueprint configuration files would fail to be activated).