| Close Window |
The Open Services Gateway Initiative (OSGi) Alliance is working to realize the vision of a "universal middleware" that will address issues such as application packaging, versioning, deployment, publication, and discovery.
In this article we'll examine the need for the kind of container model provided by the OSGi, outline the capabilities it would provide, and discuss its relationship to complementary technologies such as SOA, SCA, and Spring. Enterprise software is often composed of large amounts of complex interdependent logic that makes it hard to adapt readily to changes in requirements from the business. You can enable this kind of agility by following a Service Oriented Architecture (SOA) pattern that refactors a system into application modules grouped by business functions that expose their public functionality as services (interfaces).
For example, a customer relationship management (CRM) solution would have modules such as sales, marketing, call center, and customer service. These modules use services exposed by other modules. To implement such a modular SOA pattern in Java-based enterprise systems there are often issues such as class conflict, unintended use of internal functions, interrupted upgrades, and multiple versions. Problems such as bundling, abstractions, dependencies, dynamic loading, lifecycle management, and side-by-side versioning are programmers' nightmares. Ideally containers should take care of these common issues, freeing application developers to solve the business problems.
Unfortunately many containers, including Enterprise JavaBeans (EJB), don't solve these issues satisfactorily. In this article, we'll explain how an Open Services Gateway initiative (OSGi) container would solve them. We'll begin with an introduction to the OSGi's solution to the problem, concepts, and platform, and then we'll delve into the evolution of the OSGi from its past in the world of embedded devices to its future in enterprise systems. We'll also explain the relationship between the OSGi and other initiatives, containers, and technologies to provide a comprehensive picture of the OSGi from the perspective of software development.
OSGi's Background
In March 1999, the OSGi Alliance was formed to provide a dynamic component model for service gateways to develop networked embedded systems.
The OSGi specifications developed provide a standardized, component-oriented platform for Java-based software. The platform solves the dynamic loading, versioning, and lifecycle management issues for Java-based services and also provides services to develop an ecosystem around it. In the last few years, OSGi has progressed far enough beyond embedded systems that its promoters are positioning it as universal middleware.
In retrospect, the use of "G" for "gateway" in the OSGi acronym is something of a misnomer. Universal middleware has a broader scope than just gateways, which are typically brokers on a network edge that provide interaction between external and internal networks. The use of the OSGi specification has broadened beyond embedded devices. This trend is noticeable in the alliance's supporting organizations too. Initially most of the supporting organizations were from the embedded space. Currently they've expanded to include major J2EE application vendors, ESB and middleware vendors.
Introduction to OSGi's Solution and Its Architecture
OSGi provides a component-oriented, lightweight container framework to host dynamically managed services. A module, called bundles in the OSGi, is a jar containing interfaces, their implementations, other classes, and a manifest. A bundle is a basic module for packaging, deploying, and managing the lifecycle of a group of services.
OSGi Bundles Provide an Isolation Model
Each OSGi bundle encapsulates packaged services and controls their visibility through metadata in a manifest file. As shown in Figure 1, a package or service in a module can be made available to other modules by explicitly exporting it. Other modules can't access any internal, non-exported interfaces or their implementations or other internal classes. In Figure 1, notice the import statements. Classes from other bundles can use these exported services by explicitly declaring imports.
OSGi Container Manages Lifecycle & Supports Dynamic Loading
Modules go through lifecycle events such as deploy (install), start, stop, redeploy, and uninstall. When a module (bundle) is being installed, the container checks all the dependencies (imports). If all the dependencies are satisfied, the module is ready to start. Figure 2 shows the lifecycle management of OSGi bundles. The OSGi runtime container provides a lightweight microkernel in which modules can be dynamically added or removed.
OSGi Natively Supports Dynamic Versioning of Services
During the long life span of enterprise software, business and technology changes. The software must reflect these changes and upgrade different modules independently of each other. For example, a company might have a customer data model (CDM) for its sales, order capture, and marketing systems. When there's an upgrade of the CDM, the company might choose to upgrade sales and marketing systems. However, upgrading the order capture system could have implications for business process or stability and so might not be upgraded at the same time, resulting in a need to support two versions of the CDM simultaneously.
The OSGi specification natively supports versioning with version attributes in the export and import instructions (see Figure 1) in the manifest files. It also provides additional control via arbitrary export/import attributes. The selection of an imported service or bundle is based on its version and attribute(s). OSGi also provides a unique isolation model in which multiple versions of the same service can co-exist and each service instance is isolated from the potential problems of class conflicts. A service consumer can get a reference to the correct version by specifying a version and other attributes in a filter as shown in Figure 3.
OSGi Provides a Service-Oriented Programming Model
OSGi also provides a programming model based on SOA. It's important to note that OSGi natively provides service-oriented programming in a dynamic environment. Unlike the RMI service registry, the OSGi service registry is native to the container - the services are automatically registered during the load without having to register them programmatically. A publisher can register a service using the registerService method in its BundleContext. Similarly, a service requester can discover a service using the getServiceReference method from its BundleContext. Unlike EJB or RMI, the services don't need to implement any remotable interface. It's all POJO!
OSGi Can Handle the Dynamic Lifecycle of Services
Again, in enterprise software you can add or remove modules. Since the container automatically manages the registration and deregistration, application programmers have to understand that services come and go at any time. OSGi provides a framework to track and react to lifecycle changes in the service, sending notifications of the registrations and deregistrations to a service layer that also provides a service tracker utility to help client programming in this dynamic environment (Figure 3). There's also a declarative model to handle lifecycle changes. Other containers like EJB/RMI don't handle such changes in lifecycle.
OSGi and Spring: Providing a Stable Proxy in a Dynamic Environment
The OSGi/Spring combination further enriches the solution to the dynamic lifecycle problem. Interface21 is already working to develop OSGi/Spring integration, and in March 2007 provided a first milestone drop for download. The current specification is version 0.7 and is still being evolved. The specification's stated goal is to provide an "easier path to build Spring applications that can be deployed in an OSGi execution environment and that can take advantage of the services offered by the OSGi framework."
The goal of the OSGi/Spring effort is to combine the best features of both OSGi and the Spring framework. This integrated framework inherits isolations and modularity, side-by-side versioning, dynamic deployment, and updates and dynamic discovery from OSGi. Spring provides an easy-to-use framework based on dependency injection (DI) and aspect-oriented programming (AOP), powered by various services.
Spring provides a simple, familiar programming model that enterprise developers can use to exploit the features of the OSGi platform. The OSGi/Spring combination also manages the switching of services in the background. Spring provides a stable proxy for services that can dynamically come and go. If a service in use needs a behind-the-scenes upgrade, the Spring-based proxy lets you to bring down the service and replace it without a glitch in the stateless environment. In stateful Web Services, clients must track the lifecycle of the target service. The OSGi/Spring combination provides a service binder framework to track and react to the binding and unbinding of the target services. The Spring framework provides a stable proxy in a dynamic environment, and the OSGi platform provides dynamic lifecycle and versioning.
OSGi Architecture & Services
Now that you
understand OSGi's capabilities, it would make sense to understand its
architecture. The OSGi platform provides core framework and platform
services. The core framework provides a runtime foundation to run and
manage the lifecycle of various applications in a secured and
modularized environment. The framework has four layers: security,
modularization, lifecycle, and service.
The security layer provides additions to Java security that restrict
the public and private exposure of packages and services and also
provides permissions to import/export packages and register/access
services from the service registry.
The modularization layer handles class loading, versioning, and the
import/export of packages. It also manages the dependency resolutions
of bundles.
The lifecycle layer manages the lifecycle of bundles and provides a generic API abstraction to enable remote management in a variety of management models.
The service layer adds a dynamic behavior to the OSGi platform in which bundles can come and go. The heart of this layer is a service registry in which services are registered and discovered. The framework handles automatic registration and deregistration and triggers lifecycle events. OSGi further provides a declarative model to express service registrations and dependencies in an XML declaration. This declarative framework supports lazy (delayed) loading of resources by loading them only when they're actually needed.
The OSGi ecosystem platform provides various service interfaces that can be implemented by vendors, depending on the nature of their applications. The OSGi framework may provide a permission admin service, conditional permission admin service, a package admin service, and URL handler service. The OSGi Alliance specifies various system services such as a log service, and administrative services for managing configuration, event administration, users, devices, and applications. The Alliance has also defined an HTTP service so that bundles can provide servlets that can be made available over HTTP. Besides declaration and event services, in release 4, the Alliance defined a wire admin service to manage configuration-based connectivity between a service producer and consumers, enabling data objects to be exchanged over a wire. (Figure 4)
Recent Momentum
Those who are using the Eclipse
3.0 framework are already using OSGi indirectly. When Eclipse-based
applications became more complex, Eclipse needed an appropriate
framework that could provide a dynamic, modular, and flexible runtime.
The Eclipse group found that the OSGi framework satisfied most of their
requirements. The Eclipse 3.0+ plug-in framework is based on OSGi.
Eclipse's use of OSGi is now being evolved as the Equinox project.
Eclipse's use of OSGi caught the attention of the developer community. Besides Eclipse, there are currently many other open source projects such as Apache's Felix, Newton, Knopflerfish, and OXSA. These open source implementations provide a meaningful way for developers and researchers to adapt the platform. Extensive adoption made 2007 a good year for OSGi. IBM and Cisco announced plans to develop a unified communications and collaboration platform called UC2 based on OSGi. And early last year Spring made its first milestone drop available to the public. Most of the leading application server vendors such as Oracle, IBM, and BEA either have an OSGi container in their stacks already or are working to add it.
With Eclipse, application servers, and other open source projects, OSGi has entered the mainstream to solve the modularization problems (dynamic modular deployment, versioning, and so on) of Java applications. The next step in its evolution is to provide interconnectivity for OSGi servers hosting services that can be moved from one server to another.
Future Evolution of OSGi Distributed OSGi:
A Journey Towards Universal Middleware
The OSGi specification has, by and large, assumed an environment
constrained to a single Java virtual machine (JVM) in that its service
repository is referenced as local in-memory objects and the bundles are
loaded and accessed via direct references in the same JVM. To be
universal middleware, OSGi has to tackle the issues related to
distributed computing, which it has started to do. There are a few key
issues: How does one discover services on the network? And how can one
invoke them?
To address the service discovery and remote services issues, OSGi's R3 specification included recommendations to use Jini and universal plug and play (UPnP). Recently, during the Eclipse 2007 conference, a third approach called R-OSGi was introduced. It's based on a discovery protocol called the service location protocol (SLP), a lightweight, decentralized, extensible protocol (see Figure 5).
However, each option has its own set of issues. The issues are mainly incompatibility between the remote service interfaces - Jini attributes don't match with OSGi, and Jini's reference implementation is based on the RMI invocation framework, which is perceived to be too heavy for OSGi devices. UPnP has a separate set of issues. Although UPnP is still recommended in OSGi R4, Jini is thrown out apparently because of issues such as interactions between class loaders and incompatibilities between security models. Although Jini didn't see a lot of momentum and releases, the specification provided a robust platform for some applications, including financial applications. Moreover, there's an open source initiative called Newton, and its commercial product, Infiniflow, which supports OSGi and Jini. Last year, after Sun open sourced its reference implementation, we expected some momentum, but it hasn't materialized.
The R-OSGi prototype uses SLP as a discovery protocol and provides a framework for service invocation based on dynamically generated proxies. R-OSGi also provides a way to define abstract proxies. During an R-OSGi demo, we observed that it has a very small footprint, but it needs some effort to make it robust. Moreover, the R-OSGi's service invocation protocol is optimized but proprietary. A standards-based approach would have been preferable. It seems that R-OSGi doesn't use RMI for performance reasons and issues related to RMI's distributed garbage collection when working with the OSGi lifecycle.
Service discovery and remote invocation doesn't provide complete distributed functionalities to OSGi. A new enterprise expert group was formed inside OSGi to look into the issues of taking OSGi to the enterprise level. The group has proposed works in areas of distributed registry, interaction with external systems, enterprise Web applications, and OSGi with J2EE, SCA, Spring, and so on. However, instead of charting yet-another new course, we believe the OSGi should reuse the appropriately relevant work already done in the J2EE and WS arenas.
OSGi & SCA: A Possible Alliance
Service
Component Architecture (SCA) provides an assembly model for building
composite applications using services implemented in a variety of
technologies. SCA already has support from the major application
servers and enterprise service bus (ESB) vendors. The SCA specification
has been submitted to OASIS for standardization. Now work can be
initiated for an integration plan for SCA and OSGi.
Conceptually both SCA and OSGi provide a composite model for assembling a services-based composite application that can expose some services to the external world as well as invoke external services. In OSGi R4, declarative services define a model to declare a component in XML, capturing its implementation and references. Besides SCA-like component-level information, the OSGi model captures additional information to control runtime behavior. For example, R4 provides bind/unbind methods to track the lifecycle or manage target services dynamically. SCA metadata defines wires between components or from a component to a reference in its composite model. However, SCA doesn't dictate a runtime implementation. OSGi defines wires in a composite model but lets the administrator add and delete wires using wire admin services (see Figure 6).
For OSGi-SCA integration, there are three possible scenarios:
• OSGi is a container for the SCA runtime
• OSGi and SCA are peers that can import and export each other's services
• OSGi as yet-another implementation type of SCA service
Where Do We Go from Here?
We'd like to see OSGi
evolve, specifically in the enterprise market. It has definite uses as
a microkernel in application servers. Other uses may evolve - service
platforms are leveraging powerful combinations of two or more
frameworks, such as OSGi, SCA, and Spring. OSGi would be useful for
building SOA and enterprise applications, expanding OSGi's applications
beyond embedded and network devices and microkernel and application
servers. Some ESB vendors would find OSGi's dynamic services capability
useful too. Different technologies working together with the OSGi could
make a powerful platform to build large, complex enterprise
applications.
© 2008 SYS-CON Media Inc.