Maven Doc OSGi Quickstart

Working with OSGi Bundles and Maven

This document is a draft. The current version of this document is OSGi Declarative Services Using Maven

This document demonstrates how support for the Open Services Gateway Initiative (OSGi) framework is integrated in NetBeans IDE. In this tutorial you will create a simple OSGi bundles using Maven and deploy the bundle to the Felix OSGi container that is included with the IDE.

After you create the basic OSGi bundle, the tutorial demonstrates how to implement OSGi declarative services in the bundle using the Apache Felix Maven SCR plugin. When you deploy the bundle to GlassFish v3, the Felix container starts the services provided by the bundle.

You will then create and deploy a simple Java EE web client that demonstrates how you can access the services from a servlet. Using an OSGi bundle in an Enterprise Application can provide greater modularity and flexibility with respect to updating individual bundles. The out-of-the-box support for OSGi in GlassFish v3 makes incorporating bundles into your application very easy.

Contents


Requirements for This tutorial

You need the following software:

  • NetBeans IDE 6.9

Prerequisites

This document assumes you have some basic knowledge of, or programming experience with, the following technologies:

  • Java Programming
  • NetBeans IDE

Before starting this tutorial you may want to familiarize yourself with the following documentation.

Creating the OSGi Bundle Project

OSGi Framework

Creating the Bundle

  1. Open New Project window
  2. Choose Maven OSGi Bundle from Maven category. Click Next.
  3. Type MavenHelloService for the Project Name. Click Finish.
  4. Open the project's Properties window and confirm that the Source/Binary Format is set to 1.6 and the Encoding is UTF-8 in the Sources category.

When you click Finish, the IDE automatically adds the org.osgi.core-1.4.0.jar as a dependency. The IDE also generates the felix.xml file in the assembly directory under Other Sources.

If you look at the pom.xml, you can see that the packaging element specifies bundle.

<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>MavenHelloService</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>MavenHelloService OSGi Bundle</name>

You can see that the POM specifies the maven-bundle-plugin for building the bundle.

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <version>2.0.1</version>
                <extensions>true</extensions>
            </plugin>
        </plugins>
    </build>

The IDE also creates a configuration profile named run-on-felix.

Implementing the BundleActivator Interface

In this exercise you will use a wizard to create a Java class named Installer that implements the org.osgi.framework.BundleActivator interface. The bundle activator manages the lifecycle of the bundle and the class is instantiated when the bundle is started.

  1. Right-click project and choose New > Other.
  2. Choose Bundle Activator in the OSGi category. Click Next.
  3. Type Installer for the Class Name and choose com.mycompany.mavenhelloservice as the Package. Click Finish.
  4. Open Installer.java in the editor.
  5. Modify the start() and stop() methods to add the following println messages.
package com.mycompany.mavenhelloservice;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

/**
 *
 * @author nb
 */
public class Installer implements BundleActivator {

    public void start(BundleContext context) throws Exception {
        String userName = context.getProperty("user.name");
        System.out.println("Maven Hello Service: Started OSGi bundle");
        System.out.println("User Name: " + userName);
    }

    public void stop(BundleContext context) throws Exception {
        System.out.println("Maven Hello Service: Stopped OSGi bundle");
    }

}
  1. Save your changes.


You can see that the bundle activator class imports org.osgi.framework.BundleActivator and org.osgi.framework.BundleContext and that by default the class contains two methods: start() and stop(). The OSGi framework invokes the start() and stop() methods to initialize or shutdown the functionality provided by the bundle. When the bundle is started, the OSGi container calls the start() method and registers the component in the service registry. After a bundle is registered, other bundles can use the registry to look up and then use the active services.

If you look at the POM for the project, you can see that the IDE added the <<Bundle-Activator> element to the configuration for the maven-bundle-plugin.

<plugin>
      <groupId>org.apache.felix</groupId>
      <artifactId>maven-bundle-plugin</artifactId>
      <version>2.0.1</version>
      <extensions>true</extensions>
      <configuration>
            <instructions>
                  <Bundle-Activator>com.mycompany.mavenhelloservice.Installer</Bundle-Activator>
            </instructions>
      </configuration>
