Showing posts with label OSGi import package. Show all posts
Showing posts with label OSGi import package. Show all posts

Wednesday, September 6, 2017

OSGi Bundle MANIFEST Headers

OSGi bundle MANIFEST file is core resource of bundle and we can say its bundle deployment configuration file. OSGi containers will read the information from MANIFEST file and do subsequent actions. We can use many standard OSGi bundle headers in bundle MANIFEST file. Each header have their own significant meaning. Bundle header and its value separated with colon:

The following are headers which proposed by OSGi Alliance. We have other vendor specific headers like Eclipse Foundation, Spring Source and aQute.

OSGi Alliance Standard Headers

The headers proposes by OSGi alliance supported by all OSGi implementation environments like Apache Felix, Equinox and Knopflerfish.

Bundle-ActivationPolicy

Bundle-ActivationPolicy will notify to the container when should bundle available to use or activated. Usually when we deploy bundle, it is immediately available.

Bundle-ActivationPolicy value is lazy it means when bundle will get first request then bundle will be activated.

Example:


Bundle-ActivationPolicy: lazy 


Bundle-Activator

Bundle-Activator header specify the bundle activator java class. Bundle Activator is java class, which manage the bundle life cycle. Each bundle must have activator class and OSGi container invoke the lifecycle methods based on bundle lifecycle stages.

Example:


Bundle-Activator : com.liferaysavvy.bundle.Activator


Bundle-Classpath

Bundle-Classpath is list of values separated by comma delimiter. The values may be jar files or directories and directories have jar files or java classes. Bundle will look for required classes in the given location.

Example:


Bundle-Classpath : apache-commons.jar, apache-logs.jar

OR

Bundle-Classpath : .,WEB-INF/classes,foo1.jar

OR

Bundle-ClassPath: ., A.jar, B.jar, C.jar



Note:

The values separated by comma and dot will specify the current bundle directory.

Bundle-ContactAddress

Bundle-ContactAddress its just information which will use to contact bundle vendors. It’s some text or may be company URL

Example:


Bundle-ContactAddress : Liferay Savvy India

OR

Bundle-ContactAddress : http://www.liferaysavvy.com


Bundle-Copyright

Bundle-Copyright is just copyright information.

Bundle-Description

Bundle-Description is description about bundle and its simple human readable text.

Bundle-License

Bundle-License specify the license information of bundle and it is a text.

Bundle-ManifestVersion:

This header is required and marks the jar as a bundle, the value is always 2 (newer OSGi specifications might add more features in which case the number would be increased).

Value 1 indicates OSGi release 3

Value 2 indicate OSGi release 4

Example:


Bundle-ManifestVersion : 2


Bundle-Name:

Bundle-Name is human readable name for bundle.

Example:


Bundle-Name: LSServiceProvider


Bundle-SymbolicName

Bundle-SymbolicName is unique identification name for bundle. This name will used by other bundle when they have dependency.

Example:


Bundle-SymbolicName: com.ls.de.LSServiceProvider


Bundle-Vendor

Bundle-Vendor is vendor name who implemented the bundle.

Example:


Bundle-Vendor : Liferay Savvy


Bundle-RequiredExecutionEnvironment

Bundle-RequiredExecutionEnvironment is specify the JRE execution environment.

Example:


Bundle-RequiredExecutionEnvironment:  JavaSE-1.8

OR

Bundle-RequiredExecutionEnvironment:  JavaSE-1.7

OR

Bundle-RequiredExecutionEnvironment:  JavaSE-1.6



Bundle-Version

Bundle-Version specify the version number for bundle.

Example:


Bundle-Version: 1.0.0.qualifier

OR

Bundle-Version: 1.0.0


Export-Package

Export-Package contains list of java packages separated by comma delimiter that will be exported and available to other bundles. Only the packages specified by the header will be exported, the rest will be private and will not be seen outside the bundle.

Example:


Export-Package: com.ls.de.lsserviceprovider.services

OR

Export-Package:org.springframework.core.task;uses:="org.springframework.core,org.springframework.util";version=2.5.1 org.springframework.core.type;uses:=org.springframework.core.annotation;version=2.5.1[...]


Export-Service

Export-Service specify the services, which are exported from the bundle, and it will be available to other bundles. List separated by comma delimiter. This header will work when we work with multiple bundles and there is dependency between each other.

Example:


Export-Service: org.osgi.service.log.LogService,org.osgi.service.log.LogReaderService


Import-Package

Import-Package specify the list of bundle packages, which required in the current working bundle. What are the packages exported by other bundles, can import in the current bundle with help of Import-Package header. This header will work when we work with multiple bundles and there is dependency between each other.

Example:


Import-Package: com.ls.de.lsserviceprovider.services

OR

Import-Package:org.apache.commons.logging,edu.emory.mathcs.backport.java.util.concurrent;resolution:=optional[...]


