Developing OSGi applications with Java EE 6 - Web Application Bundles in IBM WebSphere Application Server V8

Z Jacek Laskowski - Wiki Amatora Programowania
Skocz do: nawigacji, wyszukiwania

Web Application Bundle (WAB) "is a OSGi bundle that performs the same role as the WAR in Java EE […] and can leverage the full set of features of the OSGi Service Platform." (quoting the specification, page 417). It's described in Chapter 128 Web Applications Specification of the OSGi Service Platform Release 4 Version 4.2 Enterprise Specification.

The article is about HOW to achieve a specific goal - to develop a OSGi application with Java EE 6 - and WHAT to use to have it done - IBM WebSphere Application Server V8 (BASE 8.0.0.3) and IBM Rational Application Developer V8 (Version: 8.0.4.1, Build ID: RADO8041-I20120502_2148), with no WHY you'd ever want to go this way. I've been mostly concerned with HOW and WHAT until I realized that WHY is often more important. Not this time, tough. It should be a topic of the next installments. Should you find it out sooner, grab the specifications where the answers are easily to be found.

The article assumes some knowledge about Enterprise OSGi and Java EE 6, and their respective runtime environments - a OSGi platform for the former and a Java EE 6 application server for the latter. Send your questions to jacek@japila.pl, should the article or a part of it be improved or explained differently - it usually boils down to relying on your experience so let me know how advanced you are with OSGi and/or Java EE 6.

Valuable articles that I have thoroughly used for the purpose of correctly shaping the article:

I've also been presenting Enterprise OSGi with Apache Aries in the article Enterprise OSGi runtime setup with Apache Aries Blueprint.

Spis treści

Introduction

An OSGi bundle, which can be any JAR file, e.g. WAR file or EJB jar file, contains a bundle manifest file META-INF/MANIFEST.MF with OSGi-specific headers - the metadata. Annotations in a source code, headers in MANIFEST.MF or entries in a deployment descriptor are a means of enabling platform-specific, in this case the OSGi Framework's, features.

There're mandatory headers described by the respective specifications - the JAR File specification, and the OSGi 4.2 Core and Enterprise specifications. Since they're declarative they're processed by a runtime environment that acts upon them accordingly, if needed. It means that the metadata is effective if a runtime decides so - we, developers, merely ask for services offered by the runtime platform and should take into account their unavailability.

There're many specifications that constitute what one could call the OSGi platform. There are so many specifications that the term "the OSGi platform" is hardly to be understood correctly the first time you hear it. In this article, the OSGi platform means a runtime environment that supports the following specifications:

Developing Web Application Bundle

Hello bundle and Hello interface

The contract between modules (OSGi bundles) is described by the following interface - pl.japila.osgi.hello.Hello. It's in a OSGi bundle project - Hello.

package pl.japila.osgi.hello;
 
public interface Hello {
    String hello();
}


The reason to make it a separate OSGi bundle is to provide (export) the interface and let implementers (other OSGi bundles) to import it so there's a clear distinction between contract and implementation providers.

With the help of Rational Application Developer, it merely boils down to adding the necessary headers in the MANIFEST.MF with the Runtime tab in the Plug-in Manifest Editor.

Entosgi-javaee6-was8-rad8-plugin-manifest-editor-runtime-tab.png

It should look as follows:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Hello
Bundle-SymbolicName: Hello
Bundle-Version: 1.0.0
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Export-Package: pl.japila.osgi.hello

Developing a OSGi service - HelloService

A possible implementation of the Hello contract (interface) is a OSGi bundle - HelloService. It's another OSGi Bundle project.

Import the package pl.japila.osgi.hello so the interface pl.japila.osgi.hello.Hello is accessible (visible) for the bundle. Rational Application Developer made it as simple as using the Dependencies tab of the Plug-in Manifest Editor.

Entosgi-javaee6-was8-rad8-plugin-manifest-editor-dependencies-tab.png

With the import, creating the implementation became easy - the interface's already available for the New Java Class wizard.

package pl.japila.osgi.hello.service;
 
import pl.japila.osgi.hello.Hello;
 
public class HelloService implements Hello {
 
    @Override
    public String hello() {
        return "Hello from " + this;
    }
 
}

The bundle project uses the OSGi Blueprint Container so exposing a OSGi service is as simple as to declaratively specifing our intent in the Blueprint deployment descriptor - OSGI-INF/blueprint/blueprint.xml (use New > Blueprint File wizard of Rational Application Developer).

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  <bean id="HelloServiceBean" class="pl.japila.osgi.hello.service.HelloService" />
  <service id="HelloService" ref="HelloServiceBean" interface="pl.japila.osgi.hello.Hello" />