</plugin>

When you build the bundle, the plugin will generate a Manifest Header in the bundle's manifest file in the JAR and specify the Bundle Activator class. The OSGi runtime looks for the Bundle-Activator header in the manifest file when a bundle is deployed.

Bundle-Activator:com.mycompany.mavenhelloservice.Installer



Building and Checking the Bundle

In this exercise you will build the OSGi bundle. You can then check to see that the bundle is working correctly by running the bundle on the Apache Felix OSGi container that is included with the IDE.

  1. Right-click the project and choose Build.

When you click Build, the IDE builds and installs the snapshot JAR in the local repository

  1. Click Run and you will see the following in the Output window.
Welcome to Felix
================

Maven Hello Service: Started OSGi bundle
User Name: nb

You have now created an OSGi bundle. Right now the bundle does not provide any functionality. In the next section you will add some code so that the bundle provides a service.

Making the OSGi Bundle a Service

This section shows how to use Maven Bundle Plugin and Maven SCR Plugin to create an OSGi bundle with two declarative services.

http://blogs.sun.com/arungupta/entry/totd_124_osgi_declarative_services

Adding Support for SCR Annotations

  1. Right-click the Libraries node and choose Add Dependency.
  2. Type org.apache.felix for the GroupId, org.apache.felix.scr.annotations for the ArtifactId and 1.3.0 for the Version. Click OK.

The IDE adds the dependency under the Libraries node.

Creating the Service API

  1. Right-click Source Packages node of the MavenHelloService project and choose New > Java Interface. Click Next.
  2. Type HelloService as the Class Name
  3. Type com.mycompany.mavenhelloservice.api as the Package. Click Finish.
  4. Modify the interface to add the following code.
public interface HelloService {

    public String sayHello(String name);

}

Creating Implementations of the Service Interface

  1. Right-click Source Packages and choose New > Java Class. Click Next.
  2. Type HelloImpl as the Class Name.
  3. Type com.mycompany.mavenhelloservice.impl as the Package. Click Finish.
  4. Implement the HelloService interface and then implement the abstract methods.
  5. Modify the sayHello method to return the String name.
public String sayHello(String name) {
        return "Hello " + name;
    }
  1. Add the @Service and @Component annotations
package com.mycompany.mavenhelloservice.impl;

import com.mycompany.mavenhelloservice.api.HelloService;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;

/**
 *
 * @author nb
 */
@Component(name="hello-service")
@Service
public class HelloImpl implements HelloService {

    public String sayHello(String name) {
        return "Hello " + name;
    }

}
  1. Fix imports to import org.apache.felix.scr.annotations.Component and org.apache.felix.scr.annotations.Service.
  2. Repeat the steps to create the HowdyImpl class in the same package.
@Component(name="howdy-service")
@Service
public class HowdyImpl implements HelloService {

    @Override
    public String sayHello(String name) {
        return "Howdy " + name;
    }

}

Specify the packages to export

  1. Right-click the project node and choose Properties.
  2. Select the Export Packages category and then select the com.mycompany.mavenhelloservice.api package. Click OK.

The IDE modifies the POM to specify the export package.

<plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <version>2.0.1</version>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Bundle-Activator>com.mycompany.mavenhelloservice.Installer</Bundle-Activator>
                        <Export-Package>com.mycompany.mavenhelloservice.api</Export-Package>
                        <Private-Package>com.mycompany.mavenhelloservice.*</Private-Package>
                    </instructions>
                </configuration>
            </plugin>



Add scr Plugin to the POM

  1. Modify the POM to add maven-scr-plugin as a build plugin.
<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-scr-plugin</artifactId>
    <executions>
	   <execution>
		<id>generate-scr-scrdescriptor</id>
		<goals>
		    <goal>scr</goal>
		</goals>
	   </execution>
    </executions>
</plugin>

Apache Felix Maven SCR Plugin