Import-Service

Import-Service is similar to Export-service but it is vice versa. The list of service class names which required by the bundle. Services which are already exported can use in the list.

Example:


Import-Service: org.osgi.service.log.LogService,org.osgi.service.log.LogReaderService


Provide-Capability


More details you can found here



Require-Bundle

Require-Bundle specify the dependency on other bundle. The bundle we specified in the header must be required to activate current bundle. This bundle similar to Import-Bundle header proposed by Spring Source.

Example:


Require-Bundle: org.example.foo; bundle-version=3.0,org.example.bar; bundle-version=1.0



The following are very important headers and we use very regular in the OSGi bundle development.


Manifest-Version
Bundle-ManifestVersion
Bundle-Name
Bundle-SymbolicName
Bundle-Version
Bundle-Activator
Bundle-Vendor
Bundle-RequiredExecutionEnvironment
Export-Package
Import-Package



Spring Source MANIFEST headers

The following are Spring Source proposed MANIFEST headers. To use these headers we must have vendor specific implementation bundle in the OSGi container.

Import-Bundle

Import-Bundle is similar to Require-Bundle proposed by OSGi Alliance and both are same meaning.

Example:

Import-Bundle: org.example.foo; bundle-version=3.0,org.example.bar; bundle-version=1.0


Web-ContextPath.

The default context from which the web content is hosted. You must set the value of the Web-ContextPath header to the value of the <context-root> element for the corresponding web module in the application.xml file. The presence of this header identifies this bundle as a web application bundle.

Example:


Web-ContextPath: /contextRoot


Web-DispatcherServletUrlPatterns

Web-DispatcherServletUrlPatterns specify the URL patterns for Dispatcher servlet.

Example:


Web-DispatcherServletUrlPatterns : /spring/*


Web-FilterMappings

Web-FilterMappings specify the application filter mappings

Example:


Web-FilterMappings  : /secure/*


aQute MANIFEST headers

The following are aQute proposed MANIFEST headers. To use these headers we must have vendor specific implementation bundle in the OSGi container.

Include-Resource

Include-Resource is path where bundle resource files are available like properties files

Example


Include-Resource: src/main/resources


Private-Package

List of packages, which are specific, the current bundle and it will not be available outside. Other bundles cannot access these packages. This header will used in bnd tools developed OSGi environment. Usually we specify the bundle services implementation packages in the list.

Example:


Private-Package: com.ls.de.lsserviceprovider.services.impl



Eclipse Foundation MANIFEST headers

The following are Eclipse Foundation proposed MANIFEST headers. To use these headers we must have vendor specific implementation bundle in the OSGi container. Equinox implementation support these headers.

The following are headers proposed by Eclipse Foundation.


Eclipse-BuddyPolicy
Eclipse-BundleShape
Eclipse-ExtensibleAPI
Eclipse-PlatformFilter
Eclipse-RegisterBuddy


Reference Links


Author

Tuesday, September 5, 2017

OSGi Dependency Management Example

OSGi dependency management explain, how components or bundles share code between bundles. OSGi is dynamic component development so each application composed of components. Dependency Management define how code can be shared between bundles or we can say how we can access one bundle classes/interfaces in other bundles.

When we develop OSGi bundles any class or interfaces which we developed in the bundles accessible to within the bundle and not outside the bundle. Dependency management will explain how we can access one bundle resources in other bundles.

The following articles will give the introduction about OSGi dependency management


Usually to understand example we have two bundles and one bundles will have interface with set of service and its implementation. Other bundle will access the services which are developed by other bundle

The following are the steps

Bundle A Creation

  • Create New Bundle A
  • Define Service in the Interface
  • Implements Service defined in the Interface
  • Export Service Package
  • Register Service Implementation Object with Bundle Context


Bundle B Creation

  • Create New Bundle B
  • Import Service Provider Bundle Services Package
  • Access Service Provider Bundle Service Implementation Object in Consumer Bundle

Prerequisites

Install Java 8
Latest Eclipse IDE (Oxygen Release (4.7.0))

Create New Bundle A

Create New Bundle A

Create new bundle using eclipse with activator class. This bundle will have one interface and its service implementation.

Start Eclipse

File à New Project à New Plugin Project


Bundle Name: com.ls.de.LSServiceProvider

Target Platform à OSGi Framework à standard





Click on next

Click on Check Box Generate Activator Class and provide name


Example:

com.ls.de.lsserviceprovider.ServiceActivator





Click on Finish then new bundle will be created. Bundle can be visible in the project explorer with generated activator class and MANIFEST file



Define Services in the Interface

We already created bundle and now create Service Interface and define the service.
Create new package and create new java interface

Right Click on Project Src à New Interface à Provide Details à Click On Finish

Package :           com.ls.de.lsserviceprovider.services
Interface Name: HelloService





Now define service method in the Interface finally it looks like as follows

HelloService.java


package com.ls.de.lsserviceprovider.services;

public interface HelloService {
      public String greetHello();
}


Implements Service defined in the Interface

We already define the service interface with method. Now we have to implements the service method in the implementation class. Create new package and new implementation class.

Right Click on Project Src à New Class à Provide Details à Click on Finish

Package :           com.ls.de.lsserviceprovider.services.impl
Interface Name: HelloServiceImpl




Implement interface method in the implementation class, finally implementations class as follows.

HelloServiceImpl.java


package com.ls.de.lsserviceprovider.services.impl;

import com.ls.de.lsserviceprovider.services.HelloService;

public class HelloServiceImpl implements HelloService {
    
     @Override
      public String greetHello() {
          
           System.out.println("=====Inside HelloServiceImpl.greetHello()=====");
        return "Hello Greeting from Liferay Savvy World..";
     }

}

Export Services Package

Now we have to Export Services package from services bundles so that these interfaces or resources can be accessible in the other bundles. Remember here only we are exporting services package not implementation package.

MANIFEST have OSGi header called “Export-Package” and we need to add package names with comma separate value, so that we can access these resources in other bundles.

Add “com.ls.de.lsserviceprovider.services” package name under “Export-Package” in the Bundle MANIFEST file

Finally MANIFEST looks as follows

MANIFEST.MF


Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: LSServiceProvider
Bundle-SymbolicName: com.ls.de.LSServiceProvider
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.ls.de.lsserviceprovider.ServiceActivator
Bundle-Vendor: LS
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: com.ls.de.lsserviceprovider.services
Import-Package: org.osgi.framework;version="1.3.0"


Register Service Implementation Object with Bundle Context

Now we need to register service implantation in OSGi Bundle Context so that it will be accessible to other bundles.

The services registration and unregister information will managed by Service Registration object. When we register Service Implementation object with Bundle Context it will return Service Registration Object.

Usually when bundle is started then we register the services with bundle context. We will use Bundle Activator start (--) method to register service objects
Bundle Context have methods registerService(--) and unregister(--) methods to register and unregister service objects.

registerService(--) method will take three arguments

Argument: 1

Service object unique identification to identify the service, usually we will use fully qualified service interface class name

Argument: 2

Service Implementation Object to register with bundle context

Argument: 3

Its Java MAP object to filter the service objects. Sometime same interface have multiple implementation then we will use some filter properties to identify the service implementation object. Service Identification is same for all implementation so we will additional properties to get service objects. In this example we have only one implementation so we have passed null.

unregister(--) method will unregister service object from Bundle Context. Usually we unregister service when bundle is removed from the container then it will call stop(--) lifecycle method. We will unregister service when it execute stop(--) method.

Now go to Bundle Activator class add following code parts in the start (--) and stop (--) methods.  
  
ServiceActivator.java

package com.ls.de.lsserviceprovider;

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

import com.ls.de.lsserviceprovider.services.HelloService;
import com.ls.de.lsserviceprovider.services.impl.HelloServiceImpl;

public class ServiceActivator implements BundleActivator {

     private static BundleContext context;
     ServiceRegistration serviceRegistration;

     static BundleContext getContext() {
           return context;
     }

     /*
      * (non-Javadoc)
      * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
      */
     public void start(BundleContext bundleContext) throws Exception {
           ServiceActivator.context = bundleContext;
           System.out.println("Liferay Savvy Hello World Service Provider Bundle Activator Start");
           HelloService helloService = new HelloServiceImpl();
           serviceRegistration =context.registerService(HelloService.class.getName(), helloService, null);
     }

     /*
      * (non-Javadoc)
      * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
      */
     public void stop(BundleContext bundleContext) throws Exception {
           ServiceActivator.context = null;
           System.out.println("Liferay Savvy Hello World Service Provider Bundle Activator Stop");
           serviceRegistration.unregister();
     }

}


Create New Bundle B

Create new bundle using eclipse with activator class.
Start Eclipse

File à New Project à New Plugin Project


Bundle Name: com.ls.de.LSServiceConsumer
Target Platform à OSGi Framework à standard





Click on next

Click on Check Box Generate Activator Class and provide name


Example:

com.ls.de.serviceconsumer.ServiceConsumerActivator



Click on Finish then new bundle will be created. Bundle can be visible in the project explorer with generated activator class and MANIFEST file




Import Service Provider Bundle Services Package

We have to Import Services package from services bundle so that these interfaces or resources can be accessible in the consumer bundle.

MANIFEST have OSGi header called “Import-Package” and we need to add package names with comma separate value, so that we can access these resources in current bundle.

Add “com.ls.de.lsserviceprovider.services” package name under “Import-Package” in the Bundle MANIFEST file

