DUE TO SPAM, SIGN-UP IS DISABLED. Goto Selfserve wiki signup and request an account.
...
| Wiki Markup |
|---|
_\[This document describes framework launching introduced in Felix Framework 2.0.0 and continuing with the latest releases; it is incompatible with older versions of the Felix framework.\]_ |
- Introduction
- OSGi Launching and Embedding API Overview
- Launching Felix
- Embedding Felix
- Caveat
- Feedback
...
Introduction
The Apache Felix framework Framework is intended to be easily launchable and embeddable. For example, the Felix framework implementation avoids the use of system properties for configuration, since these are globals and can cause interference if multiple framework instances are created in the same VM. Felix The framework also tries to multiplex singleton facilities, like the URL stream handler factory. The goal is to make it possible to use Felix the framework in a variety of scenarios; however, this is still just a goal. In other words, this is a work in progress and if any issues arise, it would be greatly appreciated if they are brought to the attention of the Felix community. The next section provides a Felix API overviewan overview of the standard OSGi launching and embedding API for frameworks, while the remainder of the document is divided into two sections, one focusing on how to launch Felix and one focusing on how to embed Felix into a host application.
| Anchor | ||||
|---|---|---|---|---|
|
OSGi Launching and Embedding API Overview
The Felix framework is implemented by the org.apache.felix.framework.Felix class or just Felix for short. As part of the R4.2 OSGi specification, the launching and embedding API of the OSGi framework has been standardized. The approach is to have the framework implement the org.osgi.framework.launch.Framework interface, which extends the org.osgi.framework.Bundle interface. These interfaces provide the necessary means to launch and manage framework instances. The Bundle interface is defined as:
...
| Code Block |
|---|
public interface Framework extends Bundle
{
void init();
FrameworkEvent waitForStop(long timeout);
}
|
To actually construct a framework instance, the R4.2 specification defines the FrameworkFactory interface:
| Code Block |
|---|
public interface FrameworkFactory
{
Framework newFramework(Map configMapconfig);
}
|
The framework factory can be used to create configured framework instances. It is obtained following the standard META-INF/services approach.
...
org.osgi.framework.system.packages- specifies a list of packages the system bundle should export from the environment; if this is not set, then the framework uses a reasonable default fault.org.osgi.framework.system.packages.extra- specifies a list of additional packages the system bundle should export from the environment that are appended to the packages specified inorg.osgi.framework.system.packages; there is no default value for this property.org.osgi.framework.bootdelegation- specifies a list of packages that should be made implicitly available to all bundles from the environment (i.e., no need to import them); there is no default value for this property and its use should be avoided.org.osgi.framework.bundle.parent- Specifies which class loader is used for boot delegation. Possible values are:bootfor the boot class loader,appfor the application class loader,extfor the extension class loader, andframeworkfor the framework's class loader. The default isboot.org.osgi.framework.storage- specifies the path to a directory, which will be created if it does not exist, to use for bundle cache storage; the default value for this property is "felix-cache" in the current working directory.org.osgi.framework.storage.clean- specifies whether the bundle cache should be flushed; the default value for this property is "none", but it can be changed to "onFirstInit" to flush the bundle cache when the framework is initialized.org.osgi.framework.startlevel.beginning- specifies the start level the framework enters upon startup; the default value for this property is 1.
...
The init() method is necessary since the framework does not have a BundleContext when it is first created, so a transition to the Bundle.STARTING state is required to acquire its context (via Bundle.getBundleContext()) for performing various tasks, such as installing bundles. Note that the Felix framework also provides the felix.systembundle.activators property that serves a similar purpose, but is not standard. After the init() method completes, the follow actions have been performed:
...
In reality, the first step is optional, since all properties will have reasonable defaults, but if you are creating a launcher you will generally want to more than that, such as automatically installing and starting bundles when you start the framework instance. The default Felix launcher defines reusable functionality to automatically install and/or start bundles upon framework startup; see the usage document for more information on configuring the Felix framework and on the various configuration properties.
The remainder of this section describes how the standard Felix launcher works as well as how to create a custom launcher for Felix.
| Anchor | ||||
|---|---|---|---|---|
|
Standard Felix Framework Launcher
The standard Felix framework launcher is very simple and is not intended to solve every possible requirement; it is intended to work for most standard situations. Most special launching requirements should be resolved by creating a custom launcher. This section describes how the standard launcher works. The following code represents the complete main() method of the standard launcher, each numbered comment will be described in more detail below:
| Code Block |
|---|
public static void main(String[] args) throws Exception
{
// (1) Check for command line arguments and verify usage.
String bundleDir = null;
String cacheDir = null;
boolean expectBundleDir = false;
for (int i = 0; i < args.length; i++)
{
if (args[i].equals(BUNDLE_DIR_SWITCH))
{
expectBundleDir = true;
}
else if (expectBundleDir)
{
bundleDir = args[i];
expectBundleDir = false;
}
else
{
cacheDir = args[i];
}
}
if ((args.length > 3) || (expectBundleDir && bundleDir == null))
{
System.out.println("Usage: [-b <bundle-deploy-dir>] [<bundle-cache-dir>]");
System.exit(0);
}
// (2) Load system properties.
Main.loadSystemProperties();
// (3) Read configuration properties.
Properties configProps = Main.loadConfigProperties();
if (configProps == null)
{
System.err.println("No " + CONFIG_PROPERTIES_FILE_VALUE + " found.");
configProps = new Properties();
}
// (4) Copy framework properties from the system properties.
Main.copySystemProperties(configProps);
// (5) Use the specified auto-deploy directory over default.
if (bundleDir != null)
{
configProps.setProperty(AutoProcessor.AUTO_DEPLOY_DIR_PROPERY, bundleDir);
}
// (6) Use the specified bundle cache directory over default.
if (cacheDir != null)
{
configProps.setProperty(Constants.FRAMEWORK_STORAGE, cacheDir);
}
// (7) Add a shutdown hook to clean stop the framework.
String enableHook = configProps.getProperty(SHUTDOWN_HOOK_PROP);
if ((enableHook == null) || !enableHook.equalsIgnoreCase("false"))
{
Runtime.getRuntime().addShutdownHook(new Thread("Felix Shutdown Hook") {
public void run()
{
try
{
if (m_fwk != null)
{
m_fwk.stop();
m_fwk.waitForStop(0);
}
}
catch (Exception ex)
{
System.err.println("Error stopping framework: " + ex);
}
}
});
}
// Print welcome banner.
System.out.println("\nWelcome to Felix");
System.out.println("================\n");
try
{
// (8) Create an instance and initialize the framework.
FrameworkFactory factory = getFrameworkFactory();
m_fwk = factory.newFramework(configProps);
m_fwk.init();
// (9) Use the system bundle context to process the auto-deploy
// and auto-install/auto-start properties.
AutoProcessor.process(configProps, m_fwk.getBundleContext());
// (10) Start the framework.
m_fwk.start();
// (11) Wait for framework to stop to exit the VM.
m_fwk.waitForStop(0);
System.exit(0);
}
catch (Exception ex)
{
System.err.println("Could not create framework: " + ex);
ex.printStackTrace();
System.exit(-10);
}
}
|
The general steps of the standard launcher are quite straightforward:
- The launcher supports setting the auto-deploy directory (with the
-bswitch) and setting the bundle cache path with a single argument, so check for this and issue a usage message it there are more than one arguments. - Load any system properties specified in the
system.propertiesfile; this file is typically located in theconf/directory of the Felix installation directory, but it can be specified directly using thefelix.system.propertiessystem property. This file is not needed to launch Felix and is provided merely for convenience when system properties must be specified. The file is a standard Java properties file, but it also supports property substitution using${<property-name} syntax. Property substitution can be nested; only system properties will be used for substitution. - Load any configuration properties specified in the
config.propertiesfile; this file is typically located in theconf/directory of the Felix installation directory, but it can be specified directly using thefelix.config.propertiessystem property. This file is used to configure the Felix framework instance created by the launcher. The file is a standard Java properties file, but it also supports property substitution using "${<property-name>}" syntax. Property substitution can be nested; configuration and system properties will be used for substitution with configuration properties having precedence. - For convenience, any configuration properties that are set as system properties are copied into the set of configuration properties. This provide an easy way to add to or override configuration properties specified in the
config.propertiesfile, since the Felix instance will never look at system properties for configuration. - If the
-bswitch was used to specify an auto-deploy directory, then use that to set the value offelix.auto.deploy.dir. - If a single command-line argument is specified, then use that to set the value of
org.osgi.framework.storage; relative paths are relative to the current directory unless thefelix.cache.rootdirproperty is set. - Add a shutdown hook to cleanly stop the framework, unless the hook is disabled.
- Create a framework instance using the
FrameworkFactorypassing in the configuration properties, then initialize the factory instance; see the custom launcher example below to see how the META-INF/servicesFrameworkFactoryis obtained. - Use
org.apache.felix.main.AutoProcessor, which will automatically deploy any bundles in the auto-deploy directory as well as bundles specified in thefelix.auto.installandfelix.auto.startconfiguration properties during framework startup to automatically install and/or start bundles; see the usage document for more information configuration properties and bundle auto-deploy. - Invoke
waitForStop()to wait for the framework to stop to force the VM to exit; this is necessary because the framework never callsSystem.exit()and some libraries (e.g., Swing) create threads that will not allow the VM to exit.
...