</blueprint>

Right after you've defined the service, Rational Application Developer creates the node Services to easily navigate between the services.

Entosgi-javaee6-was8-rad8-services-node.png

Ultimately, the META-INF/MANIFEST.MF should be as follows:

Manifest-Version: 1.0
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-Name: HelloService
Bundle-Blueprint: OSGI-INF/blueprint/*.xml
Bundle-SymbolicName: HelloService
Bundle-Version: 1.0.0
Import-Package: pl.japila.osgi.hello
Bundle-ManifestVersion: 2

Web Application Bundle - HelloWAB

HelloWAB is a OSGi bundle that represents a web application. It depends on the bundle with the interface (the bundle Hello) and declaratively looks the service HelloService (from the bundle HelloService) up in the OSGi Service Registry. The task is handed over to the OSGi Blueprint Container (one could draw a logical conclusion that it's a Dependency Injection framework like Guice or Spring Framework and would not be mistaken at all).

The WAB bundle uses the Java Servlet 3.0 specification of Java EE 6 so no deployment descriptor is necessary. While the OSGi bundle project is created it's necessary to add Web support in Rational Application Developer.

Entosgi-javaee6-was8-rad8-hellowab-project-wizard.png

The WAB bundle belongs to the OSGi Application Project HelloWAB.app which is created while the WAB is.

Before you create the servlet class you'll have to import the interface pl.japila.osgi.hello.Hello from the bundle Hello. The META-INF/MANIFEST.MF file should look as follows:

Manifest-Version: 1.0
Bundle-ClassPath: WEB-INF/classes
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-Name: HelloWAB
Bundle-Blueprint: OSGI-INF/blueprint/*.xml
Bundle-SymbolicName: HelloWAB
Web-ContextPath: /HelloWAB
Bundle-Version: 1.0.0
Import-Package: javax.el;version="2.0";resolution:=optional,javax.serv
 let;version="2.5",javax.servlet.annotation;resolution:=optional,javax
 .servlet.http;version="2.5",javax.servlet.jsp;version="2.0",javax.ser
 vlet.jsp.el;version="2.0",javax.servlet.jsp.tagext;version="2.0",pl.j
 apila.osgi.hello
Bundle-ManifestVersion: 2

The servlet uses dependency injection with the @Resource annotation to access the service offered by the bundle HelloService which in turn is made accessible by the OSGi Blueprint Container with the following configuration file - OSGI-INF/blueprint/blueprint.xml:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  <reference id="helloRef" interface="pl.japila.osgi.hello.Hello" />
</blueprint>

The configuration files are to specify your intent to use the package - pl.japila.osgi.hello - with the interface - pl.japila.osgi.hello.Hello - and the service - helloRef (the name is arbitrary and its interface is what points to the appropriate service in the OSGi Service Registry). You are now ready to develop the servlet - HelloServlet.

package pl.japila.osgi.hello.servlet;
 
import java.io.IOException;
 
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import pl.japila.osgi.hello.Hello;
 
@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
 
    @Resource(lookup="blueprint:comp/helloRef")
    Hello helloRef;
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String htmlTemplate = "<html><body><h2>Hello from Web Application Bundle (WAB): %s</h2></body></html>";
        response.getWriter().printf(htmlTemplate, helloRef.hello());
    }
 
}

Note the package which is different than the other packages in the pl.japila.osgi.hello common package. It's how OSGi works where interface providers are supposed to expose their services under a package and the implementers use another for their services.

It might be necessary to click Update the classpath settings to have the lookup attribute of the @Resource annotation accepted by the IDE.

Entosgi-javaee6-was8-rad8-hellowab-update-the-classpath-settings.png

As the final step in the development process you should add the bundles Hello and HelloService to the OSGi Application Project HelloWAB.app.

Entosgi-javaee6-was8-rad8-osgi-application-project-contained-bundles.png

Final (manual) testing

Time to run the web application bundle. It's a web application after all so using Run As > Run on Server with the servlet selected should be all that's needed.

Entosgi-javaee6-was8-rad8-hello-from-wab-in-browser.png

It works fine as the web page shows - the first "Hello from" message comes from the servlet whereas the latter is from the service HelloService. They're all connected and play well together.

Although the application works fine, WAS V8 emits FFDC Incident: javax.naming.ConfigurationException: NamingManager.getURLContext cannot find the factory for this scheme: blueprint. Disregard it.

Should you have questions on the topic of developing OSGi applications, Java EE 6 and IBM WebSphere Application Server V8, let me know at jacek@japila.pl. Thanks.

Osobiste
Przestrzenie nazw

Warianty
Działania
Nawigacja
Narzędzia