Finally MANIFEST looks as follows

MANIFEST.MF


Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: LSServiceConsumer
Bundle-SymbolicName: com.ls.de.LSServiceConsumer
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.ls.de.serviceconsumer.ServiceConsumerActivator
Bundle-Vendor: LS
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.ls.de.lsserviceprovider.services,
 org.osgi.framework;version="1.3.0"


When we use import header then the listed java classes and interfaces are available in the current working bundles.

Access Service Provider Bundle Service Implementation Object in Consumer Bundle

We already register services object and exported package in the consumer bundle. Now we can user service implementation in the consumer bundle. Now we can access service implementation object from consumer bundle context.

We have Bundle Context getService(--) method and it will return the service implementation object. We need to pass service reference object for this method.

We will identify the Service Implementation Object by service interface name. We already register the service with same name. So we will use same name to identify the service implementation Object.

We will use consumer Activator Class to get implementation object and call the required services.

Go to Consumer Bundle Activator class add the following code part in the Start (--) method and invoke service method using service implementation object.

ServiceConsumerActivator.java

package com.ls.de.serviceconsumer;

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

import com.ls.de.lsserviceprovider.services.HelloService;

public class ServiceConsumerActivator implements BundleActivator {

     private static BundleContext context;
     ServiceReference helloServiceReference;

     static BundleContext getContext() {
           return context;
     }

     /*
      * (non-Javadoc)
      * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
      */
     public void start(BundleContext bundleContext) throws Exception {
            ServiceConsumerActivator.context = bundleContext;
            System.out.println("Hello World Consumer Bundle Activator Start");
          helloServiceReference= context.getServiceReference(HelloService.class.getName());
          HelloService helloService =(HelloService)context.getService(helloServiceReference);
          System.out.println(helloService.greetHello());

     }

     /*
      * (non-Javadoc)
      * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
      */
     public void stop(BundleContext bundleContext) throws Exception {
           ServiceConsumerActivator.context = null;
           System.out.println("Hello World Consumer Bundle Activator Stop");
           context.ungetService(helloServiceReference);
     }

}



Execute Bundles

We have two bundles Service Provider Bundle and Service Consumer bundle.
Service Consumer bundle dependence on Service Provider Bundle. So we have to activate Service Provider bundler before access services in the consumer bundle.


Service Provider Bundle Name:
 com.ls.de.LSServiceProvider

Service Consumer Bundle Name:
com.ls.de.LSServiceConsumer



Start com.ls.de.LSServiceProvider

Go to com.ls.de.LSServiceProvider Activator Class and Right click on class you can see Run

Right Click à Run à Run Configuration

Run configuration window check the required bundles then click on run
Basically we need OSGi implementation bundles that equinox and we can also use other implementation as well like apache Felix. Other two bundles are that we developed. Select only service provider bundle so that only provider bundle will be executed.



Once you run then bundle will activated you can see messages in the console.
In the console just type OSGi gogo shell command to list the bundles then you can see Service Provider Bundle in the list and we can see status that is activated.

Type following command in the gogo shell then we can see all bundles list

lb



Now you can see Service Provider bundle in the list with active state and bundle number.


Now use following stop and start commands then you can see console messages. It will invoke Bundle Activator class


osgi> stop 1003
Liferay Savvy Hello World Service Provider Bundle Activator Stop
osgi> start 1003
Liferay Savvy Hello World Service Provider Bundle Activator Start
osgi>


Note:

We will use bundle number to start or stop bundle in the OSGi container.

The following console shows Invoking Service Provider Bundle Life cycle methods.


Start com.ls.de.LSServiceConsumer

Service Provide Bundle is activated and Now execute Service Consumer bundles so that it will invoke the greetHello(--) method which is implemented in the Service Provider bundle.
Go to com.ls.de.LSServiceConsumer Activator Class and Right click on class you can see Run

Right Click à Run à Run Configuration

Run configuration window check the required bundles then click on run
Basically we need OSGi implementation bundles that equinox and we can also use other implementation as well like apache Felix. Other two bundles are that we developed. Select both bundle and click on run.


Go to Console and list bundles using lb command then you can see both bundles are in active state

Now use stop and start shell commands for service consumer bundle then we can see the console message that make sure that is invoking greetHell(--) method from service provider bundle from consumer bundle

osgi> stop 1003
Liferay Savvy Hello World Service Provider Bundle Activator Stop

osgi> stop 1004

osgi> start 1003
Liferay Savvy Hello World Service Provider Bundle Activator Start

osgi> start 1004
Liferay Savvy Hello World Consumer Bundle Activator Start
=====Inside HelloServiceImpl.greetHello()=====
Hello Greeting from Liferay Savvy World..

osgi>

The following is console which shows its invoked greetHello(--) method




Author

Recent Posts

Recent Posts Widget

Popular Posts