Building the Bundle

When you build the IDE creates the JAR and installs the JAR in the local repository.

Installing com/mycompany/MavenHelloService/1.0-SNAPSHOT/MavenHelloService-1.0-SNAPSHOT.jar
Writing OBR metadata
------------------------------------------------------------------------
BUILD SUCCESSFUL
------------------------------------------------------------------------
Total time: 5 seconds
Finished at: Fri May 07 16:34:41 CEST 2010
Final Memory: 23M/79M
------------------------------------------------------------------------

Notice that the output displays "Writing OBR metadata". You can expand the JAR created in the target directory to see that MANIFEST.MF was created in the META-INF directory and that serviceComponents.xml was created in the OSGI-INF directory.

If you open MANIFEST.MF you can see the following:

Manifest-Version: 1.0
Service-Component: OSGI-INF/serviceComponents.xml
Export-Package: com.mycompany.mavenhelloservice.api
Built-By: nb
Tool: Bnd-0.0.357
Bundle-Name: MavenHelloService OSGi Bundle
Created-By: Apache Maven Bundle Plugin
Build-Jdk: 1.6.0_17
Bundle-Version: 1.0.0.SNAPSHOT
Bnd-LastModified: 1273242881061
Bundle-ManifestVersion: 2
Bundle-Activator: com.mycompany.mavenhelloservice.Installer
Bundle-SymbolicName: com.mycompany.MavenHelloService
Import-Package: com.mycompany.mavenhelloservice.api,org.osgi.framewor
 k;version="1.5"

The maven-bundle-plugin handles the generation of the MANIFEST.MF file. You can see that plugin generated manifest headers to declare the Export Packages and the Bundle Activator class as specified in the POM. The OSGi container reads the Export-Package manifest header to determine the classes in the bundle that can be accessed from outside the bundle. In this example, the classes in the com.mycompany.mavenhelloservice.api package are exposed but the implementation classes in com.mycompany.mavenhelloservice.impl are not exposed.

The maven-scr-plugin handles the generation of the serviceComponents.xml descriptor file where the services are declared. If you open serviceComponents.xml, you can see that file declares the implementation classes of each of the named services.

Deploying the OSGi Bundle to GlassFish v3

  1. Start GlassFish.
  2. Open a command line terminal.
  3. From the command line, navigate to the target directory that contains MavenHelloService-1.0-SNAPSHOT.jar.
  4. Type the following in the terminal.
<glassfish-install>/glassfish/bin/asadmin deploy --type osgi MavenHelloService-1.0-SNAPSHOT.jar

Where <glassfish-install> is the location of your GlassFish installation. You will see something similar to the following in the terminal window:

Authentication failed with password from login store: /Users/nb/.asadminpass
Enter admin password for user "admin">
  1. Hit the Enter key (the default admin password is "null")

When you hit the Enter key you will see the following in the terminal window.

Application deployed successfully with name MavenHelloService-1.0-SNAPSHOT.

Command deploy executed successfully.

You will see something similar to the following in the Output window of the IDE.

INFO: Maven Hello Service: Started OSGi bundle
INFO: User Name: nb
INFO: MavenHelloService-1.0-SNAPSHOT was successfully deployed in 372 milliseconds.

If you started GlassFish using the terminal, you can see the following output in the server log

