aqute bundle programming by peter kriens ceo aqute osgi director of technology & osgi fellow
TRANSCRIPT
aQuteBundle Programming
By Peter KriensCEO aQute
OSGi Director of Technology & OSGi Fellow
©1999-2004 aQute, All Rights Reserved slide #2
Contents
• Overview• The Bundle• Class loading• Using Services• Threads and synchronization• Cleaning up• Whiteboard pattern• Life Cycle Operations• XML Parsing• Tools
©1999-2004 aQute, All Rights Reserved slide #3
Bundle Programming Overview
• So you have to start programming for OSGi?
• Assuming you have some experience with J2SE programming, what are the key differences?– Dynamic environment, everything changes all the time– You share code and resources with other applications– Many bundles run on resource constrained devices
• Programming in a dynamic environment is difficult
• The course first goes through the “gory” details and then shows some convenience models that are coming in R4
©1999-2004 aQute, All Rights Reserved slide #4
The bundle
• A bundle is a JAR file– Based on the ZIP format,
contains• Classes• Resources (images,files)• Manifest
• A bundle contains all that is necessary to run it, except some well defined dependencies
©1999-2004 aQute, All Rights Reserved slide #5
Bundle model
• Bundles are like the (old) Mac model, not like the PC model
• A single file contains all that is needed
• No requirement for application installers that modify data all over the place
• Subsystems access the bundle to provide the relevant information they need
• No uninstallers that leave remains
WebServer
DeskTop
DataBase
MacApplication
PCApplication
©1999-2004 aQute, All Rights Reserved slide #6
Bundle Model
• For example, a management system wants to use an icon for a bundle
• They agree on a common name for a gif resource in the JAR file (the icon)
• If the management system receives the JAR it can find the icon and display
• System is easy to extend independent from others, only the JAR namespace must be managed
ManagementSystem
Bundle
META-INF MANIFEST.MF icon.gifcom/acme/appl/……
Get META-INF/icon.gif
Displayicon
©1999-2004 aQute, All Rights Reserved slide #7
Bundle Model
• Most important resources are the classes
• Classes in Java are packed in packages
• Each package is a directory in the JAR file– Dots become / however
• Naming, by convention, is done with the reverse domain name– com.acme.application
• Package naming is important for versioning an dependencies
• Never program in the default package (i.e. no package name specified)
com.acme.application
com.acme.application
javax.servletjavax.servlet
javax.servlet.httpjavax.servlet.http
META-INF MANIFEST.MFcom/acme/application MyApplication.class smiley.gif Handler.classjavax/servlet Servlet.class ServletRequest.classjavax/servlet/http …
©1999-2004 aQute, All Rights Reserved slide #8
Manifest
• The Manifest contains information about the bundle and its resources
• The Manifest is standardized by SUN
– http://java.sun.com/docs/books/tutorial/jar/basics/manifest.html
– http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html
• The basic format is – Header– ‘:’– Value (max 76 characters but is
extended on the next line if the next line starts with a space)
• A valid manifest starts with– Manifest-Version: 1.0
• Headers are not case sensitive• Java 2 has a Manifest parser in
the java.util.jar package
©1999-2004 aQute, All Rights Reserved slide #9
Interesting OSGi headers
• Bundle-Activator– The fully qualified name of a class that is used to start the bundle
• Bundle-Name– Human Readable name, used to in UIs
• Bundle-SymbolicName– Name of the application that this bundle implements. The
symbolic name must remain the same, but the version may change
• Bundle-Version– The actual version of the bundle.
• <major>[.<minor>[.<micro>[.<qualifier>]]]
• Bundle-Vendor• Bundle-Copyright• Bundle-Category• Bundle-Description
©1999-2004 aQute, All Rights Reserved slide #10
Starting the bundle
• There are two types of bundles– Applications– Libraries
• Applications require the activation of the bundle, libraries only export packages
• The manifest header Bundle-Activator points to a fully qualified class name– com.acme.application.Activator
• This class must implement the org.osgi.framework.BundleActivator interface
• When using Eclipse, the browse button in the manifest header will analyze the classes to find out which classes implement this interface
©1999-2004 aQute, All Rights Reserved slide #11
Starting the bundle
• The start method from the BundleActivator interface must be implemented carefully
• The start method borrows a Framework thread that is shared between all bundles. The start method should therefore return quickly
• Programmers do heavy initialization in the start method and the start method is synchronous and sequential
• A start method does not get its own thread!
©1999-2004 aQute, All Rights Reserved slide #12
Initialization
• Number one problem in OSGi deployments is startup time …
• Initialization should be limited to setting up the minimum and doing the rest of the initialization when the functionality is really needed– Lazy initialization is best, maybe your function is never
needed!– Heavy initialization should be done in a thread
• Dangerous functions are– Opening connections (name lookup can take serious time)– Allocating resources that are not yet needed– Waiting for events that can take time to happen
©1999-2004 aQute, All Rights Reserved slide #13
The BundleContext
• The start method hands over a org.osgi.framework.BundleContext object
• This object represents the Framework but each bundle will gets own private context
• BundleContext objects should not be shared– Cost allocation– Capability
• The Framework is the center of the OSGi service platform universe
BundleA
Framework
BundleB Bundle
C
Bundle Context
©1999-2004 aQute, All Rights Reserved slide #14
Bundle Context method categories
• Private File Access
• Service Registry
• Event Handling
• Life Cycle Management
• Status information
• More about this later …
©1999-2004 aQute, All Rights Reserved slide #15
Sharing packages
• The Hello World example was trivial because it was fully self contained– It did not use any external resources– Nor did it provide any
• Real world applications share code and interact with each other
• Bundles can come and go at will, this introduces difficult sharing problems– What will happen when shared package goes away?– What happens when a new version becomes available?
• The Framework handles these issues
©1999-2004 aQute, All Rights Reserved slide #16
Sharing packages
• All classes in the bundle are by default private
• Sharing of classes is done with packages
• Manifest headers are used to control the sharing
• Import-Package contains a list of packages that are needed before this bundle can run– Import-Package:
com.acme.application, com.acme.event, javax.servlet
Bundle B
Framework
Import-Package
©1999-2004 aQute, All Rights Reserved slide #17
Sharing packages
• Export-Package contains a list of packages that may be shared with other bundles– Export-Package: com.acme.xyz,
javax.
• All packages that are referred to from a bundle must be imported except ones that start with java.
• This said, there is an issue that currently packages on the classpath must not be imported or they cannot be found. This may change in the future
Bundle A
Bundle B
Framework
Import-Package
Export-Package
©1999-2004 aQute, All Rights Reserved slide #18
Class cast exception
• The Framework guarantees that each package has only a single provider by picking only one provider, even if there are multiple exporters
• Why is it important that all bundles use the same class object?
• If the same class occurs multiple times in the system, bundles will experience hard to trouble shoot ClassCastExceptions because the names of the classes are equal
• So the Framework prevents this case
MyObject x = (MyObject) z;
BundleA
BundleB
B Provides the MyObjectClass
But z is from theclass MyObject from A
©1999-2004 aQute, All Rights Reserved slide #19
Package sharing
A B
C
Private classes
Shared classesFramework guarantees single Exporter for each package
©1999-2004 aQute, All Rights Reserved slide #20
Package versions
• When a package is imported or exported, it may have a version– Import-Package: com.acme.application;specification-version=“3.1”– Export-Package: com.acme.application;specification-version=“3.5”
• You may both import and export a package with different versions– Try to explain why export should have a higher version number?
• Packages must be backward compatible with lower version numbers
• When the specification-version attribute is omitted, the Framework assumes a version that is less than 0.0.0
©1999-2004 aQute, All Rights Reserved slide #21
Standard libraries and versions
• Many standard libraries are not well versioned, if at all
• Even if they are, they do not have the OSGi headers
• This means they should normally be imported without version specifiers
©1999-2004 aQute, All Rights Reserved slide #22
R4 And Versions
• R4 will have a more rich version model as well as standardizing the version syntax– Supported by a Version object
• Import can be specified with ranges, no longer requiring the backward compatibility rules
• R4 will also allow sharing of bundles– Enables private package sharing between bundles– Means same package name can appear in the system
in different versions
©1999-2004 aQute, All Rights Reserved slide #23
Resolving
• Before a bundle is started, it must be resolved
• Resolving tries to match imports and exports
• If a bundle is resolved, it may be started
• Resolving may happen at any time between the installation and start
• Starting the bundle must attempt to resolve the bundle
©1999-2004 aQute, All Rights Reserved slide #24
Resolving
Bundle AExport org.osgi.service.log com.ibm.service.log com.ibm.j9Import org.osgi.service.http javax.servlet.http
Framework org.osgi.framework org.osgi.service.http
Bundle BExport ericsson.osgi javax.servlet javax.servlet.http org.osgi.service.logImport org.osgi.service.http
B resolved
A resolved
©1999-2004 aQute, All Rights Reserved slide #25
Dynamic Importing
• Static import (Import-Package) allows tool to reason about the bundle before it is installed
• Sometimes the packages that need to be imported are not known a-priori
• This only possible with the Class.forName mechanism• Many popular packages use Class.forName to bind to unknown
providers– Ant tasks– Jave Media Framework plugins– Applets– Security Providers
• Normal compiled implies that the dependency is always known a priori
• Tools can take advantage of this a priori knowledge and create the appropriate import statements
©1999-2004 aQute, All Rights Reserved slide #26
Assignment: Playing with Import and Export
• Use the Hello World project to see the effects of importing and exporting
• Add an import clause to the manifest of “hello world” – Import-Package: org.osgi.framework
• Create the JAR and check the console
• The bundle should start OK
©1999-2004 aQute, All Rights Reserved slide #27
Cheating
• Note that we actually cheated in the Eclipse tutorial, we never imported org.osgi.framework, but we should have
• It works because the org.osgi.framework package is also on the system class path
• In officially is required to import org.osgi.framework though … in R4 code that does not import correctly will break
©1999-2004 aQute, All Rights Reserved slide #28
Assignment: Playing with Import and Export
• Modify the manifest to add a version of 99 to the import statement– Import-Package:
org.osgi.framework;specification-version=99
• Build and check again
• Now move back to version 1
• Check again
©1999-2004 aQute, All Rights Reserved slide #29
Assignment: Playing with Import and Export
©1999-2004 aQute, All Rights Reserved slide #30
What happens when we use a class we do not import?
• Make a copy of HelloWorld, call it UsingImportedClass
• Extend HttpServlet
• (Use Control-Shift-O to find the imports)
• Change the manifest so it points to our new UsingImportedClass
• Create the bundle
• See the error message on the bottom of the console
• The framework cannot find the java.servlet.http package
©1999-2004 aQute, All Rights Reserved slide #31
How do we solve this?
• Create an import statement in the manifest for– javax.servlet – javax.servlet.http
• Both are needed because javax.servlet.http.HttpServlet extends javax.servlet.Servlet …
Manifest-Version: 1.0Bundle-Activator:
aQute.workshop.hello.UsingImportedClassImport-Package:
org.osgi.service.log;specification-version=1.2,
javax.servlet;specificaton-version=2.1, javax.servlet.http; specificaton-version=2.1
©1999-2004 aQute, All Rights Reserved slide #32
How can we get the ClassCastException?
• This is something you (normally) want to avoid at all times! However, it is educational to see how it can be done.
• The ClassCastException can happen when:– You have a class in your JAR, say X– You get an object from elsewhere that is of class X– You assign this object to a variable of type X
©1999-2004 aQute, All Rights Reserved slide #33
How to get a class cast exception
• We can show this using services (which will be thoroughly discussed later)
• We will get the log service from the Framework
• We will also include the org.osgi.service.log package into our JAR
• By using 2 different manifests we select where the log comes from
HelloWorld.jar
osgi.jar
...service.logaQute.hello
...service.log…
©1999-2004 aQute, All Rights Reserved slide #34
Class Cast Exception
package aQute.workshop.hello;import org.osgi.framework.*;import org.osgi.service.log.*;
public class ClassCastException implements BundleActivator {public void start(BundleContext context) throws Exception { System.out.println("ClassCastException Example"); ServiceReference ref = context.getServiceReference(LogService.class.getName()); Object object = context.getService(ref); try { LogService log = (LogService) object; System.out.println("We could succesfully cast the log service ... "); } catch( Exception cce ) { System.out.println("We could not cast the log service ... "); } System.out.println( "Classloader we see: " + LogService.class + " " + LogService.class.getClassLoader() ); Class [] interfaces = object.getClass().getInterfaces(); for ( int i = 0; i<interfaces.length; i++ ) { System.out.println( "Their classloader " + interfaces[i] + " " + interfaces[i].getClassLoader() ); }}public void stop(BundleContext arg0) throws Exception { System.out.println("Goodbye ClassCastException");}
}
©1999-2004 aQute, All Rights Reserved slide #35
HelloWorld
Log Service
Class Cast Exception
Manifest 1 (different classloaders)
Manifest-Version: 1.0Bundle-Activator:
aQute.workshop.hello.ClassCastException
Import-Package: org.osgi.framework; specification-version=1
Manifest 2 (importing, assuring same classloader)
Manifest-Version: 1.0Bundle-Activator:
aQute.workshop.hello.ClassCastException
Import-Package: org.osgi.framework; specification-version=1,
org.osgi.service.log;specification-version=1.2
org.osgi.service.log
aQute.workshop.hello
org.osgi.service.log
org.osgi.impl.service.log
…
object
variable
Ouch…OK
©1999-2004 aQute, All Rights Reserved slide #36
What Did This Assignment Teach?
• Bundles have dependencies on other classes that must be fulfilled before the bundle can be resolved
• Resolved bundles can be started
• It is necessary to specify all imports except java.*
• Class cast exceptions are hard to debug!
©1999-2004 aQute, All Rights Reserved slide #37
Bundle Class path
• There is a special manifest header that is called Bundle-Classpath
• This contains a comma separated list of embedded JAR files – “.” is the JAR itself– Bundle-Classpath: .,servlet.jar
• The Framework will treat the JAR file according to this Bundle classpath– Including order
• Powerful way to include existing JAR files without having to break them open
main.jarb.jar
c.jara.jar
Bundle-Classpath: .,a.jar,
b.jar,c.jar
©1999-2004 aQute, All Rights Reserved slide #38
Collaborative model
• The OSGi specifications are more than an Applet, MIDlet, Xlet runner
• These models access APIs through shared packages– Factories– Listeners
• This model is supported in OSGi, but there are some disadvantages to this model– Packages need to be resolved at bundle start time, hard, if
not impossible, to add missing packages later– No notifications for packages that come and go– Difficult to model multiplicity– Java can eagerly bind linked packages– Classloading issues
©1999-2004 aQute, All Rights Reserved slide #39
Collaborative Model
• What is needed is a controlled facility to communicate with other bundles
• The OSGi Alliance therefore introduced the service registry
• The service registry allows bundles to register objects through which they can communicate
• Other bundles can find these objects, or get notifications when they are registered or unregistered
• Framework fully manages this collaboration– Dependencies– security
©1999-2004 aQute, All Rights Reserved slide #40
BundleBundle
Collaborative model
JAVA
Operating System
Hardware
OSGi Framework
Serviceregistry
packagespackages
©1999-2004 aQute, All Rights Reserved slide #41
Collaborative modelHow does OSGi relate to MIDP, Java TV, Browsers
JAVA
Operating System
Hardware
Java Application Manager
Serviceregistry
packagespackages
Midlet,Xlet,
orApplet
Midlet,Xlet,or
Applet
No native code
No package management(versions!)
No collaboration
No management bundles
©1999-2004 aQute, All Rights Reserved slide #42
Service Specifics
• A service (in the OSGi sense) is an object registered with the Framework for communicationwith other bundles
• The semantics and syntax of a service are specified in a Java interface
• Services can be seen as ports on the bundle
service
©1999-2004 aQute, All Rights Reserved slide #43
A Service Defined
Object that implements aJava Interface
register
get
get
get
events: REGISTERED, UNREGISTERING, MODIFIED
©1999-2004 aQute, All Rights Reserved slide #44
Real World Example
Third Party TeleHome Platform Gateway Client
T-Systems - TeleHome Overview
PRF
IDP
SERSER
JAAS
UMG
UIGECM-PRF
ERG SRM
SCALE SCALE
AUDAUD
USR
HMS
SNS
ACT
WMA
CAM
TXE
BUS
SUB
STK
RC
IR
USR
IR IR
TPAI
NOT
BUS
PRF
RC RC
PRF
NOT
SCN
SUB
ECM-PIM
BM MA
DM
ACT
DLC
BUS
CMD
LRD
FXE
PRF
HTM HTM
FNG
USBUSB
STK
FNG
VAP VAP
EHS
HMSD
CAD
HMS
WMA
DS DS
DS
SRMDATA
MDA MDA
ERG
FWUI
TIP6
SOAP
UIPROXY
HA
VOICE
PFW
ACC
PKI
PIM PIM
PSIPSIPInt
LOC
NBUNBU
PIM
STR
LOC
NBU
TIS
LOC
NBU
LOC
PIM
MAP
SIPExt
PMU
SMA
SOA
MSG MAILMSG VOICE HMS GSM
IDPSRV
ECM-RC
ECM-SUB
ECM-IRECM-
RLECM-NO
Bike
HomeTroinic
Camera
WashMachine
CM
IPD IPD
©1999-2004 aQute, All Rights Reserved slide #45
Services and Interfaces
Bundle
ServiceRegistry
listen “Display”
public void show(String msg) {
System.out.println(msg);
}
public void show(String msg) {
}
public void show(String msg) {
file.write(msg.getBytes());
}
B
C
regist
er “Disp
lay”
public interface Display {
void show(String msg);
}
A
©1999-2004 aQute, All Rights Reserved slide #46
Services continued
• Different bundles (from different vendors) can implement the same interface– Implementation is not visible to clients– Allows operator to replace implementations without
disrupting service
• Services are (optionally) registered with properties– Describe information about the service– The client can search (or listen) for services that have
certain properties and values for properties
• Standard properties– objectclass The interfaces of the service– service.id System generated unique id– service.pid Persistent id– service.ranking Ordering value
©1999-2004 aQute, All Rights Reserved slide #47
Services
• The service model enables a powerful component model
• Components can be plugged in, and removed, as needed
• The system adapts to these changing configurations
©1999-2004 aQute, All Rights Reserved slide #48
Services API
• Service objects should not be freely shared because of security and performance issues
• Therefore, services are normally manipulated with a ServiceReference object
• A ServiceReference can– Provide the properties of the
service– Be freely passed as a parameter
to other bundles– Can be used to retrieve the
actual service via the BundleContext, which might be personalized
ClientCode
ServiceReference
RealServiceObject
BundleContext
getService(ServiceReference)
getServiceReference(…)
©1999-2004 aQute, All Rights Reserved slide #49
How to get Services
• First is to obtain a Service Reference• Simplest way is the one that picks the highest ranking
service– ServiceReference getServiceReference(String ifName)
• The parameter is the name of the interface that is required– A good practice is to use MyClass.class.getName() instead of
“com.acme.mypackage.MyClass” because it will be automatically changed when you refactor
• The associated service is guaranteed to implement this interface (the package of the interface must be imported)
• Ranking is defined by properties– service.ranking– service.pid
©1999-2004 aQute, All Rights Reserved slide #50
Using getServiceReference
• A Service Reference is a handle to the service
• Example code• LogService log;
public void start(BundleContext context) throws Exception {ServiceReference ref = context.getServiceReference(
LogService.class.getClass() ); if ( ref != null ) { log = (LogService) context.getService(ref);}
©1999-2004 aQute, All Rights Reserved slide #51
Access to Service Reference Properties
• The Service Reference object holds a number of properties– Object getProperty(String key)– String [] getPropertyKeys()
• Properties can be any standard Java object, including arrays, vectors, arrays of primitives, etc.
• Filter searches expand arrays. – X = [“a”,”b”], matches (x=a) and (x=b)
• It is also possible to find all the keys– String[] getPropertyKeys();
©1999-2004 aQute, All Rights Reserved slide #52
Assignment
• Write a bundle that displays the Log Service properties on the console– Get the reference to the log service– Get the keys from this references– For each key
• Get the value• Print the key=value
• For nicety, printout arrays separately!
©1999-2004 aQute, All Rights Reserved slide #53
Access to the Associated Bundles
• Service References are associate with a registering bundle and a number of bundles that use it– Bundle getBundle();– Bundle[] getUsingBundles();
• Note null return for getUsingBundles()
BundleA
BundleB
BundleC
getUsingBundles
getBundle
©1999-2004 aQute, All Rights Reserved slide #54
Getting Services
• It is possible to get all Services– ServiceReference[] getServiceReferences(
String ifName, String filter)
• Note potential null return
• The ifName is the same as the previous but in this case it may be null
• The second parameter is a filter specification
• The filter syntax is of small expressive language that does an assertion on the properties
©1999-2004 aQute, All Rights Reserved slide #55
Filter Language
• The syntax is based on simple to parse, recursive structure
• Supported expressions– And “(&“ expr+ “)”– Or “(|” expr+ ”)”– Not “(!” expr+ “)”– Simple “(“ property-keyop literal “)”
©1999-2004 aQute, All Rights Reserved slide #56
Filter Syntax
• Operations– = equals (may contain ‘*’ for wildcards)– ~= looks like– >= Greater than or equal– <= Less than or equal– =* Is defined
• Examples– (vendor=*IBM*)– (&(service.pid=com.acme.bananas)(priority>=10))– (url=*)
©1999-2004 aQute, All Rights Reserved slide #57
getServiceReferences
• Example code
class MyService { void foo(); } public void start(BundleContext context) throws Exception { ServiceReference ref[] = context.getServiceReferences(
MyService.class.getName(), “(url=*)” ); for ( int i= 0; ref!= null && i<ref.length; i++ ) { MyService mys = context.getService(ref[i]); mys.foo(); } }
©1999-2004 aQute, All Rights Reserved slide #58
Assignment: Printout all services
• Create a bundle that prints out all the services that have the property “service.pid”
• Print:– Their properties – The bundle that registered it– The bundles that are using it
©1999-2004 aQute, All Rights Reserved slide #59
Registering a service
• There are two calls on the Bundle Context to register a service, both return a Service Registration object– ServiceRegistration registerService(String ifName,
Object service, Dictionary properties )– ServiceRegistration registerService(String ifNames[],
Object service, Dictionary properties )
• The ifName must match an interface on the service object
• The service is immediately available to other bundles
• The service can be unregistered with the unregister method on the Service Registration
• The properties of the service can also be changed with the setModified(Dictionary) call
©1999-2004 aQute, All Rights Reserved slide #60
Registering a Service
• import org.osgi.framework.*;• import org.osgi.service.cm.*;
• public class RegisterService implements BundleActivator {• class MyManagedService implements ManagedService {• public void updated(Dictionary properties)• throws ConfigurationException {• System.out.println("Updated " + properties);• }• }• public void start(BundleContext context) throws Exception {• System.out.println("Register Service Example");• Hashtable properties = new Hashtable();• properties.put("service.pid", "biz.aQute.ExamplePid");• ServiceRegistration reg =
context.registerService(ManagedService.class• .getName(), new MyManagedService(), properties);• }
• public void stop(BundleContext arg0) throws Exception {• }• }
©1999-2004 aQute, All Rights Reserved slide #61
Registering a Service
• In the monitor you can see the registration of the service
©1999-2004 aQute, All Rights Reserved slide #62
Listening to services
• It is possible to get notifications of– REGISTERED Service registrations– MODIFIED Service modifications– UNREGISTERED Service unregistrations
• All you have to do is add a listener to the BundleContext, there are 2 versions– addServiceListener(ServiceListener)– addServiceListener(ServiceListener,String filter)
• The second version allows to filter for only the services that are needed
• Service Listening is synchronous– Potential for deadlocks
©1999-2004 aQute, All Rights Reserved slide #63
Listening to Services
• public class ServiceListening implements BundleActivator, ServiceListener {
• public void serviceChanged(ServiceEvent event) {• String type = "UNKNOWN";• switch (event.getType()) {• case ServiceEvent.MODIFIED :type = "MODIFIED"; break;• case ServiceEvent.REGISTERED : type = "REGISTERED"; break;• case ServiceEvent.UNREGISTERING : type = "UNREGISTERING"; break;• }• ServiceReference ref = event.getServiceReference();• Long id = (Long) ref.getProperty("service.id");• String [] classes = (String[]) ref.getProperty("objectclass"); • System.out.println( "Service Event "+type + ":" + id + ":" + classes[0]);• }
• public void start(BundleContext context) throws Exception {• System.out.println("Listening to Services Example");• context.addServiceListener(this);• }
• public void stop(BundleContext arg0) throws Exception {• }• }
©1999-2004 aQute, All Rights Reserved slide #64
Assignment: Listenening
• Listen to service events
• Print them out
• Use the monitor to stop/start the bundles to see that they generate service events by registering and unregistering services
©1999-2004 aQute, All Rights Reserved slide #65
Service Registry
• The Framework Service Registry is available to all bundles to collaborate with other bundles
• Requires permission– Under Operator control
• Services are associated with properties– Query language to find appropriate service
• Bundles can update the properties
©1999-2004 aQute, All Rights Reserved slide #66
Service Factories
• How does a bundle customize a service per bundle?
• The ServiceFactory interface allows a bundle to return a specific customized service object for each bundle
• Framework calls back the factory for service get and unget methods
• The Framework keeps a reference count to the service
• Get and Unget will be perfectly matched
©1999-2004 aQute, All Rights Reserved slide #67
Service Factories
Framework BundleStandard
BundleFactory
Bundle A{ }
Bundle B{ }
©1999-2004 aQute, All Rights Reserved slide #68
Assignment: ServiceFactory
• Copy HelloWorld to ServiceFactoryExample• Register a ServiceFactory for a String object as
service type• Register it with the following attributes
– type=grabme– times=new Integer(5)
• Let the ServiceFactoryExample also implement the ServiceFactory interface
• Implement the getService(Bundle, ServiceRegistration) to return a unique string that also includes the calling bundle’s location
• Print out the get operation• Print out the unget operation
©1999-2004 aQute, All Rights Reserved slide #69
Create a test bundle
• Copy HelloWorld to Grabber• Listen to all services that have the property
– type=grabme
• If a REGISTERED event happens– Get the times propery (an Integer)– Get the service “times” times– Print out the service
• Copy hello.jardesc to grabber.jardesc• Copy Manifest.mf to grabber.mf• Modify the manifest to have the Bundle Activator point to the
Grabber• In the context menu of the grabber.jardesc file select “Open JAR
Packager”• Update the location of the jar descriptor file as well as the
manifest• Finish
©1999-2004 aQute, All Rights Reserved slide #70
Service Tracker
• Services register and unregister all the time
• Onus on the programmer to only use services that are registered
• ServiceTracker simplifies this task:– Maintains a list of active services– Events can be overridden in subclass
• Used in almost every bundle
©1999-2004 aQute, All Rights Reserved slide #71
Service Tracker
• Use "As is"
• Gets each service from the registry when it is available– Object getService()– Object[] getServices()– Object waitForService()
©1999-2004 aQute, All Rights Reserved slide #72
ServiceTracker
• Track all services of a certain type in the service registry
• Use subclassing a ServiceTracker or use the ServiceTrackerCustomizer interface
• Implement the methods:– Object addingService(ServiceReference r)– void modifiedService(ServiceReference r, Object
service)– void removedService(ServiceReference r, Object
service)
©1999-2004 aQute, All Rights Reserved slide #73
Create a service tracker
• A service tracker requires a Bundle Context • Notice that after creation, it needs to be opened
public void start(BundleContext context) throws Exception {System.out.println("ListServices");tracker = new ServiceTracker(
context,context.createFilter("(service.pid=*)"), null ) {public Object addingService(ServiceReference ref) {
printServiceReference(ref);return ref;
}public void removedService(ServiceReference ref, Object o)
{}
};tracker.open();
}
©1999-2004 aQute, All Rights Reserved slide #74
ServiceTracker: create
Framework BundleA
BundleB
BundleC
©1999-2004 aQute, All Rights Reserved slide #75
ServiceTracker: open
Framework BundleA
BundleB
BundleC
addServiceListener
Object addingService(ServiceReference r){…}
©1999-2004 aQute, All Rights Reserved slide #76
ServiceTracker: adding
Framework BundleA
BundleB
BundleC
addServiceListener
Object addingService(ServiceReference r){…}
©1999-2004 aQute, All Rights Reserved slide #77
ServiceTracker: removing
Framework BundleA
BundleB
BundleC
addServiceListener
void removedService(ServiceReference r,Objecto){…}
©1999-2004 aQute, All Rights Reserved slide #78
ServiceTracker: modified
Framework
BundleB
BundleC
addServiceListener
void modifiedService(ServiceReference r, Object o){…}
BundleA
ServiceTrackerList
©1999-2004 aQute, All Rights Reserved slide #79
Multiple constructors
• First is used to create a tracker on a specific interface– ServiceTracker( BundleContext, String, ServiceTrackerCustomizer)
• Second constructor is used to create a tracker with a filter
• Filters can be created with the BundleContext– ServiceTracker( BundleContext, Filter, ServiceTrackerCustomizer)
• Either constructor can use a ServiceTrackerCustomier
• When the customizer is null, the ServiceTracker will call the methods on itself, allowing subclassing
• The service tracker only becomes active after it is opened
• It should be closed in the stop() method
©1999-2004 aQute, All Rights Reserved slide #80
Assignment
• In a previous assignment we listed all the services that had a service.pid attribute
• Change this example to use a service tracker instead
©1999-2004 aQute, All Rights Reserved slide #81
Dependencies
• The Framework manages the dependencies between bundles
• Bundles that are installed and started will register services
• Framework will automatically unregister services when a bundle stops
• Event notifications for all important events
©1999-2004 aQute, All Rights Reserved slide #82
Dependencies
Framework
Bundle C{ }
Bundle A{ }
Bundle B{ }
Install A
start
events: install
events: register
©1999-2004 aQute, All Rights Reserved slide #83
Framework
Dependencies
Bundle C{ }
Bundle B{ }
Uninstallstop
events: uninstall
events: unregister
Bundle A{ }
©1999-2004 aQute, All Rights Reserved slide #84
Dependency Management
• When a bundle stops, it is cleaned up– Registered services are removed – References to other services removed
• Bundles can be notified when a service they depend on is unregistered
• Class path dependencies are managed
• Model allows long running applications with dynamic software updates
©1999-2004 aQute, All Rights Reserved slide #85
How To Use The Registry
• The Framework handles dependencies, but not all!
• Don’t call us, we'll call you! Is Better.– Also know as the White Board approach
• Clients should register their objects, not the Servers. This is not intuitive!
• Significantly simplifies programming, therefore strongly advised
©1999-2004 aQute, All Rights Reserved slide #86
White Board Approach
• See whitepaper: "Listeners Are Considered Harmful"
Framework
Client
Server
Client
Server
Add listener
©1999-2004 aQute, All Rights Reserved slide #87
White Board Approach
RegistryBundle A
{ }
registerWAP
bundle
Events: register, unregister
Bundle C{ }
Bundle B{ }
Publisherget
©1999-2004 aQute, All Rights Reserved slide #88
Threads
• Many tasks need to be done in a background thread– IO– Time related
• Threads cannot be stopped in Java– Some communication is used to request to stop them– A flag is reset– The thread is interrupted– Any IO channels are closed
• The continuous running model of OSGi requires that the threads remain alive, even when there are failures
• Failure handling must be careful not to overload the system
©1999-2004 aQute, All Rights Reserved slide #89
Typical thread loop
©1999-2004 aQute, All Rights Reserved slide #90
Assignment
• Write an application that sends out alive message on the network with UDP– Use your IP address as unique identifier
• Listen to the alive messages and register an Alive service for each station that has been discovered this way
• Unregister the service when no message has been received in 1 minute
• Make
©1999-2004 aQute, All Rights Reserved slide #91
Native Code
• Native code allows a bundle to carry non-java code for different operation systems
• If a bundle has a Bundle-NativeCode manifest header, the bundle should contain native code libraries that must be available for the bundle to execute.
• When a bundle makes a request to load a native code library, the findLibrary method of the caller's classloader must be called to return the file path name in which the Framework has made the requested native library available.
• The bundle must have the required RuntimePermission[loadLibrary.< library name>] in order to load native code in the OSGi Service Platform.
©1999-2004 aQute, All Rights Reserved slide #92
Native Code
• The Bundle-NativeCode manifest header must conform to the following syntax: – Bundle-NativeCode ::= nativecode-clause ( ’,’
nativecode-clause ) * – nativecode-clause ::= nativepaths ( ’;’ env-parameter
)*– Nativepaths ::= jar-path ( ’;’ jar-path )*– env-parameter ::= (processordef | osnamedef |
osversiondef | languagedef )– Processordef ::= ’processor’ ’=’ value– osnamedef ::= ’osname’ ’=’ value– osversiondef ::= ’osversion’ ’=’ value – Languagedef ::= ’language’ ’=’ value – value ::= token | quoted-string
©1999-2004 aQute, All Rights Reserved slide #93
Native Code
• The following is a typical example of a native code declaration in a bundle’s manifest:
• Bundle-NativeCode: /lib/http.DLL ;/lib/zlib.dll ;
osname = Windows95 ;osname = Windows98 ;osname = WindowsNT ;processor = x86 ;language = en ;language = se ,
/lib/solaris/libhttp.so ; osname = Solaris ; osname = SunOS ; processor = sparc,
/lib/linux/libhttp.so ; osname = Linux ; processor = “mips”
©1999-2004 aQute, All Rights Reserved slide #94
Native Code
• If a Bundle-NativeCode clause contains duplicate env-parameter entries, the corresponding values must be OR’ed together. This feature must be carefully used because the result is not always obvious. This is highlighted by the following example:
// The effect of this header
// is probably not the intended effect!
Bundle-NativeCode: /lib/http.DLL ;osname = Windows95 ;
osversion = 3.1 ;
osname = WindowsXP ;
osversion = 5.1
©1999-2004 aQute, All Rights Reserved slide #95
Native Code
• The previous example implies that the native library will load on Windows XP 3.1 and later, which was probably not intended. The single clause should be split up when the expected effect is desired:
Bundle-NativeCode: /lib/http.DLL ;osname = Windows95 ;
osversion = 3.1,
/lib/http.DLL ;
osname= WindowsXP ;
osversion = 5.1
• If multiple native code libraries need to be installed on one platform, they must be specified in the same clause for that platform.
©1999-2004 aQute, All Rights Reserved slide #96
Native Code: Use Table
OS Name Version Processor Language Filter Libs
win32 x86 en nativecodewin32.dll, nativecode1win32.dll
linux x86 en (org.osgi.framework.windowing.systems=gtk)
nativecodegtk.so
linux x86 en (org.osgi.framework.windowing.system=qt)
nativecodeqt.so
©1999-2004 aQute, All Rights Reserved slide #97
Native Code
Bundle-NativeCode nativecodewin32.dll;nativecode1win32.dll;processor=x86;osname=win32;language=en,nativecodegtk.so;processor=x86;osname=linux;selection-filter =
“(org.osgi.framework.windowing.system = gtk)”;
language=en,nativecodeqt.so;processor=x86;osname=linux;selection-filter =
“(org.osgi.framework.windowing.system = qt)”;
language=en
If the native code algorithm fails to select a native code clause from the Bundle-NativeCode header, the bundle will fail to install and a BundleException will be thrown.
The selection filter is used to select the appropriate clause based upon the windowing system.
©1999-2004 aQute, All Rights Reserved slide #98
aQute
www.aQute.biz
+15123514821, [email protected]
z