Using the OSGi Http Service on IBM WebSphere Application Server

14 05 2011

Since version 7 (Feature Pack) and version 8 (integrated), IBM WebSphere Application Server (WAS) provides the OSGi application model to enterprise application developers. It allows to develop OSGi bundles and to deploy applications as enterprise bundle archives (EBA). As WebSphere uses Equinox as the OSGi implementation, it should be possible to install and run the Rich Ajax Platform on the server. The first step is to evaluate how to install the OSGi Http Service into WebSphere’s web container and how to use it.

OSGi Feature of WebSphere Application Server

First, let me say some words about the OSGi feature in general. You can find a very detailed introduction at developerWorks. Developers that are familiar with OSGi core concepts should notice the following specifics:

  • WAS7 provides the org.eclipse.osgi bundle version 3.5.2 to OSGi applications, WAS8 provides version 3.6.1.
  • Although Equinox is the OSGi runtime, it is not intended to support features like the Extension Point Registry or the Declarative Services Specification.
  • WAS implements the OSGi Web Application Specification. Enterprise Applications are now deployed as Enterprise Bundle Archives (EBAs instead of EARs), Web modules are packaged as Web Application Bundles (WABs instead of WARs). Non-OSGi WARs can be part of an EBA and are automatically wrapped into a WAB.
  • WAS integrates Apache Aries technologies. OSGi Services can be declared by using the OSGi BluePrint Container specification. OSGi services are published to the JNDI and vice versa to connect both “worlds”.
  • Because one very important requirement to an application server is the isolation of enterprise applications, OSGi applications are launched within their own framework. Nevertheless, it is possible to resolve bundles from a bundle repository, which are then shared between multiple applications. See the following picture from the WAS7 Infocenter that explains these facts:

    Isolated Frameworks

    Isolated Frameworks

  • It is possible to place bundles within a composite bundle, which is then started within its own framework too. An EBA can contain single and composite bundles.
  • Bundle dependencies should be declared using the Import-Package header. On WAS, the Require-Bundle header is only allowed between bundles within the EBA. It is not possible to declare this header within a bundle of the EBA to a bundle resolved from the shared repository. (The EBA manifest names a list of bundles and their versions that can be resolved from the shared repository.)
  • I use IBM Rational Application Developer V8 with PDE to create OSGi applications for WebSphere. It is also possible to use Eclipse PDE and install the IBM Rational Development Tools for OSGi Applications into the IDE.

OSGi Http Service Implementation of Equinox

The Equinox Server-Side Project provides an implementation of the OSGi Http Service Specification. The HttpServiceServlet registers the service at the platform and delegates requests from the webcontainer to the Http Service. In contrast to previous versions of WAS, we do not need the BridgeServlet anymore, that launches an external OSGi framework and does not allow sharing resources between multiple applications.

So we need the org.eclipse.osgi.services bundle (that defines the HttpService interface) and the org.eclipse.equinox.http.servlet bundle (containing the HttpServiceServlet). They are configured to be part of the PDE target platform. To make them available on WAS for testing your applications, you can install them into the internal bundle repository or refer to an external bundle repository that can be created using the OSGi BIndex Tool.

Creating the WAB

We need to create a WAB that delegates incoming requests from the web container to the OSGi platform. After creating the OSGi Bundle Project, do the following steps:

  • Extend the Import-Package header of the manifest to list the “org.eclipse.equinox.http.servlet” package.
  • Add a servlet to the web.xml with the servlet class “org.eclipse.equinox.http.servlet.HttpServiceServlet” and the URL mapping “/*”. Configure the servlet to be initialized immediately, if you want the HttpService implementation to be published to the OSGi platform during application startup, which can be a long operation because this can invoke the registration of servlets to the HttpService by other bundles.

That’s all! You can download the example WAB.

Using the OSGi Http Service

You can bind the Http Service programmatically using OSGi Servicetracker, or you can use Blueprint. See the BluePrint file example below:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
	<bean id="ServletRegistry"
		class="de.ars.ws.http.example.internal.ServletRegistry" />
	<reference interface="org.osgi.service.http.HttpService"
		activation="eager" availability="optional">
		<reference-listener bind-method="bind" unbind-method="unbind" ref="ServletRegistry"/>
	</reference>
</blueprint>

And the bean that registers the servlet to the Http Service:

package de.ars.ws.http.example.internal;

import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;

import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;

public class ServletRegistry {

	private static final Logger logger = Logger.getLogger(ServletRegistry.class
			.getName());

	public void bind(HttpService service) {
		if (null != service) {
			try {
				logger.log(Level.INFO, "HTTP Service bound: " + service);
				service.registerServlet("/example/servlet", new ExampleServlet(service),
						null, null);
				service.registerResources("/example/resources", "/resources", null);
			} catch (ServletException e) {
				logger.log(Level.WARNING,
						"Unable to register example servlet!", e);
			} catch (NamespaceException e) {
				logger.log(Level.WARNING,
						"Unable to register example servlet!", e);
			}
		}
	}

	public void unbind(HttpService service) {
		if (null != service) {
			logger.log(Level.INFO, "HTTP Service unbound: " + service);
			service.unregister("/example/servlet");
			service.unregister("/example/resources");
		}
	}

}

You can download the example bundle.

Putting it all together – the EBA

Last but not least, let’s create an EBA with a single META-INF/APPLICATION.MF file with the following content:

Application-Name: Embedded OSGi Http Service
Application-SymbolicName: org.eclipse.equinox.http.embedded
Application-ManifestVersion: 1.0
Application-Version: 1.0.0.qualifier
Application-Content: org.eclipse.equinox.http.embedded.web;version="1.0.0",
  org.eclipse.equinox.http.servlet;version=1.0.200,
  org.eclipse.osgi.services;version=3.2.0,
  de.ars.ws.http.example;version=1.0.0
Manifest-Version: 1.0

This is the isolated version of the Http Service that is created for each application framework. You have to include the Equinox bundles and the WAB for each EBA (take care about the context root of the WAB to be unique) together with your application bundles.

Another possibility would be to share the Http Service between all applications. The EBA manifest would then look like this:

Application-Name: Embedded OSGi Http Service
Application-SymbolicName: org.eclipse.equinox.http.embedded
Application-ManifestVersion: 1.0
Application-Version: 1.0.0.qualifier
Application-Content: org.eclipse.equinox.http.embedded.web;version="1.0.0"
Manifest-Version: 1.0
Use-Bundle: org.eclipse.equinox.http.servlet;version=1.0.200,
  org.eclipse.osgi.services;version=3.2.0

You can download the EBA.

The difference is that the HttpServiceServlet is resolved from the bundle repository, which causes the HttpService to be published to the Shared Bundle Space. Your application bundles can then be packaged into a separate EBA.

Conclusion

As you can see, it is possible to use the OSGi Http Service both within isolated applications and within a shared space where the Http Service acts as a singleton like the web container does (with the exception that the Http Service does not support context roots). The next step is to test how to deploy the Rich Ajax Platform on WebSphere Application Server.

Advertisements

Actions

Information

One response

28 06 2011
Some thoughts about OSGi and Java EE 6 « Ralf Zahn's blog

[…] Servlets, filters and listeners can only be registered during application startup within a ServletContextListener (and cannot be removed) – so in comparison to the lifecycle of OSGi bundles, it does not provide such a dynamic behaviour. If you want to register and remove servlets at runtime without restarting the web application, you should use the OSGi HttpService that only provides a Servlet 2.x API. (see my notes on “Using the OSGi Http Service on IBM WebSphere Application Server”) […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: