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
Download
Source
Author
0 comments :
Post a Comment