Previous: Hello World! Using OSGi Framework – Part III
Class-level scope
If you try running the sample service package now it will print “Hello World” on your Eclipse console. If you try running Activator.java
to access HelloServiceImpl.java
and compile it with the normal javac
complier, it will compile. If you try to execute this bundle in an OSGi container, however, it will throw an exception.
How is the OSGi container able to hide a few classes from the .jar file while others are visible? The answer is that the OSGi container uses the Java class loader to manage class visibility. The OSGi container creates a different class loader for every bundle. The bundle can therefore access classes from
- Boot classpath: Contains the
java.*
packages. - Framework classpath: Usually has a separate class loader for the framework implementation classes as well as key service interface classes.
- Bundle space: Consists of the JAR file that is associated with the bundle plus any additional JARs that are closely tied to the bundle, like fragments.
- Imported packages: For instance, the
HelloWorld
bundle imports thecom.javaworld.sample.service
package so it can access classes from that package.
The bundle-level scope is a powerful feature allowing you (for instance) to safely change the HelloServiceImpl.java
class without worrying that dependent code might break.
OSGi services
As previously mentioned, the OSGi architecture is a very good candidate for implementing service-oriented applications. It allows bundles to export services that can be consumed by other bundles without knowing anything about the exporting bundle. Taken with the ability to hide the actual service implementation class, OSGi provides a perfect combination for service-oriented applications.
In OSGi, a source bundle registers a POJO (you don’t have to implement any interfaces or extend from any superclass) with the OSGi container as a service under one or more interfaces. The target bundle can then ask the OSGi container for services registered under a particular interface. Once the service is found, the target bundle binds with it and can start calling its methods. As with other OSGi concepts, a sample application will make all of this more clear.
Exporting services
In this section we will change the HelloService
bundle so that it exports objects of the HelloServiceImpl.java
class as a service. Here are the steps to set up the sample application:
- Change the
MANIFEST.MF
forcom.javaworld.sample.HelloService
to import theorg.osgi.framework
package. - Create the
com.javaworld.sample.service.impl.HelloServiceActivator.java
as shown in Listing 7.
Listing 7. Create HelloServiceActivator.java
- Note that the source bundle should use the
BundleContext.registerService()
method to export the service. It takes three parameters:- The name of the interface under which you want to register the service. If you want to register the service under multiple interfaces then you should create a
String
array of interface names and pass it as your first argument. In the sample code we want to export the service under the name ofHelloService
interface. - The actual Java object that you want to register as a service. In our sample code we are exporting objects of the
HelloServiceImpl
class as the service. - Properties of the service, in this case a
Dictionary
object. If more than one bundle exports a service under the same interface name then the target object can use these properties to filter out the service that it is interested in.
- The name of the interface under which you want to register the service. If you want to register the service under multiple interfaces then you should create a
- The last step is to change the
MANIFEST.MF
file of theHelloService
bundle to declareHelloServiceActivator
as the bundle’s activator class. To do that, simply addcom.javaworld.sample.service.impl.HelloServiceActivator
as the value of theBundle-Activator
header in yourMANIFEST.MF
file.
public class HelloServiceActivator implements BundleActivator {
ServiceRegistration helloServiceRegistration;
public void start(BundleContext context) throws Exception {
HelloService helloService = new HelloServiceImpl();
helloServiceRegistration =context.registerService(HelloService.class.getName(), helloService, null);
}
public void stop(BundleContext context) throws Exception {
helloServiceRegistration.unregister();
}
}
Now the HelloService
bundle is ready to export objects of the HelloServiceImpl
class. When the OSGi container starts theHelloService
bundle it will pass control to HelloServiceActivator.java
, which will register an object of HelloServiceImpl
as a service. The next step is to create the service consumer.
Importing the service
In this section we will change the HelloWorld
bundle developed in the last section so that it acts as a consumer of theHelloService
service. The main thing you need to do is change the Activator.java
for the HelloWorld
bundle as shown in Listing 8.
Listing 8. HelloWorldActivator.java
public class Activator implements BundleActivator {
ServiceReference helloServiceReference;
public void start(BundleContext context) throws Exception {
System.out.println("Hello World!!");
helloServiceReference= context.getServiceReference(HelloService.class.getName());
HelloService helloService =(HelloService)context.getService(helloServiceReference);
System.out.println(helloService.sayHello());
}
public void stop(BundleContext context) throws Exception {
System.out.println("Goodbye World!!");
context.ungetService(helloServiceReference);
}
}
The BundleContext.getServiceReference()
method returns a ServiceReference
object for a service registered under theHelloService
interface. If multiple such services exist, the service with the highest ranking (as specified in itsConstants.SERVICE_RANKING
property) is returned. Once you have the object of ServiceReference
you can call itsBundleContext.getService()
method to get the actual service object.
You can run this sample the same way you would execute any bundle, by clicking Run –> Run Simply make sure that both the HelloWorld
and HelloService
bundles are checked in as plugins. When you start the HelloService
bundle, you will see the message “Inside HelloServiceImple.sayHello()
” printed from the HelloServiceImpl.sayHello()
method.
Next: Hello World! Using OSGi Framework – Part V
Source: http://www.javaworld.com/javaworld/jw-03-2008/jw-03-osgi1.html
Pingback: Hello World! Using OSGi Framework – Part III | Java Archives
Pingback: Hello World! Using OSGi Framework – Part V | Java Archives