Eclipse has been enormously popular as a tooling platform. With the use of Eclipse as a Rich Client Platform (RCP), Eclipse made a step towards being a runtime platform. Now, with the emergence of Eclipse on the server, Eclipse clearly has leapt into the runtime world. So what makes Eclipse capable of adapting to these different environments – what makes Eclipse tick?
At its core, Eclipse has a modular Java runtime called Equinox ( http://eclipse.org/equinox). Equinox in turn is an implementation of the OSGi Alliance’s Service Platform R4 specification ( http://osgi.org). In fact, it is the reference implementation for the framework portion of that specification. At the heart of the OSGi specification is the notion of bundles.
Bundles are used to capture modularity for Java. A bundle is just a standard Java JAR whose manifest contains extra markup identifying the bundle and laying out its dependencies. As such, each bundle is fully self-describing. Below is an example.
Bundle-Name: Eclipse Extension Registry
The first section identifies the bundle giving it a symbolic name, version and various human-readable descriptive values. The symbolic name and version go together to uniquely identify the bundle.
The classpath entry details where, inside the bundle itself, the bundle’s code can be found. Specifying ‘.’ is the default and indicates that the bundle’s code is at the root of the bundle JAR itself.
The OSGi architecture is highly dynamic. Bundles can come and go at any time in a session. The bundle activator allows bundles to hook the start() and stop() lifecycle events and thus perform initialization and cleanup as needed.
Bundles that provide function to the rest of the system must expose the API for that function by exporting the API package. Exporting a package allows other bundles to reference the classes in the package. Notice that bundles can hide packages simply by not exporting them.
Finally, bundles can express their dependence on code supplied by other bundles. This is done either indirectly using Import-Package statements or directly using the Require-Bundle header. Importing packages allows bundles to be bound (or wired as we say) to arbitrary providers of the needed packages. Conversely, directly requiring bundles allows for implementation-specific dependencies. In both cases the prerequisite can be qualified by version ranges and other markup to refine the dependency. Note also that bundles can specify dependencies on the underlying JRE used to run them. The bundle in this example can run on J2ME Foundation 1.0 or higher or J2SE 1.3 or higher.
Given a set of bundles, Equinox resolves the dependencies and wires together the bundles. Bundles missing prerequisites are not resolved and are not eligible to be run. In the end each bundle has a dynamically computed and unique classpath that tells it exactly where to get its prerequisite code. Typically the standard Java application classpath is ignored and everything is computed from the expressed dependencies. Gone are the days of fighting with the global classpath.
How do I program and run an Equinox based system?
Developing bundles with Eclipse is the same as developing an Eclipse plug-in. In fact, there is no difference between bundles and plug-ins. While running the Eclipse SDK, simply use the New > Project > Plug-in Project wizard, enter a project name and select “OSGi framework” as the intended target platform (at the bottom of the wizard). Click Next until you get to the last page. Here you can choose from a set of templates. For your first bundle, choose the Hello OSGi Bundle template. Click Finish and you have a new bundle project.
To run the bundle, right click on the bundle project and choose Run As… > Equinox. You should see a console appear with an “osgi>” prompt and the message “Hello World!!”. That message was printed by your new bundle. At the osgi> prompt you can type various commands. For example, you can stop your bundle by typing “stop <your bundle symbolic name>”. Note that by default the project name is used as the bundle’s symbolic name. You should see the “Goodbye World!!” message. You can of course restart the bundle using “start <bundle name>”. Go take a look at the code the wizard generated and you will see an Activator class with start() and stop() methods that print the corresponding messages. There are many more details and capabilities but this should get you running.
What did I just do?
An Equinox-based system consists of; Equinox itself, a set of bundles, and a configuration. The configuration is a list of bundles to run. This list is drawn from the pool of bundles available on the user’s machine. In the example above, the tooling created a configuration that included your bundle and all the bundles the system knew about and launched it. Note that in the simple workflow used here there are many extra bundles added to the configuration. For this example, you really only need your bundle and the org.eclipse.osgi bundle in the configuration.
When Equinox is launched, it installs all of the bundles listed in the configuration, resolves them and starts any bundles listed as needed to be started. Since your bundle was installed and resolved and is listed (by default) as needing to be started, it was started and the Activator.start() method called and message printed.
Equinox and OSGi in the larger context
Both Equinox and OSGi are seeing a surge in interest from a wide range of communities from embedded, the traditional domain of OSGi, to desktop tools and applications to mobile devices and servers. The server side work is of particular interest.
The Equinox project has a server side effort that seeks to integrate the dynamic module capabilities of OSGi into standard application server scenarios (see http://eclipse.org/equinox/server). There are two main approaches; embedding Equinox in the servlet container or embedding the servlet container in Equinox. To a large extent the choice made here does not impact your server application or functionality. The choice is more a function of the infrastructure needs of your environment. For example, are there other standard web applications running, are you using clustering or other infrastructure, …
The following three diagrams illustrate the traditional
web application server setup and contrasts it with the Equinox in Container approach and the Container in Equinox approach. Equinox is embedded in an existing servlet container as shown in Figure 2 by installing a very thin web application. This application contains a Bridge Servlet that launches an Equinox instance inside the application and then forwards all requests to the Equinox-based application (servlets, JSPs, …) via a very lightweight HTTP service.
In Figure 3, the approach is turned around and Equinox runs an application container (e.g., embedded Jetty) and provides some glue code that wires Equinox-based applications into the application container.
Figure 1: Traditional web application server structure
Figure 2: Embedding Equinox in an existing application container
Figure 3: Embedding an application container in Equinox
In both Equinox-based scenarios, writing your application is the same. You create a bundle project using the Eclipse plug-in development environment (PDE) and add the static content, servlets and JSPs as needed. Then add traditional Eclipse extension markup to surface your content in the user’s URL space. The snippet below shows an example.
<plugin> <extension point="org.eclipse.equinox.http.registry.resources"> <resource alias="/files" base-name="/web_files"/> </extension> <extension point="org.eclipse.equinox.http.registry.servlets"> <servlet alias="/test" class="com.example.servlet.MyServlet"/> </extension> </plugin>
The first extension places the content of the “web_files” directory of the bundle at /files in the user’s URL space (e.g., http://localhost/files/...). The second extension places MyServlet at /test in the URL space (e.g., http://localhost/test).
The easiest way of running you application is to launch directly from Eclipse using the Container in Equinox approach. This is the same process you used with the example bundle above and allows you to run without setting up an application server or deploying the code. As a result it is much faster and easier to test and debug. For complete instructions, see the Server-side QuickStart Guide at http://eclipse.org/equinox/documents/http_quickstart.php.
Since your function is defined in bundles and running in Equinox, everything is dynamic and extensible. You can add, remove and update dynamically without taking down the server, the URL space is updated as you modify the function available and your business logic can be reused on the server, the desktop and in mobile clients.
What’s next for Equinox and OSGi?
Equinox is a mature codebase with millions of users – after all, every Eclipse user is running Equinox. Nonetheless the Equinox team is continually refining the implementation and adding support for new use cases.
OSGi on the server and in the enterprise is becoming increasingly interesting. The next version of IBM’s flagship WebSphere Application Server is actually based on Equinox under the covers. The OSGi Alliance is responding to the increased interest by creating an Enterprise Expert Group (EEP) to look at issues such as distributed computing, multi-language support and enterprise wide provisioning.
The general Java community has recognized that it too can benefit from the modularity that OSGi brings. While JSR 277 seeks to add a level of modularity in the Java 7 timeframe, JSRs 232 and 291 provide OSGi-based dynamic Java modularity to Java today. These two JSRs enable OSGi-based modularity at all levels of Java from J2ME CDC/Foundation 1.0 to J2SE 1.3 and up.
The explosion in interest in Equinox and OSGi should not have surprised us but it did. Many people in the Java community are struggling with system complexity and management issues. With Eclipse, Equinox and OSGi you too can enjoy the benefits of modular, componentized Java wherever you compute.
Jeff McAffer leads the Eclipse RCP and Runtime teams and is one of the Eclipse Platform's original architects and committers. Prior to his work at IBM's Ottawa Software Lab, he was a developer at Object Technology International focusing on areas such as distributed/parallel OO computing, expert systems, and meta-level architectures. Jeff holds a Ph.D. from the University of Tokyo.
Simon Kaegi works at Cognos as a developer looking at the run-time provisioning of enterprise software. A committer on the Eclipse Equinox project his current focus is on enabling the many use-cases for OSGi in server-side environments.