Post on 27-Mar-2015
OSGi World CongressOSGi World CongressWorkshop ExerciseWorkshop Exercise
By Peter KriensBy Peter Kriens
CEO aQuteCEO aQute
OSGi Technology OfficerOSGi Technology Officer
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 22
Functional Description Functional Description ProgramProgram
““See your buddies” web page viewerSee your buddies” web page viewer At the end, each participant adds a At the end, each participant adds a
web page to the portal of all other web page to the portal of all other participantsparticipants
Zero Administration …Zero Administration …
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 33
ArchitectureArchitecture
app2
app3 app1
app4
Browser
app 1app 2app 3app 4
SP 2
SP 3
SP 4
SP 1
multicast
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 44
Architecture: ClassesArchitecture: Classes
ActivatorDistributor
Link
HttpTrackerTracks httpservers
findsbuddies
<<interface>>Http Service
ServiceTracker
Thread<<interface>>BundleActivator
Tracks buddies Registers page
Portal Tracks portal entries
Registers /portal page
LogService
Logs messages
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 55
Start: Hello WorldStart: Hello World
Activator
The Activator class will print “Hello The Activator class will print “Hello World” when the bundle is started World” when the bundle is started and “Goodbye World” when it stops.and “Goodbye World” when it stops.
<<interface>>BundleActivator
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 66
Getting StartedGetting Started
AssumptionsAssumptions– Eclipse 2.0.1 (check in Help:About, 2.0.0 Eclipse 2.0.1 (check in Help:About, 2.0.0
does not work!) installeddoes not work!) installed– unzipped fwx.zipunzipped fwx.zip
fwx.exefwx.exe load directoryload directory osgi.jarosgi.jar servlet.jarservlet.jar
– Started EclipseStarted Eclipse
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 77
EclipseEclipse
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 88
Getting StartedGetting Started
Create new Java ProjectCreate new Java Project– File:New:ProjectFile:New:Project– Java Project, NextJava Project, Next– Name is “ws”Name is “ws”– Default location, NextDefault location, Next– Libraries, Add external jars, Libraries, Add external jars,
servlet.jar, osgi.jar servlet.jar, osgi.jar (from where you unzipped fwx.zip, e.g. c:\fwx\(from where you unzipped fwx.zip, e.g. c:\fwx\osgi.jar)osgi.jar)
– Attach source (select osgi.jar), FinishAttach source (select osgi.jar), Finish
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 99
Add External JarAdd External Jar
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 1010
Setup Activator classSetup Activator class
Add PackageAdd Package– File:New:PackageFile:New:Package– Name, aQute.world.congressName, aQute.world.congress
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 1111
Setup Activator classSetup Activator class
Add new classAdd new class File:New:ClassFile:New:Class
– Package, aQute.world.congressPackage, aQute.world.congress– Name, ActivatorName, Activator– InterfacesInterfaces
Add BundleActivatorAdd BundleActivator
FinishFinish Eclipse will open a generated Eclipse will open a generated
source filesource file
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 1212
Activator class setupActivator class setup
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 1313
Write Hello/Goodbye Write Hello/Goodbye WorldWorld
Fill in the System.out.println(“...”) in Fill in the System.out.println(“...”) in the appropriate placesthe appropriate places
Save the file (File:Save or control-S)Save the file (File:Save or control-S)– This automatically compiles, so correct This automatically compiles, so correct
any errorsany errors
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 1414
Create The ManifestCreate The Manifest
We only define what class to start: We only define what class to start: ActivatorActivator
File:New:File, name it Manifest.mf File:New:File, name it Manifest.mf – Store in aQute.world.congress package/dirStore in aQute.world.congress package/dir
Manifest MUST end with 2 empty lines!!Manifest MUST end with 2 empty lines!! Fill in (and save):Fill in (and save):
Manifest-Version: 1.0 Bundle-Activator: aQute.world.congress.Activator Import-Package: org.osgi.framework
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 1515
Create ManifestCreate Manifest
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 1616
Create Bundle JAR file!Create Bundle JAR file!
Select “ws” in left paneSelect “ws” in left pane Press right mouse buttonPress right mouse button Select ExportSelect Export Select JAR FileSelect JAR File NextNext
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 1717
Create JAR FileCreate JAR File
Export DestinationExport Destination– Name it ws.jarName it ws.jar– Save the JAR in the load directorySave the JAR in the load directory
where you unzipped fwx.zip,where you unzipped fwx.zip,e.g. c:\fwx\loade.g. c:\fwx\load
NextNext
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 1818
Create JAR fileCreate JAR file
Deselect “with compile Deselect “with compile errors”errors”
Save the description in theSave the description in the“ws” workspace, under the“ws” workspace, under thename bundle.jardescname bundle.jardesc
NextNext
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 1919
Create JAR fileCreate JAR file
Set to use existing ManifestSet to use existing Manifest– Select Manifest.mfSelect Manifest.mf
FinishFinish
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 2020
Starting A FrameworkStarting A Framework
The fwx.exe is the OSGi Reference Framework The fwx.exe is the OSGi Reference Framework with all the R2 services reference with all the R2 services reference implementationsimplementations– This Framework is not optimized, nor industrializedThis Framework is not optimized, nor industrialized– It expires December 1It expires December 1– Contact a vendor for a real frameworkContact a vendor for a real framework
To start it, open a window on its directory and To start it, open a window on its directory and double click itdouble click it
It will automatically start all bundles in the load It will automatically start all bundles in the load directorydirectory
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 2121
Starting the FrameworkStarting the Framework
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 2222
RestartingRestarting
You can restart the bundle by You can restart the bundle by – select the bundle.jardescselect the bundle.jardesc– Right mouse: Create JarRight mouse: Create Jar
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 2323
Using The Log ServiceUsing The Log Service
Activator
We will now use a service: The Log We will now use a service: The Log ServiceService
<<interface>>BundleActivator
LogService
Logs messages
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 2424
Prepare for the Log Prepare for the Log ServiceService
Save the BundleContext parameter Save the BundleContext parameter in a context instance variablein a context instance variable
BundleContext context; public void start(BundleContext context) {
this.context = context; ...}
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 2525
The log() methodThe log() method
Add a new method to the Activator Add a new method to the Activator class: class: void log( String msg, Throwable exception ) {
ServiceReference r = context.getServiceReference( LogService.class.getName() ); LogService log =(LogService)context.getService(r); if ( log != null ) { if ( exception == null ) log.log( LogService.LOG_INFO, msg ); else log.log( LogService.LOG_ERROR, msg, exception ); } else System.out.println( msg + " : " + exception ); context.ungetService( r );}
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 2626
Use the log methodUse the log method
Replace the calls to System.out with Replace the calls to System.out with calls to the log methodcalls to the log method
public void start(BundleContext context) { this.context = context; log( "Hello world", null );}public void stop(BundleContext context){ log( "Goodbye world", null );}
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 2727
Organize ImportsOrganize Imports
Source:Organizer ImportsSource:Organizer Imports This will automatically add the This will automatically add the
necessary import statementsnecessary import statements
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 2828
Modify The ManifestModify The Manifest
Edit Manifest.mfEdit Manifest.mf Add Import-Package forAdd Import-Package for
– org.osgi.service.logorg.osgi.service.logManifest-Version: 1.0Bundle-Activator: aQute.world.congress.ActivatorImport-Package: org.osgi.framework, org.osgi.service.log
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 2929
Using the Log ServiceUsing the Log Service
Save the source file (correct compile Save the source file (correct compile errors)errors)
Select bundle.jardesc, right menu, Select bundle.jardesc, right menu, Create JARCreate JAR
Check the console of fwx:Check the console of fwx:– Goodbye worldGoodbye world– But no Hello world … This is now in the logBut no Hello world … This is now in the log– Where is the log????Where is the log????
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 3030
Reading the Log ServiceReading the Log Service
Open a telnet sessionOpen a telnet session– Start:Run:telnet localhost 2011Start:Run:telnet localhost 2011
This opens a simple OSGi This opens a simple OSGi console/debuggerconsole/debugger
TypeType– loglog
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 3131
Publishing a pagePublishing a page
HttpTrackerTracks httpservers
<<interface>>Http Service
ServiceTracker
Registers page
Portal
Registers /portal page
Activator
<<interface>>BundleActivator
LogService
Logs messages
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 3232
Write An Html PageWrite An Html Page File:New:FileFile:New:File
– Directory, aQute/world/congressDirectory, aQute/world/congress– Call it page.htmlCall it page.html
Edit it (select page.html, Open With:Text Editor)Edit it (select page.html, Open With:Text Editor)
<html> <head> <title>My Demo HTML page</title> </head> <body> <h1>My Demo</h1> This is aQute's (use your own name!) demo page </body></html>
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 3333
Create an HTML fileCreate an HTML file
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 3434
Create HttpTrackerCreate HttpTracker
HttpTracker tracks Http Service objects and HttpTracker tracks Http Service objects and adds a “page.html” to every Http Serviceadds a “page.html” to every Http Service
It extends ServiceTracker to simplify trackingIt extends ServiceTracker to simplify tracking– Object addingService(ServiceReference)Object addingService(ServiceReference)– void modifiedService(ServiceReference,Object)void modifiedService(ServiceReference,Object)– void removedService(ServiceReference,Object)void removedService(ServiceReference,Object)
Create new class Create new class aQute.world.congress.HttpTracker that aQute.world.congress.HttpTracker that extends ServiceTracker, implements extends ServiceTracker, implements HttpContextHttpContext
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 3535
Add HttpTracker classAdd HttpTracker class
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 3636
Add HttpTracker classAdd HttpTracker class
And it needs a variable, constructor, And it needs a variable, constructor, add:add:Activator activator;
public HttpTracker( Activator activator, BundleContext context ) { super( context, HttpService.class.getName(),null); this.activator = activator;}
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 3737
Add HttpTracker classAdd HttpTracker class
addingServiceaddingService
public Object addingService( ServiceReference reference ) { HttpService http = (HttpService)super.addingService(reference); try { http.registerResources("/mydemo", "", this ); } catch( NamespaceException e ) { activator.log( "Cannot register because “
+ “name is already in use /mydemo", e ); } return http;}
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 3838
Add HttpTracker classAdd HttpTracker class
Modify the getResource method to Modify the getResource method to return resources from the packagereturn resources from the package
public URL getResource(String name) { try { URL url = getClass().getResource( name.substring(1) ); return url; } catch( Exception e ) { e.printStackTrace(); } return null;}
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 3939
Add HttpTracker classAdd HttpTracker class
handlSecurity returns false. This handlSecurity returns false. This means deny access, change it to means deny access, change it to return true.return true.public boolean handleSecurity(
HttpServletRequest request, HttpServletResponse response) throws IOException { return true;}
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 4040
Add HttpTracker classAdd HttpTracker class
Organize ImportsOrganize Imports Save itSave it Add an instance variable for the Http Add an instance variable for the Http
Tracker to ActivatorTracker to Activator
And add the following line to the And add the following line to the start method start method http = new HttpTracker( this, context );
http.open();
HttpTracker http;
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 4141
Clean-upClean-up
// Add to stop methodhttp.close();
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 4242
Modify The ManifestModify The Manifest
Add Import-Package forAdd Import-Package for– org.osgi.util.trackerorg.osgi.util.tracker– org.osgi.service.httporg.osgi.service.http– javax.servlet.http, javax.servletjavax.servlet.http, javax.servlet
Manifest-Version: 1.0Bundle-Activator: aQute.world.congress.ActivatorImport-Package: org.osgi.framework, org.osgi.service.log,org.osgi.util.tracker, org.osgi.service.http,javax.servlet.http, javax.servlet
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 4343
Add HttpTracker classAdd HttpTracker class
Save open filesSave open files Select bundle.jardescSelect bundle.jardesc
– Create JARCreate JAR Open a browser and surf intoOpen a browser and surf into
– http://localhost/mydemo/page.htmlhttp://localhost/mydemo/page.html Ensure that your HTTP proxy is off!Ensure that your HTTP proxy is off!
– IE : Tools : Internet Options : IE : Tools : Internet Options : Connections : Lan settings Connections : Lan settings
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 4444
Finding Your BuddiesFinding Your Buddies
HttpTrackerTracks httpservers
<<interface>>Http Service
ServiceTracker
Registers page
Portal
Registers /portal page
Activator
<<interface>>BundleActivator
LogService
Logs messages
Distributor
Link
findsbuddies
Thread
Tracks buddies
Tracks portal entries
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 4545
Add Distributor classAdd Distributor class
Add a new class DistribitorAdd a new class Distribitor– Package aQute.world.congressPackage aQute.world.congress– Extends ThreadExtends Thread
This class will open a UDP socketThis class will open a UDP socket Will listen to all Datagram’s on port 2014Will listen to all Datagram’s on port 2014 Forwards all datagrams to the activatorForwards all datagrams to the activator Sends an announce datagram every 5 secondsSends an announce datagram every 5 seconds Simple mechanism to dynamically discover Simple mechanism to dynamically discover
othersothers
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 4646
Add Distributor classAdd Distributor class
Add Instance variable declarationsAdd Instance variable declarations
boolean active = true;DatagramSocket socket;byte outgoing[];Activator activator;
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 4747
Add Distribitor classAdd Distribitor class
Add ConstructorAdd Constructor
Distributor( Activator activator, String outgoing ) { super("distributor"); this.activator = activator; this.outgoing = outgoing.getBytes();}
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 4848
Add Distribitor classAdd Distribitor classpublic void run() { while ( active ) try { socket = new DatagramSocket( 2014 ); socket.setSoTimeout( 5000 ); activator.log("Discovery starts.", null); … inner loop … see next slide socket.close(); socket = null; } catch(Exception e) { activator.log( "Main discover loop exit", e ); if ( active ) try { Thread.currentThread().sleep(1000); } catch( Exception x) {} } activator.log("Discovery quits.", null);}
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 4949
Add Distribitor classAdd Distribitor classwhile ( active ) try { DatagramPacket packet = new DatagramPacket(new byte[256], 256); socket.receive(packet); String incoming = new String( packet.getData(), 0, packet.getLength()); activator.process( new Link(incoming) ); }catch(InterruptedIOException e) { announce();} catch(Exception e) { if ( active ) activator.log( "Receving remote “
+ “service packets, ignoring ", e );}
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 5050
Add Distribitor classAdd Distribitor class
The announce methodThe announce method
void announce() throws IOException { DatagramSocket announce = new DatagramSocket(); DatagramPacket packet = new DatagramPacket( outgoing, outgoing.length, InetAddress.getByName("255.255.255.255"), 2014 ); announce.send(packet); }
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 5151
Add Distribitor classAdd Distribitor class
And the last close methodAnd the last close method
Organize importsOrganize imports SaveSave
– Unresolved method in Activator: processUnresolved method in Activator: process
void close() { active = false; socket.close();}
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 5252
Add Link classAdd Link class
Add linke classAdd linke class The link class just holds the buddy The link class just holds the buddy
info together.info together.Hashtable properties = new Hashtable();ServiceRegistration registration;
Link( String msg ) { StringTokenizer tz =
new StringTokenizer( msg, "|" ); properties.put( "title", tz.nextToken() ); properties.put( "description",tz.nextToken()); properties.put( "url", tz.nextToken() ); }
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 5353
Add Link classAdd Link class
Register method, for a new discovered Register method, for a new discovered buddybuddy
Modify method, when old buddy, new Modify method, when old buddy, new messagemessage
void register( BundleContext context ) { registration = context.registerService( Link.class.getName(), this, properties );}
void modify( Link link ) { registration.setProperties(link.properties);}
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 5454
Add Link classAdd Link class
Unregister when link is goneUnregister when link is gone
To get the unique key To get the unique key
void unregister() { registration.unregister();}
Object getUrl(){ return properties.get( "url" ); }
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 5555
Add process method in Add process method in ActivatorActivator
The process method must add buddy The process method must add buddy to the portalto the portal
The portal tracks “url” service The portal tracks “url” service property.property.
Edit Activator, add process methodEdit Activator, add process methodHashtable links = new Hashtable();void process( Link link ) { Link existing = (Link) links.get( link.getUrl() ); if ( existing != null ) existing.modify( link ); else { link.register( context ); links.put( link.getUrl(), link ); existing = link; }}
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 5656
Add and Start the Add and Start the DistributorDistributor
// Add to start methodString host= InetAddress.getLocalHost().getHostAddress();if ( System.getProperty(
"org.osgi.service.http.port" ) != null )host += ":" + System.getProperty(
"org.osgi.service.http.port" );
distributor = new Distributor( this, "My Title|My Own Description|http://" + host + "/mydemo/page.html"
);distributor.start();
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 5757
Clean-up (stop method)Clean-up (stop method)
// Add to stop methoddistributor.close();
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 5858
Find the buddiesFind the buddies
Organize imports for all filesOrganize imports for all files Build JARBuild JAR Browse to:Browse to:
– http://localhost/portalhttp://localhost/portal You should see your own page, and You should see your own page, and
with any luck pages from your with any luck pages from your buddiesbuddies
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 5959
Advanced ExerciseAdvanced Exercise
Links are not cleaned up when the Links are not cleaned up when the buddy stops sendingbuddy stops sending
Cleanup the links when no message Cleanup the links when no message has been received for 30 secondshas been received for 30 seconds
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 6060
ConclusionConclusion
Surprisingly little code is necessary to Surprisingly little code is necessary to perform interesting functionsperform interesting functions
Coupling to other parts is minimal Coupling to other parts is minimal because OSGi specified interfaces are because OSGi specified interfaces are intermediatesintermediates
Tools are available to simplify Tools are available to simplify creation of manifest and bundle filescreation of manifest and bundle files
This is only the beginning ...This is only the beginning ...
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 6161
Vendors With Tools & Vendors With Tools & CoursesCourses
Acunia - www.acunia.comAcunia - www.acunia.com aQute - www.aQute.seaQute - www.aQute.se IBM - www.ibm.com/embeddedIBM - www.ibm.com/embedded Gatespace - www.gatespace.comGatespace - www.gatespace.com ProSyst - www.prosyst.comProSyst - www.prosyst.com
See for more www.osgi.org See for more www.osgi.org
www.aQute.sewww.aQute.se - 2002 OSGi World - 2002 OSGi World Congress - Congress - 6262
aQute
www.aQute.se
+46 300 39800, Peter.Kriens@aQute.s
e