Chapter 8. Deploying Features
Abstract
Because applications and other tools typically consist of multiple OSGi bundles, it is often convenient to aggregate inter-dependent or related bundles into a larger unit of deployment. Red Hat JBoss Fuse therefore provides a scalable unit of deployment, the feature, which enables you to deploy multiple bundles (and, optionally, dependencies on other features) in a single step.
Alternatively, you could switch to using the FAB model of deployment, which automatically aggregates related bundles at deployment time, without requiring any additional configuration.
8.1. Creating a Feature
Overview
Essentially, a feature is created by adding a new
feature
element to a special kind of XML file, known as a feature repository. To create a feature, perform the following steps:
Create a custom feature repository
If you have not already defined a custom feature repository, you can create one as follows. Choose a convenient location for the feature repository on your file system—for example,
C:\Projects\features.xml
—and use your favorite text editor to add the following lines to it:
<?xml version="1.0" encoding="UTF-8"?> <features name="CustomRepository"> </features>
Where you must specify a name for the repository, CustomRepository, by setting the
name
attribute.
Note
In contrast to a Maven repository or an OBR, a feature repository does not provide a storage location for bundles. A feature repository merely stores an aggregate of references to bundles. The bundles themselves are stored elsewhere (for example, in the file system or in a Maven repository).
Add a feature to the custom feature repository
To add a feature to the custom feature repository, insert a new
feature
element as a child of the root features
element. You must give the feature a name and you can list any number of bundles belonging to the feature, by inserting bundle
child elements. For example, to add a feature named example-camel-bundle
containing the single bundle, C:\Projects\camel-bundle\target\camel-bundle-1.0-SNAPSHOT.jar
, add a feature
element as follows:
<?xml version="1.0" encoding="UTF-8"?>
<features name="MyFeaturesRepo">
<feature name="example-camel-bundle">
<bundle>file:C:/Projects/camel-bundle/target/camel-bundle-1.0-SNAPSHOT.jar</bundle>
</feature>
</features>
The contents of the
bundle
element can be any valid URL, giving the location of a bundle (see Appendix A, URL Handlers). You can optionally specify a version
attribute on the feature element, to assign a non-zero version to the feature (you can then specify the version as an optional argument to the features:install
command).
To check whether the features service successfully parses the new feature entry, enter the following pair of console commands:
JBossFuse:karaf@root> features:refreshUrl JBossFuse:karaf@root> features:list ... [uninstalled] [0.0.0 ] example-camel-bundle MyFeaturesRepo ...
The
features:list
command typically produces a rather long listing of features, but you should be able to find the entry for your new feature (in this case, example-camel-bundle
) by scrolling back through the listing. The features:refreshUrl
command forces the kernel to reread all the feature repositories: if you did not issue this command, the kernel would not be aware of any recent changes that you made to any of the repositories (in particular, the new feature would not appear in the listing).
To avoid scrolling through the long list of features, you can
grep
for the example-camel-bundle
feature as follows:
JBossFuse:karaf@root> features:list | grep example-camel-bundle [uninstalled] [0.0.0 ] example-camel-bundle MyFeaturesRepo
Where the
grep
command (a standard UNIX pattern matching utility) is built into the shell, so this command also works on Windows platforms.
Add the local repository URL to the features service
In order to make the new feature repository available to Apache Karaf, you must add the feature repository using the
features:addUrl
console command. For example, to make the contents of the repository, C:\Projects\features.xml
, available to the kernel, you would enter the following console command:
features:addUrl file:C:/Projects/features.xml
Where the argument to
features:addUrl
can be specified using any of the supported URL formats (see Appendix A, URL Handlers).
You can check that the repository's URL is registered correctly by entering the
features:listUrl
console command, to get a complete listing of all registered feature repository URLs, as follows:
JBossFuse:karaf@root> features:listUrl mvn:org.apache.servicemix.nmr/apache-servicemix-nmr/1.1.0-fuse-01-00/xml/features mvn:org.apache.servicemix.camel/features/6.1.0.redhat-379/xml/features file:C:/Projects/features.xml mvn:org.apache.ode/ode-jbi-karaf/1.3.3-fuse-01-00/xml/features mvn:org.apache.felix.karaf/apache-felix-karaf/1.2.0-fuse-01-00/xml/features mvn:org.apache.servicemix/apache-servicemix/6.1.0.redhat-379/xml/features
Add dependent features to the feature
If your feature depends on other features, you can specify these dependencies by adding
feature
elements as children of the original feature
element. Each child feature
element contains the name of a feature on which the current feature depends. When you deploy a feature with dependent features, the dependency mechanism checks whether or not the dependent features are installed in the container. If not, the dependency mechanism automatically installs the missing dependencies (and any recursive dependencies).
For example, for the custom Apache Camel feature,
example-camel-bundle
, you can specify explicitly which standard Apache Camel features it depends on. This has the advantage that the application could now be successfully deployed and run, even if the OSGi container does not have the required features pre-deployed. For example, you can define the example-camel-bundle
feature with Apache Camel dependencies as follows:
<?xml version="1.0" encoding="UTF-8"?>
<features name="MyFeaturesRepo">
<feature name="example-camel-bundle">
<bundle>file:C:/Projects/camel-bundle/target/camel-bundle-1.0-SNAPSHOT.jar</bundle>
<feature version="6.1.0.redhat-379">camel-core</feature>
<feature version="6.1.0.redhat-379">camel-spring-osgi</feature>
<feature version="6.1.0.redhat-379">servicemix-camel</feature>
</feature>
</features>
Specifying the
version
attribute is optional. When present, it enables you to select the specified version of the feature.
Add OSGi configurations to the feature
If your application uses the OSGi Configuration Admin service, you can specify configuration settings for this service using the
config
child element of your feature definition. For example, to specify that the prefix
property has the value, MyTransform
, add the following config
child element to your feature's configuration:
<?xml version="1.0" encoding="UTF-8"?>
<features name="MyFeaturesRepo">
<feature name="example-camel-bundle">
<config name="org.fusesource.fuseesb.example">
prefix=MyTransform
</config>
</feature>
</features>
Where the
name
attribute of the config
element specifies the persistent ID of the property settings (where the persistent ID acts effectively as a name scope for the property names). The content of the config
element is parsed in the same way as a Java properties file.
The settings in the
config
element can optionally be overriden by the settings in the Java properties file located in the InstallDir/etc
directory, which is named after the persistent ID, as follows:
InstallDir/etc/org.fusesource.fuseesb.example.cfg
As an example of how the preceding configuration properties can be used in practice, consider the following Blueprint XML file that accesses the OSGi configuration properties:
<?xml version="1.0" encoding="UTF-8"?> <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"> <!-- osgi blueprint property placeholder --> <cm:property-placeholder id="placeholder" persistent-id="org.fusesource.fuseesb.example"> <cm:default-properties> <cm:property name="prefix" value="DefaultValue"/> </cm:default-properties> </cm:property-placeholder> <bean id="myTransform" class="org.fusesource.fuseesb.example.MyTransform"> <property name="prefix" value="${prefix}"/> </bean> </blueprint>
When this Blueprint XML file is deployed in the
example-camel-bundle
bundle, the property reference, ${prefix}
, is replaced by the value, MyTransform
, which is specified by the config
element in the feature repository.
Automatically deploy an OSGi configuration
By adding a
configfile
element to a feature, you can ensure that an OSGi configuration file gets added to the InstallDir/etc
directory at the same time that the feature is installed. This means that you can conveniently install a feature and its associated configuration at the same time.
For example, given that the
org.fusesource.fuseesb.example.cfg
configuration file is archived in a Maven repository at mvn:org.fusesource.fuseesb.example/configadmin/1.0/cfg
, you could deploy the configuration file by adding the following element to the feature:
<configfile finalname="etc/org.fusesource.fuseesb.example.cfg"> mvn:org.fusesource.fuseesb.example/configadmin/1.0/cfg </configfile>