Beginner to OSGi:
Layering
Modules
Services
Deployment
Implementations
Conclusion
OSGi technology is a set of specifications that defines a dynamic component system for Java. These
specifications reduce software complexity by providing a modular architecture
for large-scale distributed systems as well as small, embedded applications.
OSGi is a Java-based framework for creating applications as a set
of interconnected modules. OSGi lets you install, start, stop, update, or
uninstall modules at execution time without taking down your entire system.
It's the backbone of the Eclipse plugin system, as well as many Java EE
containers, such as GlassFish, Geronimo, and WebSphere.
OSGi is the powerful dynamic framework that underlies the Eclipse
IDE and platform, but its use is not restricted to Eclipse. In fact it is used
everywhere from mobile phone and vehicle entertainment systems to enterprise
application servers. It is, essentially, the module system for Java.
DEVELOPERS
OSGi reduces
complexity by providing a modular architecture for today's large-scale
distributed systems as well as small, embedded applications. Building systems
from in-house and off-the-shelf modules significantly reduces complexity and
thus development and maintenance expenses. The OSGi programming model realizes
the promise of component-based systems.
BUSINESS
The OSGi modular and
dynamic model reduces operational costs and integrates multiple devices in a
networked environment, tackling costly application development, maintenance and
remote service management.
The key reason OSGi technology is so
successful is that it provides a very mature component system that actually
works in a surprising number of environments. The OSGi component system is
actually used to build highly complex applications like IDEs (Eclipse), application
servers (GlassFish, IBM Websphere, Oracle/BEA Weblogic, Jonas, JBoss),
application frameworks (Spring, Guice), industrial
automation, residential gateways, phones, and so much more.
So, what benefits does OSGi's component system provide you? Well,
quite a list:
- Reduced
Complexity -
Developing with OSGi technology means developing bundles: the OSGi
components. Bundles are modules. They hide their internals from other
bundles and communicate through well defined services. Hiding
internals means more freedom to change later. This not only reduces the
number of bugs, it also makes bundles simpler to develop because correctly
sized bundles implement a piece of functionality through well defined
interfaces. There is an interesting blog that describes what OSGi technology did
for their development process.
- Reuse - The OSGi component
model makes it very easy to use many third party components in an
application. An increasing number of open source projects provide their
JARs ready made for OSGi. However, commercial libraries are also becoming
available as ready made bundles.
- Real
World -
The OSGi framework is dynamic. It can update bundles on the fly and
services can come and go. Developers used to more traditional Java see
this as a very problematic feature and fail to see the advantage. However,
it turns out that the real world is highly dynamic and having dynamic
services that can come and go makes the services a perfect match for many
real world scenarios. For example, a service could model a device in the
network. If the device is detected, the service is registered. If the
device goes away, the service is unregistered. There are a surprising
number of real world scenarios that match this dynamic service model.
Applications can therefore reuse the powerful primitives of the service
registry (register, get, list with an expressive filter language, and
waiting for services to appear and disappear) in their own domain. This
not only saves writing code, it also provides global visibility, debugging
tools, and more functionality than would have implemented for a dedicated
solution. Writing code in such a dynamic environment sounds like a
nightmare, but fortunately, there are support classes and frameworks that
take most, if not all, of the pain out of it.
- Easy
Deployment -
The OSGi technology is not just a standard for components. It also
specifies how components are installed and managed. This API has been used
by many bundles to provide a management agent. This management agent can
be as simple as a command shell, a TR-69 management protocol driver, OMA DM protocol driver, a cloud computing interface for Amazon's
EC2, or an IBM Tivoli management system. The standardized
management API makes it very easy to integrate OSGi technology in existing
and future systems.
- Dynamic
Updates -
The OSGi component model is a dynamic model. Bundles can be installed,
started, stopped, updated, and uninstalled without bringing down the whole
system. Many Java developers do not believe this can be done reliably and
therefore initially do not use this in production. However, after using
this in development for some time, most start to realize that it actually
works and significantly reduces deployment times.
- Adaptive - The OSGi component
model is designed from the ground up to allow the mixing and matching of
components. This requires that the dependencies of components need to be
specified and it requires components to live in an environment where their
optional dependencies are not always available. The OSGi service registry
is a dynamic registry where bundles can register, get, and listen to services.
This dynamic service model allows bundles to find out what capabilities
are available on the system and adapt the functionality they can provide.
This makes code more flexible and resilient to changes.
- Transparency - Bundles and services
are first class citizens in the OSGi environment. The management API
provides access to the internal state of a bundle as well as how it is
connected to other bundles. For example, most frameworks provide a command
shell that shows this internal state. Parts of the applications can be
stopped to debug a certain problem, or diagnostic bundles can be brought
in. Instead of staring at millions of lines of logging output and long
reboot times, OSGi applications can often be debugged with a live command
shell.
- Versioning - OSGi technology
solves JAR hell. JAR hell is the problem that library A works with library
B;version=2, but library C can only work with B;version=3. In standard
Java, you're out of luck. In the OSGi environment, all bundles are
carefully versioned and only bundles that can collaborate are wired
together in the same class space. This allows both bundle A
and C to function with their own library. Though it is not advised to
design systems with this versioning issue, it can be a life saver in some
cases.
- Simple - The OSGi API is
surprisingly simple. The core API is only one package and less than 30
classes/interfaces. This core API is sufficient to write bundles, install
them, start, stop, update, and uninstall them and includes all listener
and security classes. There are very few APIs that provide so much
functionality for so little API.
- Small - The OSGi Release 4
Framework can be implemented in about a 300KB JAR file. This is a small
overhead for the amount of functionality that is added to an application
by including OSGi. OSGi therefore runs on a large range of devices: from
very small, to small, to mainframes. It only asks for a minimal Java VM to
run and adds very little on top of it.
- Fast - One of the primary
responsibilities of the OSGi framework is loading the classes from
bundles. In traditional Java, the JARs are completely visible and placed
on a linear list. Searching a class requires searching through this (often
very long, 150 is not uncommon) list. In contrast, OSGi pre-wires bundles
and knows for each bundle exactly which bundle provides the class. This
lack of searching is a significant speed up factor at startup.
- Lazy - Lazy in software is
good and the OSGi technology has many mechanisms in place to do things
only when they are really needed. For examples, bundles can be started
eagerly, but they can also be configured to only start when another bundle
is using them. Services can be registered but only created when they are
used. The specifications have been optimized several times to allow for
these kind of lazy scenarios that can save tremendous runtime costs.
- Secure - Java has a very
powerful fine grained security model at the bottom but it has turned out
very hard to configure in practice. The result is that most secure Java
applications are running with a binary choice: no security or very limited
capabilities. The OSGi security model leverages the fine grained security
model but improves the usability (as well as hardening the original model)
by having the bundle developer specify the requested security details in
an easily audited form while the operator of the environment remains fully
in charge. Overall, OSGi likely provides one of the most secure
application environments that is still usable short of hardware protected
computing platforms.
- Humble - Many frameworks take
over the whole VM, they only allow one instance to run in a VM. The
flexibility of the OSGi specifications is demonstrated by how it can even
run inside a J2EE Application Server. Many developers wanted to run OSGi
but their companies did not allow them to deploy normal JARs. Instead,
they included an OSGi framework in their WAR file and loaded their bundles
from the file system or over the network. OSGi is so flexible that one
application server can easily host multiple OSGi frameworks.
- Non
Intrusive -
Applications (bundles) in an OSGi environment are left to their own. They
can use virtually any facility of the VM without the OSGi restricting
them. Best practice in OSGi is to write Plain Old Java Objects and for
this reason, there is no special interface required for OSGi services,
even a Java String object can act as an OSGi service. This strategy makes
application code easier to port to another environment.
- Runs
Everywhere -
Well, that depends. The original goal of Java was to run anywhere.
Obviously, it is not possible to run all code everywhere because the
capabilities of the Java VMs differ. A VM in a mobile phone will likely
not support the same libraries as an IBM mainframe running a banking
application. There are two issue to take care of. First, the OSGi APIs
should not use classes that are not available on all environments. Second,
a bundle should not start if it contains code that is not available in the
execution environment. Both of these issues have been taken care of in the
OSGi specifications.
- Widely
Used -
The OSGi specifications started out in the embedded home automation market
but since 1998 they have been extensively used in many industries:
automotive, mobile telephony, industrial automation, gateways &
routers, private branch exchanges, fixed line telephony, and many more.
Since 2003, the highly popular Eclipse Integrated Development Environment
runs on OSGi technology and provides extensive support for bundle
development. In the last few years, OSGi has been taken up by the
enterprise developers. Eclipse developers discovered the power of OSGi
technology but also the Spring Framework helped popularize this technology
by creating a specific extension for OSGi. Today, you can find OSGi
technology at the foundation of IBM Websphere, SpringSource dm Server,
Oracle (formerly BEA) Weblogic, Sun's GlassFish, and Redhat's JBoss.
- Supported
by Key Companies -
OSGi counts some of the largest computing companies from a diverse set of
industries as its members. Members are from: Oracle, IBM, Samsung,
Nokia, Progress, Motorola, NTT, Siemens, Hitachi, Deutsche Telekom,
Redhat, Ericsson, and many more.
The OSGi specifications were started in 1998 and were intended for
the home automation market, trying to solve the problem how to build
applications out of independent components. In the past decade, the software
industry was fundamentally changed because of the explosion in open source
projects. Ten years ago, an application consisted mostly of specifically
written code. Today, most software is largely wiring up open source artifacts
that were often not designed to work together. This is similar to the problem
that OSGi was designed to solve. Many open source projects are therefore
adopting the OSGi specifications because they see that they can focus on the
real problem and worry less about infrastructure, as well as becoming easier to
use in other projects. This trend is accelerating.
If you are developing software in Java then OSGi technology should
be a logical next step because it solves many problems that you might not even
be aware can be solved. The advantages of OSGi technology are so numerous that
if you are using Java, then OSGi should be in your tool chest.
The
OSGi Architecture:
The OSGi technology is a set of specifications that define a
dynamic component system for Java. These specifications enable a development
model where applications are (dynamically) composed of many different
(reusable) components. The OSGi specifications enable components to hide their
implementations from other components while communicating through services,
which are objects that are specifically shared between components. This
surprisingly simple model has far reaching effects for almost any aspect of the
software development process.
Though components have been on the horizon for a long time,
so far they failed to make good on their promises. OSGi is the first technology
that actually succeeded with a component system that is solving many real
problems in software development. Adopters of OSGi technology see significantly
reduced complexity in almost all aspects of development. Code is easier to
write and test, reuse is increased, build systems become significantly simpler,
deployment is more manageable, bugs are detected early, and the runtime
provides an enormous insight into what is running. Most important, it works as
is testified by the wide adoption and use in popular applications like Eclipse
and Spring.
We developed the OSGi technology to create a collaborative software
environment. We were not looking for the possibility to run multiple
applications in a single VM. Application servers do that already (though they
were not yet around when we started in 1998). No, our problem was harder. We
wanted an application to emerge from putting together different reusable components that had
no a-priori knowledge of
each other. Even harder, we wanted that application to emerge from dynamically assembling a set
of components. For example, you have a home server that is capable of managing
your lights and appliances. A component could allow you to turn on and off the
light over a web page. Another component could allow you to control the
appliances via a mobile text message. The goal was to allow these other
functions to be added without requiring that the developers had intricate
knowledge of each other and let these components be added independently.
Layering
The OSGi has a layered model that is depicted in the
following figure.
The following list contains a short definition of the terms:
- Bundles - Bundles are the OSGi components made
by the developers.
- Services - The services layer connects bundles
in a dynamic way by offering a publish-find-bind model for plain old Java
objects.
- Life-Cycle - The API to install, start, stop,
update, and uninstall bundles.
- Modules - The layer that defines how a bundle
can import and export code.
- Security - The layer that handles the security
aspects.
- Execution Environment - Defines what methods
and classes are available in a specific platform.
These concepts are more extensively explained in the
following sections.
Modules
The fundamental concept that enables such a system is modularity.
Modularity, simplistically said, is about assuming less. Modularity is about
keeping things local and not sharing. It is hard to be wrong about things you
have no knowledge of and make no assumptions about them. Therefore, modularity
is at the core of the OSGi specifications and embodied in thebundle concept. In Java terms, a bundle is a plain old JAR file.
However, where in standard Java everything in a JAR is completely visible to
all other JARs, OSGi hides everything in that JAR unless explicitly exported. A
bundle that wants to use another JAR must explicitly import the parts it needs.
By default, there is no sharing.
Though the code hiding and explicit sharing provides many
benefits (for example, allowing multiple versions of the same library being
used in a single VM), the code sharing was only there to support OSGi services model. The
services model is about bundles that collaborate.
Services
The reason we needed the service model is because Java shows
how hard it is to write collaborative model with only class sharing. The
standard solution in Java is to use factoriesthat use dynamic class loading and statics. For example, if
you want a DocumentBuilderFactory, you call the static factory method
DocumentBuilderFactory.newInstance(). Behind that façade, the newInstance
methods tries every class loader trick in the book (and some that aren't) to
create an instance of an implementation subclass of the DocumentBuilderFactory
class. Trying to influence what implementation is used is non-trivial (services
model, properties, conventions in class name), and usually global for the VM. Also
it is a passive model.
The implementation code can not do anything to advertise its availability, nor
can the user list the possible implementations and pick the most suitable
implementation. It is also not dynamic. Once an implementation hands out an instance,
it can not withdraw that object. Worst of all, the factory mechanism is aconvention used in hundreds of places in the VM where each factory has
its own unique API and configuration mechanisms. There is no centralized
overview of the implementations to which your code is bound.
The solution to all these issues is the OSGi service registry. A
bundle can create an object and register it with the OSGi service registry
under one or more interfaces. Other bundles can go to the registry and list all
objects that are registered under a specific interfaces or class. For example,
a bundle provides an implementation of the DocumentBuilder. When it gets started,
it creates an instance of its DocumentBuilderFactoryImpl class and registers it
with the registry under the DocumentBuilderFactory class. A bundle that needs a
DocumentBuilderFactory can go to the registry and ask for all available
services that extend the DocumentBuilderFactory class. Even better, a bundle
can wait for a specific service to appear and then get a call back.
A bundle can therefore register a service, it
can get a service, and
it can listen for a service to
appear or disappear. Any number of bundles can register the same service type,
and any number of bundles can get the same service. This is depicted in the
following figure.
What happens when multiple bundles register objects under
the same interface or class? How can these be distinguished? The answer is
properties. Each service registration has a set of standard and custom
properties. A expressive filter language is available to select only the
services in which you are interested. Properties can be used to find the proper
service or can play other roles at the application level.
Services are dynamic. This means that a bundle can decide to
withdraw its service from the registry while other bundles are still using this
service. Bundles using such a service must then ensure that they no longer use
the service object and drop any references. We know, this sounds like a
significant complexity but it turns out that helper classes like the Service
Tracker and frameworks like iPOJO, Spring, and Declarative Services can make
the pain minimal while the advantages are quite large. The service dynamics
were added so we could install and uninstall bundles on the fly while the other
bundles could adapt. That is, a bundle could still provide functionality even
if the http service went away. However, we found out over time that the real
world is dynamic and many problems are a lot easier to model with dynamic
services than static factories. For example, a Device service could represent a
device on the local network. If the device goes away, the service representing
it is unregistered. This way, the availability of the service models the
availability of a real world entity. This works out very well in, for example,
the distributed OSGi model where a service can be withdrawn if the connection
to the remote machine is gone. It also turns out that the dynamics solve the
initialization problem. OSGi applications do not require a specific start
ordering in their bundles.
The effect of the service registry has been that many
specialized APIs can be much modeled with the service registry. Not only does
this simplify the overall application, it also means that standard tools can be
used to debug and see how the system is wired up.
Though the service registry accepts any object as a service,
the best way to achieve reuse is to register these objects under (standard)
interfaces to decouple the implementer from the client code. This is the reason
the OSGi Alliance publishes the Compendium specifications. These specification
define a large number of standard services, from a Log Service to a Measurement
and State specification. All these standardized services are described in great
detail.
Deployment
Bundles are deployed on an OSGi framework, the bundle runtime environment. This is not a container like
Java Application Servers. It is a collaborative environment. Bundles run in the same VM and can
actually share code. The framework uses the explicit imports and exports to
wire up the bundles so they do not have to concern themselves with class
loading. Another contrast with the application servers is that the management
of the framework is standardized. A simple API allows bundles to install,
start, stop, and update other bundles, as well as enumerating the bundles and
their service usage. This API has been used by manymanagement agents to control OSGi frameworks. Management agents are as diverse as
the Knopflerfish desktop and an IBM Tivoli management server.
Implementations
The OSGi specification process requires
a reference implementation for each specification. However, since the first
specifications there have always been commercial companies that have
implemented the specifications as well as open source implementations. Currently,
there are 4 open source implementations of the framework and too many to count
implementations of the OSGi services. The open software industry has discovered
OSGi technology and more and more projects deliver their artifacts as bundles.
Conclusion
The OSGi specifications provide a mature and comprehensive
component model with a very effective (and small) API. Converting monolithic or
home grown plugin based systems to OSGi almost always provides great
improvements in the whole process of developing software.
Exp1:
http://www.osgi.org/Links/BasicEducation
1.
Get file org.eclipse.osgi_3.2.1.R32x_v20060919.jar and rename to equinox.jar for making cmd simple
Get file org.eclipse.osgi_3.2.1.R32x_v20060919.jar and rename to equinox.jar for making cmd simple
2.
>java -jar equinox.jar -console
>java -jar equinox.jar -console
Framework is launched.
id State Bundle
0 ACTIVE system.bundle_3.2.1.R32x_v20060919
3. Create a bundle.
import org.osgi.framework.*;
public class HelloActivator implements BundleActivator {
public void start(BundleContext context) {
System.out.println("Hello EclipseZone Readers!");
}
public void stop(BundleContext context) {
System.out.println("Goodbye EclipseZone Readers!");
}
}
4. A bundle also needs a manifest file HelloWorld.mf
Manifest-Version: 1.0
Bundle-Name: HelloWorld
Bundle-Activator: HelloActivator
Bundle-SymbolicName: HelloWorld
Bundle-Version: 1.0.0
Import-Package: org.osgi.framework
5. > javac -classpath equinox.jar HelloActivator.java
> jar -cfm HelloWorld.jar HelloWorld.mf HelloActivator.class 6. OSGi console, typeinstall file:HelloWorld.jarFramework is launched.
id State Bundle
0 ACTIVE system.bundle_3.2.1.R32x_v20060919
1 INSTALLED HelloWorld_1.0.0
7.
start 1
============================================================================
Personal collection from http://www.osgi.org/Specifications
============================================================================

