Chapter 1. Introduction to OSGi
The OSGi specification supports modular application development by defining a runtime framework that simplifies building, deploying, and managing complex applications.
Apache Karaf is an OSGi-based runtime container for deploying and managing bundles. Apache Karaf also provides native operating system integration, and can be integrated into the operating system as a service so that the lifecycle is bound to the operating system.
Apache Karaf has the following structure:
- Apache Karaf - a wrapper layer around the OSGi container implementation, which provides support for deploying the OSGi container as a runtime server. Runtime features provided by the Fuse include hot deployment, management, and administration features.
- OSGi Framework - implements OSGi functionality, including managing dependencies and bundle lifecycles
1.2. Architecture of Apache Karaf
Apache Karaf extends the OSGi layers with the following functionality:
- Console - the console manages services, installs and manages applications and libraries, and interacts with the Fuse runtime. It provides console commands to administer instances of Fuse. See the Apache Karaf Console Reference.
- Logging - the logging subsystem provides console commands to display, view and change log levels.
Deployment - supports both manual deployment of OSGi bundles using the
bundle:startcommands and hot deployment of applications. See Section 6.1, “Hot Deployment”.
- Provisioning - provides multiple mechanisms for installing applications and libraries. See Chapter 9, Deploying Features.
Configuration - the properties files stored in the InstallDir
/etcfolder are continuously monitored, and changes to them are automatically propagated to the relevant services at configurable intervals.
- Blueprint - is a dependency injection framework that simplifies interaction with the OSGi container. For example, providing standard XML elements to import and export OSGi services. When a Blueprint configuration file is copied to the hot deployment folder, Red Hat Fuse generates an OSGi bundle on-the-fly and instantiates the Blueprint context.
1.3. OSGi Framework
The OSGi Alliance is an independent organization responsible for defining the features and capabilities of the OSGi Service Platform Release 4. The OSGi Service Platform is a set of open specifications that simplify building, deploying, and managing complex software applications.
OSGi technology is often referred to as the dynamic module system for Java. OSGi is a framework for Java that uses bundles to modularly deploy Java components and handle dependencies, versioning, classpath control, and class loading. OSGi’s lifecycle management allows you to load, start, and stop bundles without shutting down the JVM.
OSGi provides the best runtime platform for Java, a superior class loading architecture, and a registry for services. Bundles can export services, run processes, and have their dependencies managed. Each bundle can have its requirements managed by the OSGi container.
Fuse uses Apache Felix as its default OSGi implementation. The framework layers form the container where you install bundles. The framework manages the installation and updating of bundles in a dynamic, scalable manner, and manages the dependencies between bundles and services.
1.3.2. OSGi architecture
The OSGi framework contains the following:
- Bundles — Logical modules that make up an application. See Section 1.5, “OSGi Bundles”.
- Service layer — Provides communication among modules and their contained components. This layer is tightly integrated with the lifecycle layer. See Section 1.4, “OSGi Services”.
- Lifecycle layer — Provides access to the underlying OSGi framework. This layer handles the lifecycle of individual bundles so you can manage your application dynamically, including starting and stopping bundles.
- Module layer — Provides an API to manage bundle packaging, dependency resolution, and class loading.
- Execution environment — A configuration of a JVM. This environment uses profiles that define the environment in which bundles can work.
- Security layer — Optional layer based on Java 2 security, with additional constraints and enhancements.
Each layer in the framework depends on the layer beneath it. For example, the lifecycle layer requires the module layer. The module layer can be used without the lifecycle and service layers.
1.4. OSGi Services
An OSGi service is a Java class or service interface with service properties defined as name/value pairs. The service properties differentiate among service providers that provide services with the same service interface.
An OSGi service is defined semantically by its service interface, and it is implemented as a service object. A service’s functionality is defined by the interfaces it implements. Thus, different applications can implement the same service.
Service interfaces allow bundles to interact by binding interfaces, not implementations. A service interface should be specified with as few implementation details as possible.
1.4.2. OSGi service registry
In the OSGi framework, the service layer provides communication between Section 1.5, “OSGi Bundles” and their contained components using the publish, find, and bind service model. The service layer contains a service registry where:
- Service providers register services with the framework to be used by other bundles
- Service requesters find services and bind to service providers
Services are owned by, and run within, a bundle. The bundle registers an implementation of a service with the framework service registry under one or more Java interfaces. Thus, the service’s functionality is available to other bundles under the control of the framework, and other bundles can look up and use the service. Lookup is performed using the Java interface and service properties.
Each bundle can register multiple services in the service registry using the fully qualified name of its interface and its properties. Bundles use names and properties with LDAP syntax to query the service registry for services.
A bundle is responsible for runtime service dependency management activities including publication, discovery, and binding. Bundles can also adapt to changes resulting from the dynamic availability (arrival or departure) of the services that are bound to the bundle.
Service interfaces are implemented by objects created by a bundle. Bundles can:
- Register services
- Search for services
- Receive notifications when their registration state changes
The OSGi framework provides an event notification mechanism so service requesters can receive notification events when changes in the service registry occur. These changes include the publication or retrieval of a particular service and when services are registered, modified, or unregistered.
Service invocation model
When a bundle wants to use a service, it looks up the service and invokes the Java object as a normal Java call. Therefore, invocations on services are synchronous and occur in the same thread. You can use callbacks for more asynchronous processing. Parameters are passed as Java object references. No marshalling or intermediary canonical formats are required as with XML. OSGi provides solutions for the problem of services being unavailable.
OSGi framework services
Package Admin service—allows a management agent to define the policy for managing Java package sharing by examining the status of the shared packages. It also allows the management agent to refresh packages and to stop and restart bundles as required. This service enables the management agent to make decisions regarding any shared packages when an exporting bundle is uninstalled or updated.
The service also provides methods to refresh exported packages that were removed or updated since the last refresh, and to explicitly resolve specific bundles. This service can also trace dependencies between bundles at runtime, allowing you to see what bundles might be affected by upgrading.
- Start Level service—enables a management agent to control the starting and stopping order of bundles. The service assigns each bundle a start level. The management agent can modify the start level of bundles and set the active start level of the framework, which starts and stops the appropriate bundles. Only bundles that have a start level less than, or equal to, this active start level can be active.
- URL Handlers service—dynamically extends the Java runtime with URL schemes and content handlers enabling any component to provide additional URL handlers.
- Permission Admin service—enables the OSGi framework management agent to administer the permissions of a specific bundle and to provide defaults for all bundles. A bundle can have a single set of permissions that are used to verify that it is authorized to execute privileged code. You can dynamically manipulate permissions by changing policies on the fly and by adding new policies for newly installed components. Policy files are used to control what bundles can do.
- Conditional Permission Admin service—extends the Permission Admin service with permissions that can apply when certain conditions are either true or false at the time the permission is checked. These conditions determine the selection of the bundles to which the permissions apply. Permissions are activated immediately after they are set.
The OSGi framework services are described in detail in separate chapters in the OSGi Service Platform Release 4 specification available from the release 4 download page on the OSGi Alliance web site.
OSGi Compendium services
In addition to the OSGi framework services, the OSGi Alliance defines a set of optional, standardized compendium services. The OSGi compendium services provide APIs for tasks such as logging and preferences. These services are described in the OSGi Service Platform, Service Compendium available from the release 4 download page on the OSGi Alliance Web site.
The Configuration Admin compendium service is like a central hub that persists configuration information and distributes it to interested parties. The Configuration Admin service specifies the configuration information for deployed bundles and ensures that the bundles receive that data when they are active. The configuration data for a bundle is a list of name-value pairs. See Section 1.2, “Architecture of Apache Karaf”.
1.5. OSGi Bundles
With OSGi, you modularize applications into bundles. Each bundle is a tightly coupled, dynamically loadable collection of classes, JARs, and configuration files that explicitly declare any external dependencies. In OSGi, a bundle is the primary deployment format. Bundles are applications that are packaged in JARs, and can be installed, started, stopped, updated, and removed.
OSGi provides a dynamic, concise, and consistent programming model for developing bundles. Development and deployment are simplified by decoupling the service’s specification (Java interface) from its implementation.
The OSGi bundle abstraction allows modules to share Java classes. This is a static form of reuse. The shared classes must be available when the dependent bundle is started.
A bundle is a JAR file with metadata in its OSGi manifest file. A bundle contains class files and, optionally, other resources and native libraries. You can explicitly declare which packages in the bundle are visible externally (exported packages) and which external packages a bundle requires (imported packages).
The module layer handles the packaging and sharing of Java packages between bundles and the hiding of packages from other bundles. The OSGi framework dynamically resolves dependencies among bundles. The framework performs bundle resolution to match imported and exported packages. It can also manage multiple versions of a deployed bundle.
Class Loading in OSGi
Each bundle has its own internal classpath so that it can serve as an independent unit if required.
The benefits of class loading in OSGi include:
- Sharing classes directly between bundles. There is no requirement to promote JARs to a parent class-loader.
- You can deploy different versions of the same class at the same time, with no conflict.