In this chapter, we will cover the following topics:
Configuring production-ready logging in Apache Karaf
Creating our own custom Karaf command using a Maven archetype
Branding the Apache Karaf console
Deploying applications as a feature
Using JMX to monitor and administer Apache Karaf
Reconfiguring SSH access to Apache Karaf
Installing Apache Karaf as a service
Setting up Apache Karaf for high availability
Experienced users of Apache Karaf will tell you that out of the box, Karaf provides you with the features and tools you'll need to deploy your application. However, to build a production-ready environment, you'll want to tweak things.
The recipes in this chapter are devoted to systems builders, the people who need to make their Apache Karaf instance production-ready and applications within it manageable.
Tip
New to Apache Karaf and OSGi?
Readers interested in obtaining a deeper understanding of Apache Karaf and its underlying technologies should consult Packt Publishing's Instant OSGi Starter, Jamie Goodyear and Johan Edstrom, and Learning Apache Karaf, Jamie Goodyear, Johan Edstrom, and Heath Kesler.
One of the first tasks administrators of Apache Karaf undertake is changing the default logging configuration to more production-ready settings.
To improve the default logging configuration, we'll perform the following tasks:
Update the logfile location to be outside the data folder. This helps administrators avoid accidentally wiping out logfiles when deleting runtime data.
Increase the logfile size. The default size of 1 MB is too small for most production deployments. Generally, we set this to 50 or 100 MB, depending on the available disk space.
Increase the number of logfiles we retain. There is no correct number of logfiles to retain. However, when disk space is cheap and available, keeping a large number of files is a preferred configuration.
Configuring Karaf's logging mechanism requires you to edit the etc/org.ops4j.pax.logging.cfg
file. Open the file with your preferred editor and alter the following highlighted code entries:
# Root logger log4j.rootLogger=INFO, out, osgi:* log4j.throwableRenderer=org.apache.log4j.OsgiThrowableRenderer # File appender log4j.appender.out=org.apache.log4j.RollingFileAppender log4j.appender.out.layout=org.apache.log4j.PatternLayout log4j.appender.out.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n log4j.appender.out.file=${karaf.base}/log/karaf.log log4j.appender.out.append=true log4j.appender.out.maxFileSize=10MB log4j.appender.out.maxBackupIndex=100
In the preceding configuration, we instruct Karaf to write logs to a log folder in the base installation directory, increase the logfile size to 10 MB, and increase the number of retained logfiles to 100.
When finished editing the file, save the changes. They will take effect shortly.
The logging system for Karaf is based on OPS4J Pax Logging with the log4j
library acting as its backend. The configuration file, etc/org.ops4j.pax.logging.cfg
, is used to define appenders, log levels, and so on. Let's take a look at the following default appender configuration and how we'll tweak it to become more production-ready:
# Root logger log4j.rootLogger=INFO, out, osgi:* log4j.throwableRenderer=org.apache.log4j.OsgiThrowableRenderer # File appender #log4j.appender.out=org.apache.log4j.RollingFileAppender #log4j.appender.out.layout=org.apache.log4j.PatternLayout #log4j.appender.out.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n #log4j.appender.out.file=${karaf.data}/log/karaf.log #log4j.appender.out.append=true #log4j.appender.out.maxFileSize=1MB #log4j.appender.out.maxBackupIndex=10
In the previous code, the File appender
configuration sets up the default Karaf logging behavior. The initial configuration sets RollingFileAppender
and constructs a log entry pattern. The remaining options dictate the location of the logfile, its size, and the number of logfiles to retain.
Karaf monitors the configuration file in the KARAF_HOME/etc
folder. When the updates to the configuration file are read, the logging service is updated with the new value(s). The mechanism that allows this behavior is provided by File Install (available at http://felix.apache.org/site/apache-felix-file-install.html) and the OSGi Configuration Admin service. Have a look at the following figure:

As illustrated in the preceding figure, when a file in the KARAF_HOME/etc
directory is created, deleted, or modified, the file scanner will pick up on the event. Given a configuration file change (a change in the file format of the Java properties file), a configuration processor will process the entries and update the OSGi Configuration Admin service.
Tip
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
To further improve logging, you can provide the log4j
library with an external logging location, separating the I/O requirements of logging from the base system at the expense of increased network traffic. This architecture is shown in the following figure:

To achieve this logging architecture, you'll need to mount the external volume on the server on which Karaf is running.
The Karaf console provides a multitude of useful commands to interact with the OSGi runtime and manage deployed applications. As a systems builder, you may want to develop custom commands that integrate directly into Karaf so that you can automate tasks or interact directly with your applications.
Custom Karaf commands will appear in your container as a fully integrated component of the console, as shown in the following screenshot:

The previous screenshot illustrates our sample cookbook command accepting an option flag and an argument. Let's dive into building your own command.
The ingredients of this recipe include the Apache Karaf distribution kit, access to JDK, Maven, and a source code editor. The sample code for this recipe is available at https://github.com/jgoodyear/ApacheKarafCookbook/tree/master/chapter1/chapter1-recipe2.
The first step is generating a template command project. To encourage building custom commands, the community has provided the following Maven archetype invocation to generate Karaf command projects:
mvn archetype:generate \ -DarchetypeGroupId=org.apache.karaf.archetypes \ -DarchetypeArtifactId=karaf-command-archetype \ -DarchetypeVersion=3.0.0 \ -DgroupId=com.packt.chapter1 \ -DartifactId=command \ -Dversion=1.0.0-SNAPSHOT \ -Dpackage=com.packt
In the preceding archetype invocation, we supply the Maven project group and artifact names. The process will request you to supply a command name. Maven then generates a project template for your command.
The next step is implementing your custom code. The custom command template project will supply you with a Maven POM file, Blueprint wiring (in the
src/main/resources/OSGI-INF/blueprint
directory), and custom command stub implementation (in thesrc/main/java/
directory). Edit these files as required to add your custom actions.The last step is building and deploying the custom command in Karaf. We build our command via the Maven invocation
mvn install
. Deploying it in Karaf only requires issuing a well-formed install command; to do this, invokeinstall –s mvn:groupId/artifactId
in the Karaf console. Consider the following invocation:karaf@root()> install –s mvn:com.packt.chapter1/command Bundle ID: 88 karaf@root()>
The preceding invocation has the
groupId
value ascom.packt.chapter1
and theartifactId
value ascommand
.
The Maven archetype generates the POM build file, Java code, and Blueprint file for your custom command. Let's take a look at these key components.
The generated POM file contains all of the essential dependencies a Karaf command requires and sets up a basic Maven Bundle Plugin configuration. Edit this file to bring in additional libraries your command requires. Make sure that you update your bundle's build parameters accordingly. When this project is built, a bundle will be produced that can be installed directly into Karaf.
Our custom command logic resides in the generated Java source file, which will be named after the command name you supplied. The generated command extends Karaf's OSGICommandSupport
class, which provides us with access to the underlying command session and OSGi environment. A Command
annotation adorns our code. This provides the runtime with the scope, name, and description. Karaf provides the Argument
and Option
annotations to simplify adding a command-line argument and option processing.
The Blueprint container wires together our command implementation to the commands available in Karaf's console.
Tip
For more information on extending Karaf's console, see http://karaf.apache.org/manual/latest/developers-guide/extending.html.
Thanks to Apache Karaf's SSHD service and remote client, your custom commands can be leveraged to provide external command and control of your applications. Just pass your command and its parameters to the remote client and monitor the returned results.
Apache Karaf is used as the runtime environment for production application platforms. In such deployments, it is common to have Karaf sporting a custom branding.
The Karaf community has made rebranding the runtime a simple task. Let's make our own for this book.
The ingredients of this recipe include the Apache Karaf distribution kit, access to JDK, Maven, and a source code editor. The sample code for this recipe is available at https://github.com/jgoodyear/ApacheKarafCookbook/tree/master/chapter1/chapter1-recipe3.
The first step is generating a Maven-based project structure. For this recipe, we need to only create the bare of Maven POM files, set its packaging to
bundle
, and include abuild
section.The next step is adding a resource directive to our POM file's build section. In our POM file, we add a resource directive to our build section, as shown in the following code:
<resource> <directory> ${project.basedir}/src/main/resources </directory> <filtering>true</filtering> <includes> <include>**/*</include> </includes> </resource>
We add a resource directive to our build section to instruct Maven to process the contents of our
resources
folder, filter any wildcards, and include the result in the generated bundle.Next, we configure the Maven Bundle Plugin as shown in the following code:
<configuration> <instructions> <Bundle-SymbolicName> ${project.artifactId} </Bundle-SymbolicName> <Import-Package>*</Import-Package> <Private-Package>!*</Private-Package> <Export-Package> org.apache.karaf.branding </Export-Package> <Spring-Context> *;publish-context:=false </Spring-Context> </instructions> </configuration>
We configured the Maven Bundle Plugin to export
Bundle-SymbolicName
as theartifactId
and set theExport-Package
option toorg.apache.karaf.branding
. The symbolic name as the project'sartifactId
variable is a common convention among Karaf bundle developers. We export the Karaf branding package so that the Karaf runtime will identify the bundle as containing the custom branding.The next step is creating our custom branding resource file. Returning to our project, we'll create a
branding.properties
file in thesrc/main/resource/org/apache/karaf/branding
directory. This.properties
file will contain ASCII and Jansi text characters, organized to produce your custom look. Using Maven resource filtering, you can use variable substitutions in the${variable}
format, as shown in the following code:## welcome = \ \u001B[33m\u001B[0m\n\ \u001B[33m _ ___ ____ ______ \u001B[0m\n\ \u001B[33m / \\ |_ ||_ _| .' ___ | \u001B[0m\n\ \u001B[33m / _ \\ | |_/ / / .' \\_| \u001B[0m\n\ \u001B[33m / ___ \\ | __'. | | \u001B[0m\n\ \u001B[33m _/ / \\ \\_ _| | \\ \\_ \\ '.___.'\\ \u001B[0m\n\ \u001B[33m|____| |____||____||____| '.____ .' \u001B[0m\n\ \u001B[33m \u001B[0m\n\ \u001B[33m Apache Karaf Cookbook \u001B[0m\n\ \u001B[33m Packt Publishing - http://www.packtpub.com\u001B[0m\n\ \u001B[33m (version ${project.version})\u001B[0m\n\ \u001B[33m\u001B[0m\n\ \u001B[33mHit '\u001B[1m<tab>\u001B[0m' for a list of available commands\u001B[0m\n\ \u001B[33mand '\u001B[1m[cmd] --help\u001B[0m' for help on a specific command.\u001B[0m\n\ \u001B[33mHit '\u001B[1m<ctrl-d>\u001B[0m' or '\u001B[1mosgi:shutdown\u001B[0m' to shutdown\u001B[0m\n\ \u001B[33m\u001B[0m\n\
In the preceding code, we use a combination of ASCII characters and Jansi text markup in the
branding.properties
file to produce simple text effects in Karaf, as shown in the following screenshot:The final step is building and deploying our custom branding. We build our branding via the Maven invocation
mvn install
. After we build our branding bundle, we place a copy inside Karaf'sKARAF_HOME/lib
folder and then start the container. Upon the first boot, you will see our custom branding displayed.
At the first boot, Apache Karaf will check for any bundle in its lib
folder and will export the org.apache.karaf.branding
package. Upon detection of this resource, it will access the branding.properties
file content and display it as part of the runtime startup routine.
The Apache Karaf community maintains a web console that may also be branded to reflect your organization's branding. See https://karaf.apache.org/index/subprojects/webconsole.html for more details.
Managing the assembly and deployment of repository locations, bundles, configuration, and other artifacts quickly becomes a major headache for system builders. To combat this, the Karaf community has developed the concept of features. The following figure describes the concept of features:

A feature descriptor is an XML-based file that describes a collection of artifacts to be installed together into the Karaf container. In this recipe, we'll learn how to make a feature, add it to Karaf, and then use it to install bundles.
The ingredients of this recipe include the Apache Karaf distribution kit, access to JDK, Maven, and a source code editor. The sample code for this recipe is available at https://github.com/jgoodyear/ApacheKarafCookbook/tree/master/chapter1/chapter1-recipe4.
The first step is generating a Maven-based project. For this recipe, we need to create a Maven POM file, set its packaging to
bundle
, and include abuild
section.The next step is editing the POM file's
build
directives. We add aresources
directive to our POM file'sbuild
section andmaven-resources-plugin
andbuild-helper-maven-plugin
to its plugin list. Consider the following code:<resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources>
In the preceding code, the
resources
directive indicates the location of the features file we'll create for processing. Now, consider the following code:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <executions> <execution> <id>filter</id> <phase>generate-resources</phase> <goals> <goal>resources</goal> </goals> </execution> </executions> </plugin>
In the preceding code,
maven-resources-plugin
is configured to process our resources. Now, consider the following code:<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <executions> <execution> <id>attach-artifacts</id> <phase>package</phase> <goals> <goal>attach-artifact</goal> </goals> <configuration> <artifacts> <artifact> <file>${project.build.directory}/classes/${features.file}</file> <type>xml</type> <classifier>features</classifier> </artifact> </artifacts> </configuration> </execution> </executions> </plugin>
Finally,
build-helper-maven-plugin
completes the build of ourfeatures.xml
file as described in the preceding code.The third step is creating a
features.xml
resource. In thesrc/main/resources
folder, add a file namedfeatures.xml
with the details of your bundles, as shown in the following code:<?xml version="1.0" encoding="UTF-8"?> <features> <feature name='moduleA' version='${project.version}'> <bundle> mvn:com.packt/moduleA/${project.version} </bundle> </feature> <feature name='moduleB' version='${project.version}'> <bundle> mvn:com.packt/moduleB/${project.version} </bundle> </feature> <feature name='recipe4-all-modules' version='${project.version}'> <feature version='${project.version}'>moduleA</feature> <feature version='${project.version}'>moduleB</feature> </feature> </features>
We provide each feature with a name that Karaf will use as a reference to install each element specified in the named feature's configuration. Features may reference other features, thus providing fine-grained control over installation. In the preceding features file, we can see three named features:
moduleA
,moduleB
, andrecipe4-all-modules
. Therecipe4-all-modules
feature includes the content of the other two features.Tip
If you need to include a JAR file that is not offered as a bundle, try using the
wrap
protocol to automatically provide the file with the OSGi manifest headers. For more information, see https://ops4j1.jira.com/wiki/display/paxurl/Wrap+Protocol.The final step is building and deploying our feature. Using our sample recipe project, we will build our feature by executing
mvn install
. This performs all of the feature file variable substitutions and installs a processed copy in your localm2
repository.To make our feature available to Karaf, we'll add the feature file's Maven coordinates as follows:
karaf@root()>feature:repo-add mvn:com.packt/features-file/1.0.0- SNAPSHOT/xml/features
Now, we can use Karaf's
feature
commands to installmoduleA
andmoduleB
, as shown in the following command-line snippet:karaf@root()>feature:install recipe4-all-modules Apache Karaf starting moduleA bundle Apache Karaf starting moduleB bundle karaf@root()>
Using
feature:install
in this fashion helps to promote repeatable deployments and avoid missing component installations that are not caught by the OSGi environment (if no bundle dependencies are missing, then as far as the container is concerned, all is well). We can verify whether our feature is installed by invoking the following command:karaf@root()>feature:list | grep –i "recipe"
We can then observe whether our feature is listed or not.
When Karaf processes a feature descriptor as a bundle, hot deployment, or via a system start-up property, the same processing and assembly functions occur, as shown in the following figure:

The feature descriptor invocation is transformed into a list of artifacts to be installed in the OSGi container. At the lowest level, individual elements in a feature have a handler to obtain the described artifact (such as a bundle, JAR file, or configuration file). Our sample feature uses Maven coordinates to obtain bundles, and the Maven handler will be called to process these resources. If an HTTP URL was specified, then the HTTP handler is called. Each artifact in the specified feature will be installed until the entire list is processed.
The How to do it… section of this recipe outlines a general methodology to produce a feature file for your projects and automate the filtering of resource versions. From Apache Karaf's point of view, it just processes a well-formatted features file so that you can handwrite the file and deploy it directly into Karaf.
Feature files have additional attributes that can be used to set bundle start levels, flag bundles as being dependencies, and set configuration properties. For more information, visit http://karaf.apache.org/manual/latest/users-guide/provisioning.html.
An advanced use case of Karaf feature files is to build a KAraf aRchive (KAR). A KAR file is the processed form of a feature file, collecting all the required artifacts into a single deployable form. This archive is ideal for deployment when your Karaf instance will not have access to remote repositories, as all required resources are packaged in the KAR file.
By default, Apache Karaf can be administered via Java Management Extensions (JMX). However, systems builders often need to tweak the default configurations to get their deployment integrated into their network. In this recipe, we'll show you how to make these changes.
The ingredients of this recipe include the Apache Karaf distribution kit, access to JDK, and a source code editor. The sample configuration for this recipe is available at https://github.com/jgoodyear/ApacheKarafCookbook/tree/master/chapter1/chapter1-recipe5.
The first step is editing the management configuration. Apache Karaf ships with a default management configuration. To make our modifications, we update the
etc/org.apache.karaf.management.cfg
file. Consider the following code:# # Port number for RMI registry connection # rmiRegistryPort = 11099 # # Port number for RMI server connection # rmiServerPort = 44445
The default ports, 1099 and 44444, are usually fine for general deployment. Change these ports only if you are experiencing port conflicts on your deployment. Now, consider the following snippet:
# # Role name used for JMX access authorization # If not set, this defaults to the ${karaf.admin.role} configured in etc/system.properties # jmxRole=admin
Towards the bottom of the configuration file, there will be a commented-out entry for
jmxRole
; enable this by removing the hash character.The next step is updating the user's file. We must now update the
etc/users.properties
file with the following code:karaf = karaf,_g_:admingroup _g_\:admingroup = group,admin,manager,viewer,jmxRole
The
users.properties
file is used to configure users, groups, and roles in Karaf. We appendjmxRole
to the admin group. The syntax for this file follows theUsername = password, groups
format.The last step is testing our configuration. After making the previous configuration changes, we'll need to restart our Karaf instance. Now, we can test our JMX setup. Have a look at the following screenshot:
After restarting Karaf, use a JMX-based admin tool of your choice (the previous screenshot shows JConsole) to connect to the container. Due to image size restrictions, the full URL couldn't be displayed. The full URL is
service:jmx:rmi://127.0.0.1:44445/jndi/rmi://127.0.0.1:11099/karaf-root
. The syntax of the URL isservice:jmx:rmi://host:${rmiServerPort}/jndi/rmi://host:${rmiRegistryPort}/${karaf-instance-name}
.
Using Apache Karaf via its local console provides the user with superb command and control capabilities over their OSGi container. Apache Karaf's remote console extends this experience to remote consoles, and as such, presents systems builders with an opportunity to further harden their systems. In this recipe, we'll change Karaf's default remote connection parameters.
The ingredients of this recipe include the Apache Karaf distribution kit, access to JDK, and a source code editor. The sample configuration for this recipe is available at https://github.com/jgoodyear/ApacheKarafCookbook/tree/master/chapter1/chapter1-recipe6.
The first step is editing the shell configuration. Apache Karaf ships with a default shell configuration file. It's a good practice to edit entries in the
etc/org.apache.karaf.shell.cfg
file to point to the non-default ports as a security precaution. Consider the following code:# # Via sshPort and sshHost you define the address you can login into Karaf. # sshPort = 8102 sshHost = 192.168.1.110
In the preceding sample configuration, we defined the port for SSH access to
8102
and setsshHost
to an IP address of the host machine (the default value, 0.0.0.0, means the SSHD service is bound to all network interfaces). Restricting access to particular network interfaces can help reduce unwanted access.The next step is restarting Karaf. After editing the configuration, we must restart Karaf. Once restarted, you'll be able to connect to Karaf using an SSH client command as follows:
ssh –p 8102 karaf@127.0.0.1
Upon connection, you'll be prompted for your password.
Changing the default remote access configuration is a good start. However, system builders should also consider changing the default karafuser/password
combination found in the users.properties
file.
You might also decide to generate a server SSH key file to simplify remote access. Information regarding this configuration can be found at http://karaf.apache.org/manual/latest/users-guide/remote.html.
When we install Apache Karaf, we'll want it to operate as a system service on our host platform (just like Windows or Linux). In this recipe, we'll set up Karaf to start when your system boots up.
The ingredients of this recipe include the Apache Karaf distribution kit, access to JDK, and a source code editor. The sample wrapper configuration for this recipe is available at https://github.com/jgoodyear/ApacheKarafCookbook/tree/master/chapter1/chapter1-recipe7.
The first step is installing the service wrapper feature. Apache Karaf utilizes a service wrapper feature to handle gathering and deploying of the required resources for your host operating environment. We begin its installation by invoking the following command:
karaf@root()>feature:install service-wrapper
The service wrapper feature URL is included in Karaf by default; so, no additional step is required to make it available.
The next step is installing the wrapper service. Now, we must instruct the wrapper to configure and install the appropriate service scripts and resources for us. Consider the following command:
karaf@root()>wrapper:install –s AUTO_START –n Karaf3 –D "Apache Karaf Cookbook"
The preceding
wrapper:install
command invocation includes three flags:-s
for the start type,-n
for the service name, and–D
for the service description. The start type can be one of two options:AUTO_START
, to automatically start the service on boot, andDEMAND_START
, to start only when manually invoked. The service name is used as an identifier in the host's service registry. The description provides system administrators with a brief description of your Karaf installation. After executing theinstall
command, the Karaf console will display the libraries, scripts, and configuration files that the wrapper generates. You'll now need to exit Karaf to continue the service installation.The final step is integrating it in to the host operating system. This step will require administrator level permissions to execute the generated Karaf service wrapper installation scripts.
The following command installs the service natively into Windows:
C:> C:\Path\To\apache-karaf-3.0.0\bin\Karaf3-service.bat install
The following
net
commands allow an administrator to start or stop the Karaf service:C:> net start "Karaf3" C:> net stop "Karaf3"
Linux integration will vary based on distribution. The following commands will work on Debian- or Ubuntu-based systems:
jgoodyear@ubuntu1204:~$ ln –s /Path/To/apache-karaf-3.0.0/bin/Karaf3-service /etc/init.d jgoodyear@ubuntu1204:~$ update-rc.d Karaf3-service defaults jgoodyear@ubuntu1204:~$ /etc/init.d/Karaf3-service start jgoodyear@ubuntu1204:~$ /etc/init.d/Karaf3-service stop
The first command creates a symbolic link from the service script in Karaf's
bin
folder to theinit.d
directory and then updates the startup scripts to include the Karaf service to automatically start during boot. The remaining two commands can be used to manually start or stop the Karaf service.
The wrapper service feature integrates Karaf into the host operating system's service mechanism. This means that on a Windows- or Linux-based system, Karaf will avail of the available fault, crash, processing freeze, out of memory, or similar event detections and automatically attempt to restart Karaf.
To help provide higher service availability, Karaf provides the option to set up a secondary instance of Apache Karaf to failover upon in case of an operating environment error. In this recipe, we'll configure a Master/Slave failover deployment and briefly discuss how you can expand the recipe to multiple hosts.
The ingredients of this recipe include the Apache Karaf distribution kit, access to JDK, and a source code editor. The sample configuration for this recipe is available at https://github.com/jgoodyear/ApacheKarafCookbook/tree/master/chapter1/chapter1-recipe8.
The first step is editing the system properties file. To enable a Master/Slave failover, we edit the
etc/system.properties
file of two or more Karaf instances to include the following Karaf locking configuration:## ## Sample lock configuration ## karaf.lock=true karaf.lock.class=org.apache.karaf.main.lock.SimpleFileLock # specify path to lock directory karaf.lock.dir=[PathToLockFileDirectory] karaf.lock.delay=10
The previous configuration sample contains the essential entries for a file-based locking mechanism, that is, two or more Karaf instances attempt to gain exclusive ownership of a file over a shared filesystem.
The next step is providing locking resources. If using a shared locking file approach is suitable to your deployment, then all you must do at this time is mount the filesystem on each machine that'll host Karaf instances in the Master/Slave deployment.
Tip
If you plan to use the shared file lock, consider using an NFSv4 filesystem, as it implements flock correctly.
Each Karaf instance will include the same lock directory location on a shared filesystem common to each Karaf installation. If a shared filesystem is not practical between systems, then a JDBC locking mechanism can be used. This is described in the following code:
karaf.lock=true karaf.lock.class=org.apache.karaf.main.DefaultJDBCLock karaf.lock.delay=10 karaf.lock.jdbc.url=jdbc:derby://dbserver:1527/sample karaf.lock.jdbc.driver=org.apache.derby.jdbc.ClientDriver karaf.lock.jdbc.user=user karaf.lock.jdbc.password=password karaf.lock.jdbc.table=KARAF_LOCK karaf.lock.jdbc.clustername=karaf karaf.lock.jdbc.timeout=30
The JDBC configuration is similar to the SimpleFileLock configuration. However, it is expanded to contain the JDBC
url
,driver
,timeout
,user
, andpassword
options. Two additional JDBC options are included to allow for multiple Master/Slave Karaf deployments to use a single database. These are the JDBCtable
andclustername
options. The JDBCtable
property sets the database table to use for the lock, and the JDBCclustername
property specifies which pairing group a Karaf instance belongs to (for example, hosts A and B belong to a cluster prod group, and hosts C and D belong to a cluster dev group).When using the JDBC locking mechanism, you'll have to provide the relevant JDBC driver JAR file to Karaf's
lib/ext
folder. For specific database configurations, consult Karaf's user manual (http://karaf.apache.org/manual/latest/index.html).The final step is verifying the lock behavior. Once you have configured each Karaf instance to be a participant of the Master/Slave deployment and ensured that any locking resources have been made available (mounted filesystems or database drivers/connectivity), you must now validate that it is all working as desired. The general test to perform is to start one instance of Karaf, allow it to gain the lock (you'll see this recorded in the logfile), and then start all additional instances. Only the first instance should be fully booted; the others should be trying to gain the lock. Stopping this first instance should result in another instance becoming the Master. This verification step is vital. Most Master/Slave deployment failures occur due to misconfigurations or shared resource permissions.
Each instance of Apache Karaf contains a copy of the locking configuration in its etc/system.properties
file. This is described in the following figure:

In the case of a SimpleFileLock configuration, Karaf attempts to utilize an exclusive lock upon a file to manage which Karaf instance will operate as a live (Master) container. The other instances in the set will try gaining lock file access for karaf.lock.delay
seconds each. This can be easily simulated on a single host machine with two Karaf installations both configured to use the same locking file. If the lock file is located on a shared NFSv4 filesystem, then multiple servers may be able to use this configuration. However, a JDBC-based lock is the most often used in multihost architectures.