September 30, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Create Reusable OSGi Components for Eclipse Equinox

  • March 17, 2010
  • By Manish Malhotra, Prasad Siva Sai Choutupalli
  • Send Email »
  • More Articles »

Largely because it allows multiple components to interact efficiently and securely in a Java Virtual Machine (JVM), the Open Service Gateway Initiative (OSGi) specification claims the title: "The Dynamic Module System for Java." With its rich security model, OSGi allows each component to run in its own secured environment. However, by setting the proper permissions, you can enable OSGi components to reuse other components, a capability that differentiates OSGi from other containers. This is what makes the OSGi framework lightweight and reusable.

The core of OSGi is a framework that defines:

  • An application lifecycle management model
  • A service registry
  • An execution environment
  • An atomic part of the application that is composed of modules or components

These definitions standardize how you define modules or components and how you manage the lifecycle of these components. The beauty of the OSGi runtime is that you can install, update, or remove components on the fly—without interrupting existing operations. This feature makes OSGi ideal for domains where component/module provisioning must occur without interruptions to the existing operations (e.g., grid and cloud computing). OSGi also can expose Plain Old Java Object (POJO) services at each component level, a service-oriented way for components to communicate with each other.

In this article, we walk through the development of a thick client: a user login component that authenticates users before granting access to back-end resources. Along the way, we explore reusability and size reduction of individual bundles, as well as features such as OSGi services and Eclipse plug-in extension points.

Developing a Reusable User Login Solution for OSGi

The architecture for the user login solution is composed of two layers, each containing a bundle/component. One bundle comprises the UI part (UserLoginUI) and the other provides the required services (UserLoginServices) for the solution. The UserLoginUI bundle helps to collect the credentials from the user, and the UserLoginServices bundle validates and saves the credentials for further use.

The rest of the article provides instructions for developing this solution in Eclipse.

Create a New Service

First, you need to create a new service:

  1. Click on the File tab, select the New option, and then select the Other... option (see Figure 1).

  2. Select the Plug-in Development wizard and then Plug-in Project (see Figure 2).

  3. To create a service, you need to change the target platform. The default selection is an Eclipse version. You need to change that to an OSGI framework, select Equinox from the dropdown list, and then click Next (see Figure 3).

  4. Click the Finish button, and you have created a bundle having a blank service (see Figure 4).

Register Services

The User Login solution has two services:

  • IValidateService: This service validates user credentials against a credential store. It can have multiple implementations, depending on the type of credential storage.
  • IContextDataService: This service hides the implementation classes from the consumer of the services, leaving it to the bundle's discretion which implementation is made available to the consumer.

Because OSGi allows updates to the bundles without interrupting dependent bundles, you can update these services in a highly dynamic manner without effecting the service consumer.

Before using a service, you first need to register it. Because your solution has two services, you need to register both. Here is a code snippet written in the Activator class to register them:

IContextDataService dataService = new UserSessionService(); 
IValidateService validateService = new ValidateService(); 
// register the service
context.registerService(IContextDataService.class.getName(), dataService, new Hashtable());
context.registerService(IValidateService.class.getName(), validateService, new Hashtable());


The context object is the shared object across all the bundles within a single Equinox runtime. The context object here refers to the UserLoginServices bundle, which registers the two services with the Eclipse Equinox runtime. Because the OSGi framework allows bundles to expose services for other bundles to use, you expose the packages that implement the functionality of the above-mentioned services.

Here is a snapshot of the MANIFEST.MF of UserLoginServices bundle:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: CommonServices Plug-in
Bundle-SymbolicName: CommonServices
Bundle-Version: 1.0.0
Bundle-Activator: com.infy.setl.common.services.activator.Activator
Export-Package: com.infy.setl.common.services.genericserviceint,
 com.infy.setl.common.services.usermode;uses:="com.infy.setl.common.services.usermodelint",
 com.infy.setl.common.services.usermodelint,
 com.infy.setl.common.services.userserviceint;uses:="com.infy.setl.common.services.genericserviceint",
 com.infy.setl.common.services.validateservice,
 com.infy.setl.common.services.validateserviceint