[#|2010-04-30T18:00:53.933+0200|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=24;_ThreadName=http-thread-pool-4848-(2);|Maven Hello Service: Started OSGi bundle|#]

[#|2010-04-30T18:00:54.038+0200|INFO|glassfishv3.0|javax.enterprise.system.tools.admin.org.glassfish.deployment.admin|_ThreadID=24;_ThreadName=http-thread-pool-4848-(2);|MavenHelloService-1.0-SNAPSHOT was successfully deployed in 614 milliseconds.|#]

The message"Maven Hello Service: Started OSGi bundle" shows that the Installer class in the OSGi bundle was loaded on deploy.

In the terminal you can view the deployed applications and bundles by typing the following:

<glassfish-install>/glassfish/bin/asadmin list-applications                                    
Authentication failed with password from login store: /Users/nb/.asadminpass
Enter admin password for user "admin"> 
MavenHelloService-1.0-SNAPSHOT 

Creating the Client Application

This section demonstrates how to create a Java EE web client that accesses the services. You will inject the declared services and invoke them.


Creating the Web Application

  1. Click New Project and choose Maven Web Application from the Maven category.
  2. Type MavenHelloWebClient for the Project Name. Click Finish.
  3. Open project's Properties window and set Server to GlassFish v3 in the Run category.
  4. Specify /HelloClient as the Relative URL. Click OK.
  5. Right-click the project node and choose New > Servlet.
  6. Type HelloClient for the Class Name and select the com.mycompany.mavenhellowebclient package from the dropdown list. Click Finish.
  7. Right-click the Libraries node and choose Add Dependency.
  8. Type helloservice in the Query text field to search the local repository.
  9. Select the MavenHelloService Snapshot bundle in the group com.mycompany. Click OK. Alternatively, if the bundle project is open in the IDE you can click the Open Projects tab in the Add Dependency dialog.
  10. Open the POM and and add a scope element and specify the scope as provided.
<dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>MavenHelloService</artifactId>
      <version>${project.version}</version>
      <scope>provided</scope>
</dependency>

You edit the POM to specify the scope as provided because in the previous section you manually deployed the bundle to the server .

Injecting the Services

  1. Inject the service resources using annotations.
@WebServlet(name="HelloClient", urlPatterns={"/HelloClient"})
public class HelloClient extends HttpServlet {

   @Resource(mappedName="hello-service")
   HelloService helloService;
   
   @Resource(mappedName="howdy-service")
   HelloService howdyService;
  1. Modify the processRequest method to add println to call the sayHello method in the services
out.println("<h1>Servlet HelloClient at " + request.getContextPath () + "</h1>");

out.println(helloService.sayHello("Duke"));
out.println("<br/>");
out.println(howdyService.sayHello("Duke"));

out.println("</body>");
out.println("</html>");

Building and Running the Application

  1. Right-click the web application project and choose Build.

If you look at the project in the Files window, you can see that the target directory contains the MavenHelloWebClient.war archive. If you expand the WAR, you can see that the archive does not contain the MavenHelloService JAR.

  1. Right-click the web application project and choose Run.

Undeploying the OSGI Bundle From GlassFish

To undeploy the bundle, type the following in the terminal:

<glassfish-install>/glassfish/bin/asadmin undeploy MavenHelloService-1.0-SNAPSHOT 
Authentication failed with password from login store: /Users/nb/.asadminpass
Enter admin password for user "admin"> 

Command undeploy executed successfully.

If you look at the Output window you will see the following message.

INFO: My Maven OSGi Bundle: Stopped Maven bundle

Deploying Bundles Using Autostart in GlassFish

To copy the bundle into the modules/autostart directory.

  1. Navigate to the glassfish install directory.
  2. Copy the JAR from the MavenHelloService target directory to the modules/autostart directory in GlassFish
cp /Users/nb/Documents/nbtemp-project/69-beta/MyMavenOSGiBundle/target/MyMavenOSGiBundle-1.0-SNAPSHOT.jar modules/autostart

You will see Any OSGi bundles that are copied to the autostart directory are automatically loaded.

The Output window displays the following:

INFO: Installed /Applications/NetBeans/glassfish-3.0.1-b14/glassfish/modules/autostart/MyMavenOSGiBundle-1.0-SNAPSHOT.jar
INFO: My Maven OSGi Bundle: Started Maven bundle
INFO: Started bundle: file:/Applications/NetBeans/glassfish-3.0.1-b14/glassfish/modules/autostart/MyMavenOSGiBundle-1.0-SNAPSHOT.jar

You can see that the JAR was installed in the autostart directory.

Use the rm command to remove the JAR from the directory.

rm modules/autostart/MavenHelloService-1.0-SNAPSHOT.jar

Reference

Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo