Professional Documents
Culture Documents
Introduction To Osgi Working in Osgi Environment: Valentin Valchev
Introduction To Osgi Working in Osgi Environment: Valentin Valchev
Introduction To Osgi Working in Osgi Environment: Valentin Valchev
Contents
1 Introduction 1.1 The Connected Home . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 The OSGi Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 OSGi Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Bundles 2.1 What is a Bundle . . . . . . . 2.2 Bundle Manifests . . . . . . . 2.3 Writing Bundles . . . . . . . . 2.4 What is Bundle Lifecycle . . . 2.5 A Bundle without an Activator 3 Services 3.1 What is a Service . . . . . . . 3.2 Bundles and Services . . . . . 3.3 Core OSGi Services . . . . . . 3.3.1 Device Access Service 3.3.2 HTTP Service . . . . . 3.3.3 Log Service . . . . . . 3.4 Using Services . . . . . . . . 3.5 Service Properties . . . . . . . 3.6 LDAP Filters . . . . . . . . . 3.7 Service Events and Listeners . 3.8 Using Service Tracker . . . . 4 Conclusion 2 2 2 2 4 4 4 5 6 7 9 9 9 9 9 9 10 10 12 16 18 20 22
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
1 INTRODUCTION
1 Introduction
1.1 The Connected Home
A long time ago, the computer was created to help scientists do their mathematical calculations. Years later, the computer became a tool for personal usage - we can use electronic spread sheets, we can write letters using powerful word processors, play games at home, etc. Computers are going more and more powerful each day. There are board computers in airplanes, trucks, cars, there are computers even at home. Along with progressive manufacturers offering complete home automation suite, it would be nice if we could connect these devices with our personal computer. Wouldnt it be nice to control some of your household chores by just sending a simple message through Internet. Wouldnt you feel more comfortable if you leave home knowing that everything is safe because you can control your home anytime and from anywhere. Besides home control, you can enjoy network-based services that are delivered to you by service providers and you can enjoy benets like watching your favorite movie on request, pay your phone bill while watching television and this without any particular knowledge of the whole system because your service provider does everything about maintenance instead of you.
1 INTRODUCTION
The OSGi specication allows easy maintenance of device and services, dynamic update of device drivers, easy delivery of various services, remote control and last but not least - security. Besides these very important features, as OSGi species that all software is written in Java, this makes it portable across various platforms and code written for one gateway will run without any modication on another one. The OSGi framework is the heart of the residential gateway. Each other piece of code is called bundle and it can be dynamically delivered to framework. Old Software can be easily replaced and that which is not anymore necessary can be also such easily uninstalled. Bundles themselves communicate with each other through services. The OSGi model has advanced API for retrieving and using services. Service repository enables developers to reuse common code without rewriting it and increasing software footprint and memory requirements.
2 BUNDLES
2 Bundles
This section describes what a bundle is, how a bundle is dened and how to write bundles. The chapters below are written for beginners but they presume that the reader has already downloaded the OSGi specication. If you dont have it, please download it from www.osgi.org and take a look at it before reading the following chapters. Dont worry if you initially dont understand anything - this tutorial will help you to understand it - but the specication is still required just for reference.
Bundle-ClassPath is an optional header for bundles that use their own resources. A typical bundle that uses this header is bundle - wrapper for another vendors packages. Bundle-NativeCode is a required header for bundles that exploit native code. This header is read by the bundle loader class and the described libraries are extracted from the bundles jar le and loaded by the Java Virtual Machine. Import-Package is used by bundles that use resources from other bundles. Imported packages must be exported by another bundle rst. If an imported package cannot be found, the bundle cannot be used. Export-Package is used by bundles that expose resources/packages to other bundles in the framework. Bundle-Activator contains the main activator class name which should be loaded by the bundle loader.
2 BUNDLES
Bundle-Name is a mandatory eld. This is the user friendly name of this bundle. Bundle-Description is a optional eld containing additional, more comprehensive description of the bundle and its purpose. Bundle-Version is an optional eld containing bundle version number. Bundle-Vendor is an optional eld that contains the bundle vendors name. Bundle-DocURL is an optional parameter containing the url where could nd more information about this bundle. Bundle-ContactAddress is an optional parameter containing additional information about how to receive support with this bundle. Bundle-UpdateLocation is a deprecated eld that must not be used.
And here is a simple manifest content:
Manifest-Version: 1.0 Bundle-Vendor: ProSyst Bundle-Version: 4.1.0 Bundle-ClassPath: ., servlet.jar Bundle-Category: OSGi Bundle-Activator: com.prosyst.mbs.impl.services.http.HttpActivator Bundle-Name: Http Bundle Export-Package: org.osgi.service.http, javax.servlet, javax.servlet.http Bundle-Description: The HTTP Bundle hosts an integrated HTTP server and Servlet 2.2 Engine that allow access to server and bundle resources over HTTP 1.1. Import-Package: org.osgi.service.cm
Although the manifest le is very important, there is nothing as important as the source code. In the next chapter you will learn how to write simple bundles.
2 BUNDLES
package tutorial.bundles.hello; import org.osgi.framework.; public class HelloActivator implements BundleActivator public void start(BundleContext bc) throws BundleException System.out.println("Hello World started");
Having the source code, we are ready to compile it. You should have at least the interfaces dened by OSGi to compile this example. When the source is compiled, we have to create a manifest le for our bundle. Here are the manifests contents:
Bundle-Version: 1.0.0 Bundle-Name: Hello Bundle-Description: The Hello World bundle. Bundle-Activator: tutorial.bundles.hello.HelloActivator
Having both compiled classes and written the manifest le, we can create the bundle - just pack the classes in a jar le not forgetting to add the right manifest le. The JAR le youve just created is our hello world bundle. Now you can install it on an OSGi framework and start it. You will see the Hello World started message. This bundle is the simplest we can create. More advanced topics about bundles are covered by the following sections. The next chapter will be your guide to OSGi services.
2 BUNDLES
Installed
Uninstalled
Resolved
Stopping
Starting
Active
When a bundle is installed, it is initially set to INSTALLED stated. During its life, the bundles state can switch among STARTING, STOPPING and ACTIVE. Once a bundle is stopped it gets RESOLVED state. When a bundle is no longer needed and a framework administrator uninstalls it, it will receive UNINSTALLED state. The moments a bundle becomes INSTALLED and UNINSTALLED are the end points in its Lifecycle. Hence, Bundle Lifecycle implies the periodical change of a bundles state between INSTALLED and UNINSTALLED events. What is so important about this? The idea of bundle lifecycle is the dynamic deployment, management and control over bundles and services. The JavaDoc section of the Bundle interface contains more detailed description of a Bundle itself, how it is created and methods which can be invoked on it. It is also very useful reading before continuing with the next chapters.
2 BUNDLES
indicate the vendors packed jar le, and Export-Packages containing list of the vendors API packages.
3 SERVICES
3 Services
3.1 What is a Service
Here is a quotation of Chapter 4 (Services) of OSGi Framework Specication 1.0: A service is an object that provides some well-dened functionality which is dened by the object classes it implements. It is owned by (and runs within) a bundle that makes its functionality available to other bundles by registering it with the Framework. The dependencies between the bundle owning the service and the bundles using it are managed by the Framework. So in brief we will say that service is a collection of interfaces and their implementations. And this will be our guiding point for this chapter.
3 SERVICES
HTTP Service allows other bundles in the OSGi Framework to register resources and servlets to be accessed via Hypertext Transfer Protocol (HTTP). HTTP Service may implement either HTTP/1.0 or HTTP/1.1. If you look through the JavaDoc for the HTTP Service you will nd valuable examples how to use it for registration of servlets and resources. 3.3.3 Log Service The OSGi framework is an execution environment for many bundles and services that may need to provide some additional information to the user via the log system. The log system can also be used in secure systems as the OSGi framework pretends to be. Thus OSGi species the core Log Service as a common storage for event, debug, emergency and security information. The Log service provides objects and methods for writing and reading log entries. The Log Service interfaces are declared in the org.osgi.service.log package and are very well documented in the corresponding JavaDoc les.
10
3 SERVICES
package tutorial.services.log; import org.osgi.framework.; import org.osgi.service.log.; public class LogDemo implements BundleActivator private nal static String logClass = "org.osgi.service.log.LogService"; / LogService refernce / private ServiceReference sRef = null; / LogService used to log messages / private LogService logService = null;
public void start(BundleContext bc) throws BundleException sRef = bc.getServiceReference(logClass); if( sRef null ) logService = (LogService)bc.getService(sRef); logService.log(LogService.LOG INFO, "Bundle is started"); else throw new BundleException("Unable to get LogService reference");
public void stop(BundleContext bc) logService.log(LogService.LOG INFO, "Bundle is stopped"); bc.ungetService(sRef); sRef = null; logService = null;
Bundle-Version: 1.0.0 Bundle-Name: LogDemo Bundle-Description: LogDemo bundle from tutorial. Bundle-Activator: tutorial.services.log.LogDemo Import-Package: org.osgi.service.log
11
3 SERVICES
Now pack the bundle code and the manifest into a JAR le, install it on your OSGi Framework and play with it. When you start and stop that bundle you can watch the log messages (use your vendor provided tools) and see if it works. The sources of the packed bundle can be found in sources/log directory.
12
3 SERVICES
EchoServiceImpl1.java: package tutorial.services.echo.impl; import tutorial.services.echo.EchoService; / This implementation of echo service will display echo string on System.out (java console screen) / public class EchoServiceImpl1 implements EchoService public void echo(String s) System.out.println("echo:" + s);
13
3 SERVICES
EchoServiceImpl2.java: package tutorial.services.echo.impl; import java.net.; import java.io.IOException; import tutorial.services.echo.EchoService; / This implementation of echo service will broadcast UDP packet to port 1234 containing echo string. / public class EchoServiceImpl2 implements EchoService DatagramSocket socket = null; InetAddress bcast = null; public EchoServiceImpl2() throws Exception socket = new DatagramSocket(); bcast = InetAddress.getByName("255.255.255.255");
public void echo(String s) if ( s null ) byte[] bytes = s.getBytes(); DatagramPacket packet = new DatagramPacket(bytes, bytes.length, bcast, 1234); try socket.send(packet); catch (IOException e) // just ignore this
EchoActivator.java:
14
3 SERVICES
public class EchoActivator implements BundleActivator private static nal String serviceName = "tutorial.services.echo.EchoService"; / Service registration for EchoServiceImpl1 / private ServiceRegistration reg1 = null; / Service registration for EchoServiceImpl2 / private ServiceRegistration reg2 = null; private EchoServiceImpl1 impl1 = null; private EchoServiceImpl2 impl2 = null; public void start(BundleContext bc) throws BundleException Properties props = new Properties(); impl1 = new EchoServiceImpl1(); try impl2 = new EchoServiceImpl2(); catch (Exception e) / register rst implementation / props.put("origin", "console"); reg1 = bc.registerService(serviceName, impl1, props); / register second implementation / if( impl2 null ) props.put("origin", "broadcast"); reg2 = bc.registerService(serviceName, impl2, props);
public void stop(BundleContext bc) if( reg1 null ) reg1.unregister(); if( reg2 null ) reg2.unregister();
15
3 SERVICES
Bundle-Version: 1.0.0 Bundle-Name: Echo Bundle-Description: Echo Service Example. This bundle illustrates usage of service properties. Bundle-Activator: tutorial.services.echo.EchoActivator Export-Package: tutorial.services.echo
This entire code and the bundle can be found in the sources/echo directory. In the next section you will learn how to retrieve services using their properties.
(&(objectClass=com.acme.MyLamp)(location=Kitchen))
You can see that it is very simple and easy to construct such a lter. But now we will include the lter in a real code. We will use the echo bundle from the previous chapter and we will use the lter to choose the implementation that echoes to console. Here is the code (FiltersActivator.java):
16
3 SERVICES
package tutorial.services.lters; import tutorial.services.echo.EchoService; import org.osgi.framework.; public class FiltersActivator implements BundleActivator private static nal String serviceName = "tutorial.services.echo.EchoService"; ServiceReference ref = null; public void start(BundleContext bc) throws Exception ServiceReference[] refs = bc.getServiceReferences( serviceName, "(origin console)"); if( (refs null) && (refs[0] null) ) ref = refs[0]; EchoService svc = (EchoService)bc.getService(ref); if( svc null ) svc.echo("This string must be printed from inside Echo Service");
Bundle-Version: 1.0.0 Bundle-Name: Filters Bundle-Description: This bundle illustrates usage of LDAP filters to retrieve services. Bundle-Activator: tutorial.services.filters.FiltersActivator Import-Package: tutorial.services.echo
The sources listed here are available as .java les and a ready-built bundle in the sources/lters directory.
17
3 SERVICES
18
3 SERVICES
package tutorial.services.events; import org.osgi.framework.; public class EventsActivator implements BundleActivator, ServiceListener private static nal String lter = "(objectClass tutorial.services.echo.EchoService)"; public void start(BundleContext bc) throws Exception bc.addServiceListener(this, lter);
public void stop(BundleContext bc) bc.removeServiceListener(this); / This method implements ServiceListener interface / public void serviceChanged(ServiceEvent event) ServiceReference ref = event.getServiceReference(); String action = null; switch(event.getType()) case ServiceEvent.REGISTERED: action = "REGISTERED"; break; case ServiceEvent.MODIFIED: action = "MODIFIED"; break; case ServiceEvent.UNREGISTERING: action = "UNREGISTERING"; String classes[] = (String[])ref.getProperty("objectClass"); System.out.println("Service " + classes[0] + " is " + action);
19
3 SERVICES
Bundle-Version: 1.0.0 Bundle-Name: Echo Bundle-Description: A simple service that prints on console registering/unregistering/modifying of EchoService service. Bundle-Activator: tutorial.services.events.EventsActivator
in bundles manifest le. Afterwards a ServiceTracker object can be created in three ways. The rst one is to specify a class name and all services registered with the same class name will be tracked. The second one is to specify a LDAP lter - this way all services with specied properties will be tracked. And the third way is to provide a single ServiceReference to track the exact service to which that ServiceReference points. The tracking process begins when open method is called. When a service is added, modied or removed, the ServiceTracker will call addingService, modiedService or removedService , respectively. You can read more about ServiceTracker in its documentation (JavaDoc). But now its time to see it in action, creating a simple bundle and illustrate its usage. We will use the example from the previous section but instead of using service listeners we will use ServiceTracker.
20
3 SERVICES
package tutorial.services.tracker; import org.osgi.framework.; import org.osgi.util.tracker.; public class TrackerActivator implements BundleActivator, ServiceTrackerCustomizer private static nal String lter = "(objectClass tutorial.services.echo.EchoService)"; private ServiceTracker tracker = null; private BundleContext bc = null; public void start(BundleContext bc) throws Exception this.bc = bc; tracker = new ServiceTracker(bc, bc.createFilter(lter), this); tracker.open();
//nothing here
// A simple method to extract service name from ServiceReference object. private String getServiceName(ServiceReference ref) String name = "[ "; String classes[] = (String[])ref.getProperty("objectClass"); if( classes null ) for(int i=0; i classes.length;i++) name += classes[i] + " "; name += "]"; else name = "noname?"; return name;
// The following methods implements ServiceTrackerCustomizer interface. public Object addingService(ServiceReference ref) System.out.println( "Adding service named " + getServiceName(ref) ); return bc.getService(ref);
public void modiedService(ServiceReference ref, Object service) System.out.println("Modified service named " + getServiceName(ref) );
public void removedService(ServiceReference ref, Object service) System.out.println("Removed service named " + getServiceName(ref) ); 21
4 CONCLUSION
4 Conclusion
I hope this book helped you enough and now you can easily write simple bundles and use services, lters and events. If you have any notes about this book, suggestions or anything else dont hesitate to send me an e-mail. You can do this just clicking on my name on the rst page. I would also like to write another book, containing some more topics for intermediate OSGi programmers so if you have something in mind, suggestions, ideas of what it should contain - write me. I will greatly appreciate any quality feedback.
22