Import-Package: org.osgi.framework;version="1.3.0",
 org.osgi.util.tracker;version="1.3.3"
Created-By: 1.5.0_06-b05 (Sun Microsystems Inc.)
Ant-Version: Apache Ant 1.7.1
Eclipse-LazyStart: true
Require-Bundle: org.eclipse.core.runtime


The packages exposed are the ones that contain POJO services. Another developer can import these packages individually or import the whole bundle in his or her application to make use of the services. Your solution itself uses the services of this bundle through UserLoginUI to validate and cache the credentials.

UserLoginUI

Here are the steps for creating a new UI plug-in.

  1. Click on File tab, select the New option, and then select the Other... option (see Figure 5).

  2. Select the Plug-in Development wizard and then Plug-in Project (see Figure 6).

  3. Use the default selection and click Next (see Figure 7).

  4. Click the Finish button and you have created a blank new plug-in (see Figure 8).

      Manifest and Activation of UI Bundle

      To import service bundle classes for use in the UserLoginUI bundle, specify the following in Manifest.MF:

      Manifest-Version: 1.0
      Bundle-ManifestVersion: 2
      Bundle-Name: CommonLoginAuth Plug-in
      Bundle-SymbolicName: CommonLoginAuth;singleton:=true
      Bundle-Version: 1.0.0
      Bundle-Activator: com.infy.setl.common.login.activator.Activator
      Require-Bundle: org.eclipse.ui,
       org.eclipse.core.runtime,
       org.eclipse.swt,
       org.eclipse.ui.workbench,
       org.eclipse.jface,
       CommonServices;bundle-version="1.0.0"
      Eclipse-LazyStart: true
      Export-Package: com.infy.setl.common.login.ui
      Bundle-ClassPath: .,
       org.eclipse.jface_3.3.2.M20080207-0800.jar
      Import-Package: com.infy.setl.common.services.usermode,
       com.infy.setl.common.services.usermodelint,
       com.infy.setl.common.services.userserviceint,
       com.infy.setl.common.services.validateservice,
       com.infy.setl.common.services.validateserviceint


      You export the IValidateService and IContextDataService classes to access the services.

      Next, you install and use the service imported above if the OSGI container has not done it for you (i.e., you start the services programmatically through code). You can do this by adding the code below in the Activator class or by designing a separate class. You need to have the service bundle started because the current bundle depends on the service bundle for validation and caching services.

      if(bundle!=null){
                  if(bundle.getState()==Bundle.ACTIVE){
                     context = bundle.getBundleContext();    
                     if(context!=null){
                        userServiceTracker = new ServiceTracker(context,IContextDataService.class.getName(), null);   
                        if(userServiceTracker!=null){
                           userServiceTracker.open();
                           // grab the service
                           userSessionService = (IUserSessionService)userServiceTracker.getService();
                           if(userSessionService!=null)
                              return userSessionService;
                        }
                     }
       
                  }
                  else {
                     try {
                        bundle.start();
                        context = bundle.getBundleContext();
                        if(context!=null){
                           //context.getBundle().start();
                           userServiceTracker = new ServiceTracker(context,IContextDataService.class.getName(), null);   
                           if(userServiceTracker!=null){
                              userServiceTracker.open();
                              userSessionService = (IUserSessionService)userServiceTracker.getService();
                              if(userSessionService!=null)
                                 return userSessionService;
                           }
                        }
                     }
                     catch (BundleException e) {
                        // TODO Auto-generated catch block
                        //e.printStackTrace();
                        javaLogger.log(Level.INFO, "Bundle Not Started",e);
                     }
                  }
               } }






    Page 1 of 3



    Comment and Contribute

     


    (Maximum characters: 1200). You have characters left.

     

     


    Sitemap | Contact Us

    Rocket Fuel