tutorial 1

33 %
67 %
Information about tutorial 1

Published on September 19, 2007

Author: Haggrid



OSGi Introductory Tutorial:  OSGi Introductory Tutorial Peter Kriens, aQute aQute – Software Consultancy:  aQute – Software Consultancy This tutorial is originally designed to be given by a tutor, it is not optimized to run this on your own. This does not mean that with a bit of motivation you can learn a lot from it. However, a real tutorial with a presenter is much more fun. Not in the least of what you can learn from your collegues. You can hire to organize such a workshop or you can attend one of the many workshops that are organized on conferences. Please consult the website for the current program or go to Have fun! Feedback appreciated. Slide3:  Copyright is held by the OSGi Alliance, IBM and aQute SARL This presentation is made available under the EPL v1.0 OSGi Component Programming:  OSGi Component Programming Peter Kriens OSGi Technical Director OSGi Evangelist CEO aQute Content:  Content Section I – Setting Up Eclipse and the OSGi Platform Section II – OSGi Background Section III – OSGi Technology Section IV – Fundamental OSGi Concepts Section V – Component Interaction and Collaboration Section VI – Service Components Section VII – Use Case: Developing a Chat Service Section VIII – Service Tracking Section IX – Finishing Touch Section XI – Final Section I – Setting up Eclipse and the OSGi Platform:  Section I – Setting up Eclipse and the OSGi Platform Setup: A Clean Workspace in Eclipse:  Setup: A Clean Workspace in Eclipse Setup: Your Infrastructure:  Setup: Your Infrastructure You need to have the following software installed on your machine in a new workspace: Latest Eclipse SDK (3.2 or 3.3) ( The ( Unzip this file and import it as a project. The bnd plugin, download the latest version from All examples are available as bundles and can also be installed from This tutorial assumes the PC for user interface interactions. You must translate this to your environment if you run Linux or have a Mac Install the bnd Plugin:  Install the bnd Plugin Copy in the OS the bnd.jar file to your eclipse/plugin directory related to your running eclipse.exe. The bnd.jar file resides in the aQute.tutorial.runtime project in the jar directory Copy this from your operating system Exit Eclipse and restart  Verify: Help andgt; About andgt; Plugin Details Check for 'aQute Bundle Tool' The bnd bundle/plugin provides a convenient way to make bundles. It adds a menu to files that have a '.bnd' extension The bnd file contains all the information a requires, it calculates defaults for undefined information The bnd.jar is also usable as a command line option For more documentation, Section II - OSGi Background:  Section II - OSGi Background What is the OSGi Service Platform?:  What is the OSGi Service Platform? A Java framework for developing (remotely) deployed service applications, that require: Reliability Large scale distribution Wide range of devices Collaborative Created through a collaboration of industry leaders IBM, Ericsson, Nokia, Sony, Telcordia, Samsung, ProSyst, Gatespace, BenQ, Nortel, Oracle, Sybase, Espial, and many more Spec 4.0 publicly available at … Cool! Why the OSGi Service Platform?:  Why the OSGi Service Platform? What problems does the OSGi Service Platform address? The limited (binary) software portability problem The complexity of building heterogeneous software systems Supporting the myriad of configuration, variations, and customizations required by today’s devices Managing the software on the device Problems: Limited Binary Software Portability:  Problems: Limited Binary Software Portability Lack of portability causes Market friction: No large market of reusable components and applications Reduced quality Unnecessary constraints on hardware and software architectures CPUs differ widely in cost and performance Linux is nice, but it is sub-optimal for smaller devices Benefits of the OSGi Platform Applications run unmodified on different hardware and software architectures due to a formal specification of all relevant aspects The OSGi Specifications gives you choice! Problems: Complexity of Software:  Problems: Complexity of Software Productivity Complexity and Size Problems: Limits of Object Oriented Technology:  Problems: Limits of Object Oriented Technology Objects are great, but oh, the tangled webs we weaves … Coupling severely limits reusability Using a generic object, can drag in a large number of other objects Creates overly large systems after a certain complexity is reached Flexibility must be built in by the programmer Plug-in architectures Component architectures like OSGi minimize the coupling that is created by OO Section III - OSGi Technology:  Section III - OSGi Technology The OSGi Framework Architecture:  The OSGi Framework Architecture Allows applications to share a single Java VM Handles all class loading in a much better defined way than standard Java Versioning! Gives isolation/security between applications Mediates between communication andamp; collaborations between applications Provides life cycle management (install, start, stop, update, etc). Policy free Policies are provided by bundles The OSGi Platform is a Service Oriented Architectures (SOA):  The OSGi Platform is a Service Oriented Architectures (SOA) Separate the contract from the implementation Allows alternate implementations Dynamically discover and bind available implementations Binding based on contract (interface definitions) Components are reusable Components are not coupled to implementation details of other components, only their independent interfaces have to be known Service Contract Component provides uses OSGi Service Platform Layering:  OSGi Service Platform Layering The OSGi Service Platform is divided in a number of layers Execution Environment provides a defined context for applications The Module layer provides class loading and packaging specifications The Services layer provides a collaboration model The extensive Security layer is embedded in all layers Module Life Cycle Services Security Execution Environment Applications Layers: OSGi Execution Environment:  Layers: OSGi Execution Environment Define the class library available from the VM java.* classes Additional constraints OSGi APIs use only a subset of Sun’s J2SE and J2ME CDC/CLDC OSGi Minimum EE Matches most Java profiles Implementations can use more than the OSGi Minimum EE Security is not mandatory CLDC is possible if class loaders are added in a device specific way CLDC/ MIDP J2SE CDC/FP OSGi Min. Layers: OSGi Module Layer:  Layers: OSGi Module Layer Packaging of applications and libraries in Bundles Java has significant deployment issues Class Loading modularization Java provides the Class Path as an ordered search list, which makes it hard to control multiple applications Protection Java can not protect certain packages and classes from others Versioning Java can not handle multiple versions of the same package in a VM bundle bundle bundle bundle bundle bundle bundle Layers: OSGi Life Cycle Layer:  Layers: OSGi Life Cycle Layer System Bundle represents the OSGi Framework Provides an API for managing bundles Install Resolve Start Stop Refresh Update Uninstall Bundle X Bundle X-v2 Bundle B Bundle M Bundle A System bundle State (active or not) Manages Layers: OSGi Life Cycle Layer:  Layers: OSGi Life Cycle Layer Bundle is started by the Bundle Activator class Header in the JAR manifest file refer to this class Bundle Activator interface has 2 methods Start: Initialize and return immediate Stop: Cleanup The Bundle Activator gets a Bundle Context that provides access to the OSGi Framework functions The Framework provides the Start Level service to control the start/stop of groups of applications INSTALLED RESOLVED UNINSTALLED ACTIVE STOPPING STARTING start stop Layers: OSGi Service Layer:  Layers: OSGi Service Layer Provides an inside-VM service model Discover (and get notified about) services based on their interface or properties, no protocol required Bind to one or more services by program control, default rules, or deployment configuration Service Oriented Architectures (SOA) Confusion Web services bind and discover over the net The OSGi Service Platform binds and discovers inside a Java VM The OSGi Alliance provides many standardized services Layers: The OSGi Service Layer Evolution:  Layers: The OSGi Service Layer Evolution UPnP Initial Provisioning Name Space Jini Start Level IO Connector Wire Admin XML Parser Measurement andamp; State Position Execution Env. Application Manager Foreign App. Access Signed Bundles Declarative Services Device Management Security Policies Framework Layering Initial Provisioning UPnP Conditional Permissions … 2000 2001 2003 2006 R1 R2 R3 R4 Home Automation Vehicle Mobile Framework Http Log Device Access Package Admin Configuration Admin Permission Admin User Admin Preferences MetaType Service Tracker R5 Layers: The Security Layer:  Layers: The Security Layer The OSGi Service Platform can be configured to be one of the most secure execution environments The security model is dynamic, unlike normal Java Fully under control of the operator Fully controlled systems Walled gardens Fully open systems Based on Java 2 security Permissions Bundle signing A number of extra rules to increase the overall system security The OSGi Implementations:  The OSGi Implementations Major Framework vendors are ProSyst, Gatespace Telematics, and IBM Siemens Espial Open source implementations Apache Felix Eclipse Equinox Gatespace Knopflerfish See for an overview Benefits of the OSGi Service Platform:  Benefits of the OSGi Service Platform Components are smaller Easier to make Components are minimally coupled to other components Gives reusability Collaborative model Allows reuse of other components for most problems Wide Adoption Bigger market, more components available Excellent model for the myriad of customizations and variation that are required of today’s devices What Did We Learn:  What Did We Learn The OSGi Service Platform is kind of a Java Operating System Execution Environment Module layer Service Layer Security It simplifies: Deployment Problems Software composition Software management The OSGi technologies are implemented by many vendors and open source groups. Section IV - Fundamental OSGi concepts:  Section IV - Fundamental OSGi concepts Framework Entities :  Framework Entities OSGi Framework Bundle A {…} = service, defined by java interface Bundle B {…} Bundle C {…} = bundle Bundles:  Bundles A bundle is the deliverable application Like a Windows EXE file Content is a JAR file A bundle registers zero or more services A service is specified in a Java interface and may be implemented by multiple bundles Services are bound to the bundle life-cycle Searches can be used to find services registered by other bundles Query language Bundle A {…} Bundle B {…} What is in a Bundle?:  What is in a Bundle? A Bundle contains (normally in a JAR file): Manifest (bundle meta data) Code (classes in packages) Resources (other files in the JAR file) The Framework: Reads the bundle’s manifest Installs the code and resources Resolves dependencies Controls the bundle life cycle During Runtime: Calls the Bundle Activator to start the bundle Manages java class path for the bundle as a network of class loaders Handles the service dependencies Calls the Bundle Activator to stop the bundle Cleans up after the bundle Bundle A {…} Create a Hello (and Goodbye) World Bundle:  Create a Hello (and Goodbye) World Bundle * andgt; New andgt; Project Java Project andgt; Next Fill in the information, defaults are likely to be ok. As name you can use, then andgt; Next For each tab: Source, just info Projects, for dependent projects. We have none now In Libraries andgt; Add JARs, add a JAR from project aQute.tutorial.runtime, directory work/osgi.jar. This Provides the OSGi interfaces on the class path for the bundle andgt; Finish Create a Hello (and Goodbye) World Bundle:  Create a Hello (and Goodbye) World Bundle Create a Hello (and Goodbye) World Bundle:  Create a Hello (and Goodbye) World Bundle Create a Java source called Select src folder * andgt; New andgt; Class Set the package to something like Add the BundleActivator interface to the Interfaces list box. Check the 'Inherited abstract methods' checkbox, this will generate the start and stop methods for the BundleActivor interface The remaining examples use the package names of the provided source code, no longer You should choose your own naming to not conflict with the provided source code. Source code for Hello/Goodbye World:  Source code for Hello/Goodbye World The source should look similar to the source placed adjacent We have to fill in the // TODO blocks start – Called when the bundle is started stop – When the bundle is stopped (no guarantee though!) Some tips F3 andgt; Will jump to the selected type (try, click BundleActivator, and then F3) Control-Shift-T andgt; Will show a source of a type (class) Control-Shift-R andgt; Will show a source of a resource (not a class) package; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; public class Activator implements BundleActivator { public void start(BundleContext context) throws Exception { // TODO Auto-generated method stub } public void stop(BundleContext context) throws Exception { // TODO Auto-generated method stub } } Manifest code for Hello/Goodbye World:  Manifest code for Hello/Goodbye World Each JAR file has a manifest Basic format of the manifest is defined by Sun A manifest is a text file that provides meta information about the JAR file. Used for versioning and JAR file signing. A manifest consists of a set of headers and values. For example, Manifest-Version: 1 Unrecognized headers are ignored by the Java VM, this makes it possible to extend the manifest The OSGi specifications have declared manydifferent headers Vendor information Imported and Exported packages Native code … Real code! Hello World (and Goodbye):  Real code! Hello World (and Goodbye) A bundle needs a manifest. The bnd plugin can create this for you (and verify its headers for validity!) You have to create a bnd file in the project directory. * andgt; New andgt; File, pick your own name if you want Add: Export-Package. Defines the packages that should be included in your bundle You can use wildcards Bundle-Activator, Adjust the package names to your earlier choice! Create the bundle by selecting the bnd file, then * andgt; Make Bundle This creates a JAR file, which is your first bundle! Export-Package: Bundle-Activator: \ Bnd Plugin Translation:  Bnd Plugin Translation The bnd plugin translates the file to the manifest, and embeds in the JAR file Any header that starts with an uppercase character is copied to the manifest by bnd Crucial headers will be filled in by bnd if you do not define a value Import-Package is calculated from the referred classes and matched, for example: * (all) is default !com.acme.* means do not import Export package expressions are matched against all packages on the class path Full manual: Manifest-Version: 1 Bundle-Name: Bundle-Activator: \ Import-Package:, \ org.osgi.framework;version=1.3 Bundle-ManifestVersion: 2 Bundle-SymbolicName: \ Export-Package: \; \ uses:=org.osgi.framework META-INF/MANIFEST.MF Export-Package: Bundle-Activator: \ bnd Launch a Framework:  Launch a Framework Run -andgt; Run … Select EquinoxFw The launch file is provided by the aQute.tutorial.runtime project. This starts an Equinox Framework with the fileinstall.jar bundle as only bundle. The fileinstall.jar bundle watches the work directory for bundles Any bundle in this directory will be installed and started Removed bundles will be uninstalled This is not an OSGi 'standard', it is just an application like for example Eclipse! Installing and uninstalling is therefore simply managing the aQute.tutorial.runtime/work directory Launching EquinoxFw:  Launching EquinoxFw Run the Hello World bundle:  Run the Hello World bundle The launch runs a Framework console Just copy (drag and drop or * andgt; Copy and andgt; Paste) the to the work directory See the 'Hello World' appear in the console Type 'ss' (show status) Look at the active bundles Notice the number for the bundle. This is the bundle-id. Type 'stop andlt;bundle-idandgt;' See the 'Goodbye world' The 'Hello World' appears again because the fileinstall.jar bundle starts the bundle again because it is still in the work directory. Eclipse Self Hosted Target Environment:  Eclipse Self Hosted Target Environment Eclipse also provides the Plugin Development Environment (PDE) besides the Java Development Environment (JDE) that we used so far. Plugins are bundles and the PDE is therefore usable to make bundles Handles dependencies Generates JARs Launches an Equinox Framework from a Target definition However, I find this environment hard to use for more general bundle development (I tried!) Easy to confuse the class path management JAR generation is complex and manual No extensive checks on generated bundles Cannot include packages form other sources than project What Did We Learn:  What Did We Learn The unit of deployment of an OSGi Service Platform is a bundle How to create a bundle with the bnd plugin How to launch an Equinox environment with a defined set of bundles, and manage it with the fileinstall.jar bundle How to start/stop bundles How the Equinox console works Why the Eclipse Self Hosting is not used Section V – Component interaction and collaboration:  Section V – Component interaction and collaboration Collaborative model:  Collaborative model OSGi is more than an Applet, MIDlet, Xlet runner Bundles can collaborate through: service objects package sharing A dynamic registry allows a bundle to find and track service objects Framework fully manages this collaboration Dependencies, security Collaborative model:  Collaborative model Bundle Bundle JAVA Operating System Hardware OSGi Framework Collaborative model:  Collaborative model JAVA Operating System Hardware Java Application Manager Midlet, Xlet, or Applet Midlet, Xlet, or Applet Class Path Issues:  Class Path Issues Java applications consists of classes placed in packages Java searches for a class in different jar files and directories These are usually specified in the CLASSPATH environment variable An OSGi Framework is a network of class loaders that delegate by the package name. The class loaders are parameterized by the manifest headers. Any dependencies between bundles are resolved by the OSGi Framework Complicated – But an OSGi Framework makes it painless to use See the uses: directive illustrated in this slide The bnd plugin makes it easy to generate the right information q p r p q-1.0 q q-2.0 Exported package Exported package Wire Constraint OSGi Package Dependency Resolution:  OSGi Package Dependency Resolution Bundle A Export org.osgi.service.log Import org.osgi.service.http javax.servlet.http Framework org.osgi.framework org.osgi.service.http Bundle B Export ericsson.osgi javax.servlet javax.servlet.http org.osgi.service.log Import org.osgi.service.http B resolved A resolved Package or Bundle Dependencies?:  Package or Bundle Dependencies? The OSGi Specifications supports both Require-Bundle and Import-Package Require-Bundle creates a dependency on a complete bundle Simple to use Imports packages that are never used Import-Package creates a dependency on just a package Creates less brittle bundles because of substitutability More cumbersome to use (Tools!) The bnd utility takes the pain out of this In almost all cases, Import-Package is recommended because it eases deployment and version migration The specifications detail a number of additional problems with Require-Bundle r r s r q p Require-Bundle Import-Package Service Specifics:  Service Specifics A service is an object registered with the Framework by a bundle to be used by other bundles The semantics and syntax of a service are specified in a Java interface A bundle can register a service. A bundle can use a service (bind to) with any cardinality 1..1, 0..1, 0..n A service can be discovered dynamically Active search with query filter Listener interface Services can go away at any time! This is very dynamic! service bind register listen package org.osgi.service.log; import org.osgi.framework.ServiceReference; public interface LogService { static final intLOG_ERROR= 1; static final intLOG_WARNING= 2; static final intLOG_INFO= 3; static final intLOG_DEBUG= 4; void log(int level, String message); void log(int level, String message, Throwable exception); void log(ServiceReference sr,int level, String message); void log(ServiceReference sr, int level, String message, Throwable exception); } Service Specifics:  Service Specifics The Framework Service Registry is available to all bundles to collaborate with other bundles Different bundles (from different vendors) can implement the same interface Implementation is not visible to users Allows operator to replace implementations without disrupting service OSGi defines a standard set of services Other organizations can define more (AMI-C, Ertico, JCP) Extensive notifications for service life cycles Services have a unique id Services can require Service Permission if security is enabled Fully under operator control Services are associated with properties Powerful query language to find appropriate service Bundles can update the properties of a service dynamically Manipulating Services:  Manipulating Services The Bundle Context provides the methods to manipulate the service registry Services registrations are handled by Service Registration objects They can be used to unregister a service or modify its properties Service Reference objects give access to the service as well as to the service’s properties Access to service objects is through the getService method. These services should be returned with the ungetService method ServiceRegistration registerService( String clss, Object srvc, Dictionary prprts) ServiceReference[] getServiceReferences( String clss, String fltr) Object getService( ServiceReference reference) boolean ungetService( ServiceReference rfrnc); Services and Best Practice:  Services and Best Practice Subsystem binding, like a Log Service for example Separate your code in POJOs (Plain Old Java Objects) that are not coupled to OSGi technology, and an Bundle Activator that binds the POJOs in the desired way Use declarative services to handle the binding (discussed later) Domain objects, like a Bluetooth service that is registered when a Bluetooth device comes into range Use the Service Tracker class for these situations Handle the dynamics, dynamic things will happen Start Level service is not a way to handle dynamics, believe me You can not control the initialization order, believe me What Did We Learn:  What Did We Learn The OSGi Service Platform provides a collaboration model that is based on Services Package sharing Sharing is complicated, but the well defined specifications make it quit painless for bundle developers Services provide a very powerful dynamic programming model SOA, without the communication overhead! Section VI – Service Components:  Section VI – Service Components Declarative Services Simplify Service Programming:  Declarative Services Simplify Service Programming The dynamic nature of services make programming more complicated The declarative service model simplifies handling these dynamics Dependencies are defined in an XML file or via bnd (which translates it to an XML file in the bundle, so the result is the same) Declarative Services: Optionally Depend on one or more services Optionally Provide a service Optionally lazy initialized Configurable Example shows a hello world bundle that logs 'Hello' and 'Goodbye' to the Log Service Service-Component: \ aQute.tutorial.component.World; \ log=org.osgi.service.log.LogService Export-Package: aQute.tutorial.component aQute.tutorial.component.bnd (bnd only) Service-Component ::= clause ( ‘,’ clause ) * clause ::= definition | andlt;resource pathandgt; definition ::= andlt;class-nameandgt; ( ‘;’ ‘dynamic:=‘ list ) ? ( ‘;’ ‘optional:=‘ list ) ? ( ‘;’ ‘multiple:=‘ list ) ? ( ‘;’ name ‘=‘ andlt;interface-nameandgt; ) * andlt;?xml version='1.0' encoding='utf-8' ?andgt; andlt;component name='aQute.tutorial.component.World'andgt; andlt;implementation class='aQute.tutorial.component.World'/andgt; andlt;reference name='log' interface='org.osgi.service.log.LogService' bind='setLog' /andgt; andlt;/componentandgt; OSGI-INF/aQute.tutorial.component.World.xml The Component Source Code:  The Component Source Code A component can be any class. No specific interface implementation is required. The activate and deactivate protected methods are called when the component is activated and deactivated Dependencies must be resolved. References can be bound to the component by calling the setXXX method Bnd will invoke a setXXX method when the reference name is lower case. The unsetXXX method is invoked when the policy is also dynamic. The Component Context class provides access to referenced services by name. The locateService method finds a reference by name The component instance can be sure that at any moment in time between activate and deactivate there is a valid Log Service in this example package aQute.tutorial.component; import org.osgi.service.component.*; import org.osgi.service.log.LogService; public class World { LogService log; protected void activate( ComponentContext context) { log.log(LogService.LOG_INFO, 'Hello World'); } protected void deactivate( ComponentContext context) { log.log(LogService.LOG_INFO, 'Goodbye World'); } public void setLog(LogService log) { this.log = log; } } andlt;?xml version='1.0' encoding='utf-8' ?andgt; andlt;component name='aQute.tutorial.component.World'andgt; andlt;implementation class='aQute.tutorial.component.World'/andgt; andlt;reference name='log' interface='org.osgi.service.log.LogService' bind='setLog' /andgt; andlt;/componentandgt; OSGI-INF/component.xml Launching:  Launching Launch the EquinoxFw launch configuration You can look in the log with the log command. Enter: osgiandgt; log Last event is at bottom, so scroll back Find the 'Hello World' Stop the bundle Enter in the console: osgiandgt; stop andlt;bundle-idandgt; Run log again What Did We Learn:  What Did We Learn Programming with services can be complicated The Declarative Services model makes service programming much, much, simpler How the component XML is constructed How bnd provides a simplified syntax How to use the Log Service Section VII – Use Case: Developing a Chat Service:  Section VII – Use Case: Developing a Chat Service A Chat Service:  A Chat Service A Chat client should be able to communicate with a user through: A window, telnet session, MSN, AOL, Skype, etc. interface. We base the communication between chat clients on a Channel service. The registrar of the service receives the messages The getter of the service sends the message A property contains the user name to identify the service Two services are used to communicate For simplicity, we use a command based interface for login and listing buddies Channel service send(from,msg) Chat send Chat receive Channel services message Channel Service Design:  Channel Service Design Create a new project to hold our service interface Call this project andlt;mynameandgt;.chat This is a Java Project The Channel service is one way: The registrar receives through a Channel service! A service property is defined. This property must be registered with the service CH_NAME – This must be set to the name of the user, e.g. 'pkriens' A single method send with the following arguments from – The user name that sends the message. There normally should be a Channel service with that CH_NAME msg – The message to be send Export the package in the bnd file. Create your JAR with * andgt; Make Bundle, and copy it to the runtime work directory to install it. package; import*; public interface Channel { String CH_NAME=''; void send(String from, String msg) throws IOException ; } Export-Package: Good Pattern: Whiteboard Approach:  Good Pattern: Whiteboard Approach What we use in the Channel service is the 'Whiteboard Approach'. Based on Inversion of Control (IoC) pattern: Don’t call us, we will call you It is very effective because it reduces the number of couplings between bundles Pattern: Register a service Let any interested bundle use it The Whiteboard approach was discovered during finishing of R1. We were not brave enough to scrap, that is why the Log Service and Http Service are not white board There is a white-paper comparing a whiteboard approach with a non whiteboard approach. Bundle A { } register Server bundle Events: register, unregister, modified Bundle C { } Bundle B { } Publisher bind Telnet Based Chat Client:  Telnet Based Chat Client The best way to find out if this works is to design a small test program. The easiest way for a 'UI' is a telnet server that uses the Channel service to communicate with siblings This also shows how Internet server daemons should be constructed The Telnet Chat server will create a Handler for each opened session. The Handler is a thread that waits for input from the user The Handler registers a Channel service. The Handler is stopped when the session closes (user quits or the connection is lost). This must unregister the Channel service Activated by Declarative Services User For each session 1 * Class Diagram = Service Interface The TelnetChat Manifest:  The TelnetChat Manifest Create a new Java project for a telnet chat Call this project andlt;mynameandgt;.telnetchat Add the osgi.jar from the aQute.tutorial.runtime/work directory to your project for the OSGi interfaces Define the andlt;mynameandgt;.telnetchat.bnd file We only specify a reference to the Log Service Notice that we use upper case, for demo reasons. Bnd does not create set and unset methods when the name starts with uppercase. Export-Package: aQute.tutorial.telnetchat.* Service-Component: \ aQute.tutorial.telnetchat.TelnetChat; \ LOG=org.osgi.service.log.LogService aQute.tutorial.telnetchat.bnd The TelnetChat Component code:  The TelnetChat Component code Create a new source for the TelnetChat server. No interfaces, no extends The code does not show the import packages and field definitions The source code is provided for you in aQute.tutorial.telnetchat Control-Shift-O organizes your imports! Good exercise  The activate method: Remembers the Bundle Context for later Gets the Log Service Starts the Thread. The deactivate method: Sets the quit flag so any loops in the started Thread will finally end. Threads can not be stopped. Closes all created Handler objects Exceptions are ignored because we are closing And closes the Server Socket object, this will surely quit the main socket accept loop. protected void activate( ComponentContext context) { this.context = context; log = (LogService) context .locateService('LOG'); start(); } public void deactivate( ComponentContext context) throws Exception { quit = true; for (Iterator i = handlers.iterator(); i .hasNext();) { Handler handler = (Handler); try { handler.close(); } catch (Throwable e) { // We are closing } } server.close(); } The TelnetChat run method:  The TelnetChat run method The run method creates a Server Socket and accepts incoming connections. For bundles, it is crucial that this loop never quits, but also not overloads the system by trying continuously There is usually no user watching a server … The outer loop therefore catches errors, sleeps and tries again A lot of problems disappear over time. For example, an Internet connection can be temporarily down The Server Socket has a timeout to check the flag regularly, extra safety The inner loop Wait for an incoming Socket Creates a Handler object And starts the Handler’s Thread public void run() { while (!quit) try { server = new ServerSocket(2030); server.setSoTimeout(1000); loop(); } catch (Exception e) { log .log( LogService.LOG_ERROR, '[TelnetChat] Inn…', e); sleep(10000); } } void loop() throws Exception { while (!quit) try { Socket socket = server.accept(); Handler handler = new Handler(context .getBundleContext(), socket, this); handlers.add(handler); handler.start(); } catch (SocketTimeoutException e) { // Just for checking the quit flag // at a regular basis } } TelnetChat convenience methods:  TelnetChat convenience methods Convenience methods void remove(Handler handler) { handlers.remove(handler); } void sleep(int ms) { try { Thread.sleep(ms); } catch (InterruptedException e1) {} } The Handler Source Code:  The Handler Source Code Create a file The constructor receives the Socket for the session with the end user. It initializes: The fields A Writer object to send text to the end user The send method writes the message in the Writer object and flushes it to ensure the user sees it The close method closes the different objects and quits the main loop: By setting the quit flag By closing the Socket Closing the Socket of a listener thread is a crude but sure way to get the Thread’s attention public Handler(BundleContext context, Socket socket, TelnetChat activator) throws Exception { this.ctxt = context; this.socket = socket; this.parent = activator; writer = new PrintWriter( new OutputStreamWriter(socket .getOutputStream())); } public void send(String source, String msg) throws IOException { writer.println(source + 'andgt; ' + msg); writer.flush(); } void close() { try { quit = true; writer.close(); socket.close(); } catch (IOException e) { // Ignore in close } } The Handler Source Code:  The Handler Source Code The run method loops as long as there is input from the user. It quits when the Socket is closed or an error occurs. Errors are only logged when the session has not quit because there are usually Socket errors during closing The finally clause is used to guarantee that the Handler is removed from the parent when it is closed. If a valid line is received, it is send to the process method The line is cleaned from nasty characters and backspaces (for telnet clients that send character by character). public void run() { writer .println('Welcome…Telnet Chat'); writer.flush(); try { InputStreamReader srdr = new InputStreamReader( socket.getInputStream()); BufferedReader reader = new BufferedReader( srdr); while (!quit andamp;andamp; (line = reader.readLine()) != null){ process(clean(line)); } writer.println('bye'); } catch (Exception e) { parent.log.log(LogService.LOG_ERROR, 'reading user input', e); } finally { parent.remove(this); parent = null; close(); } } The Handler Source Code:  The Handler Source Code The process method handles a line of input from the user. It checks the line against the /login or /quit command. Simplistic, I know If the line starts with /quit, we quit the program by setting the quit flag. Otherwise we assume it is a line we need to send to another user, which is handled in the dispatch method void process(String line) throws Exception { if (line.startsWith('/login')) login(line); else if (line.startsWith('/quit')) quit = true; else dispatch(line); } void login(String line) throws IOException { String parts[] = line.split('\\s'); if (parts.length != 2) send('error', '/login andlt;nameandgt;'); user = parts[1]; if (channel != null) channel.unregister(); Dictionary properties = new Hashtable(); properties.put(Channel.CH_NAME, user); channel = parent.context .getBundleContext().registerService( Channel.class.getName(), this, properties); } The Handler Source Code:  The Handler Source Code The dispatch method parses the destination name from the input For this name , finds a Channel service n It then sends the remainder of the line to that service with the send method of that service void dispatch(String line) throws Exception { try { String parts[] = line.split('\\s+'); ServiceReference channels[] = ctxt .getServiceReferences( Channel.class.getName(), '(' + Channel.CH_NAME + '=' + parts[0] + ')'); if (channels != null) { Channel toChannel = (Channel) ctxt .getService(channels[0]); toChannel.send(user, line.substring( parts[0].length()).trim()); ctxt.ungetService(channels[0]); } else { send('error', 'no such user: ' + parts[0]); } } catch (Exception e) { send('error', 'problems: ' + e); } } The Handler Source Code:  The Handler Source Code The clean method cleans up the input if backspaces were used Also ignores non ASCII characters String clean(String line) { byte[] buf = line.getBytes(); int out = 0; for (int in = 0; in andlt; line.length(); in++) { char c = line.charAt(in); if (c == '\b') // backspace out--; else if (c andgt;= 32 andamp;andamp; c andlt; 0x7F) buf[out++] = (byte) c; } return new String(buf, 0, out); } Run the Telnet Chat:  Run the Telnet Chat Do * andgt; Make Bundle on the aQute.tutorial.telnetchat.bnd file Copy your resulting bundle to the aQute.tutorial.runtime/work directory to get it installed Create 2 telnet sessions: Open a telnet session into port 2030 Login with your last name (/login kriens) Open a second telnet session into port 2030 Login with another name (/login peter) Don’t forget, the first word is the name of the receiver peter Hello! See if you can send messages. Check the services in the console, and see that two channel services are registered osgiandgt; services (objectclass=*Channel) What Did We Learn:  What Did We Learn How services are designed The Whiteboard pattern Developed a simple Telnet Chat application Chat sessions use the whiteboard approach to communicate with Channel services Build a real, albeit small, bundle Threading issues with bundles Section VIII – Service Tracking:  Section VIII – Service Tracking Creating a Chat Library Bundle:  Creating a Chat Library Bundle The aQute.tutorial.telnetchat bundle contains code that must be repeated between different clients A chat middleware library that captures the shared code would be useful. As a bundle, this could run on phones, Eclipse, vehicles, etc. Add to the project a new package: For this example, we create a Chat class that works on a command line basis The Chat class will be added to the andlt;mynameandgt;.chat bundle (we use Lines that start with /are treated as commands This bundle will therefore act as a middleware library and is the exporter of the chat package Not all code is shown, however, this is available in the project Export-Package:, \ aQute.tutorial.telnetchat aQute.tutorial.telnetchat Chat Library: The Case for the ServiceTracker:  Chat Library: The Case for the ServiceTracker Finding services for each message is kind of expensive. The ServiceTracker in org.osgi.util.tracker package with the Service Tracker class is intended to simplify this task A Service Tracker maintains a list of services based on: A filter A specific class A Service Reference object It reports any existing or new services as well as any services that become unregistered Object addingService void modifiedService void removedService The Service Tracker is used to track Channel services and store them in a Map object Chat Library: The Case for the ServiceTracker: create:  Chat Library: The Case for the ServiceTracker: create Framework Bundle A Bundle B Bundle C Chat Library: The Case for the ServiceTracker: open:  Chat Library: The Case for the ServiceTracker: open Object addingService(ServiceReference r){…} Framework Bundle A Bundle B Bundle C Object addingService(ServiceReference r){…} Chat Library: The Case for the ServiceTracker: adding:  Chat Library: The Case for the ServiceTracker: adding Framework Bundle A Bundle B Bundle C Object addingService(ServiceReference r){…} Chat Library: The Case for the ServiceTracker: removing:  Chat Library: The Case for the ServiceTracker: removing Framework Bundle A Bundle B Bundle C void removedService(ServiceReference r,Objecto){…} Chat Library: The Case for the ServiceTracker: modified:  Chat Library: The Case for the ServiceTracker: modified Framework Bundle B Bundle C void modifiedService(ServiceReference r, Object o){…} Bundle A Chat Library: Constructor:  Chat Library: Constructor The Chat constructor initializes some fields and creates the Service Tracker The user is given as a Channel service. The user of the Chat library must implement the Channel service to get a callback for any incoming messages. public Chat(BundleContext context, final Channel user) { this.user = user; this.cntxt = context; channels = new ChannelTracker(context);; } The Chat Library: Channel Tracker:  The Chat Library: Channel Tracker The Channel Tracker is used to track Channel services The addingService method gets the Channel service and puts the Channel in a Map under the given name The removedService method just cleans up the Map by removing the Channel service class ChannelTracker extends ServiceTracker { ChannelTracker(BundleContext context) { super(context, Channel.class.getName(), null); } public Object addingService( ServiceReference ref) { Channel buddy = (Channel) super .addingService(ref); String name = (String) ref .getProperty(Channel.CH_NAME); bdds.put(name, buddy); return buddy; } public void removedService( ServiceReference ref, Object buddy) { bdds.entrySet().remove(buddy); } } The Chat Library: Logging in:  The Chat Library: Logging in The login method registers a new Channel service The password is ignored The result is sent as a message to the user public void login(String name, String password) throws IOException { if (registration != null) registration.unregister(); registration = null; = name; Hashtable properties = new Hashtable(); properties.put(Constants.SERVICE_PID, 'pid:chat[' + InetAddress.getLocalHost() + ']:' + name); properties.put(Channel.CH_NAME, name); properties.put('remote', '*'); registration = cntxt.registerService( Channel.class.getName(), user, properties); user.send('', 'Logged in as ' + name); } The Chat Library: execute:  The Chat Library: execute The execute method looks at the command line and scans for ‘/’ characters, which are commands /help – Show short help /buddies – List the buddies /login – Login /andlt;buddyandgt; to send to a buddy If no / is given the message is sent to the last used buddy (if exists) The last buddy is remembered in lastTo public void execute(String line) throws IOException { if (!line.startsWith('/')) send(line); else { line = line.trim(); StringTokenizer st = new StringTokenizer( line, ' \t'); int cnt = st.countTokens(); if (cnt != 0) { String ws[] = new String[cnt]; for (int i = 0; i andlt; cnt; i++) { ws[i] = st.nextToken(); } if ('/ip'.startsWith(ws[0])) doIP(); else if ('/buddies' .startsWith(ws[0])) doBuddies(); else if ('/help'.startsWith(ws[0])) doHelp(); else if ('/login'.startsWith(ws[0])) login(ws[1], null); else { lastTo = ws[0].substring(1); send(line .substring(ws[0].length())); }}}} The Chat Library: send:  The Chat Library: send The send method must transfer the message to the lastTo buddy. We maintain all the buddy Channel services in the bdds Map field, so it is easy to find them void send(String line) throws IOException { if (lastTo == null) user.send('', 'No buddy'); else { Channel channel = (Channel) bdds .get(lastTo); if (channel != null) { channel.send(name, line); user.send(name, line); } else user.send('?', 'Can't find ' + lastTo); } } The Chat Library: doBuddies, getBuddies:  The Chat Library: doBuddies, getBuddies The doBuddies method sends the list of currently logged in buddies to the user The getBuddies method returns the buddies as a String[] void doBuddies() throws IOException { StringBuffer sb = new StringBuffer(); String del = ''; for (Iterator i = bdds.keySet() .iterator(); i.hasNext();) { sb.append(del); sb.append(; del = ', '; } user.send('', sb.toString()); } public synchronized String[] getBuddies() { return (String[]) bdds.keySet().toArray( new String[0]); } The Chat Library: utiltities:  The Chat Library: utiltities The doHelp method sends some help text to the user The getName method returns the currently logged name The close method uses a careful way to unregister the associated Channel service only once Often it is not easy to control how many time close is called void doHelp() throws IOException { user.send('', 'You are logged in as: ' + name); user.send( '', '/buddies List current online buddies'); user.send('', '/help - This message'); user.send('', '/login andlt;idandgt; - Login under id'); user.send('', '/andlt;nameandgt; ... - Send msg to buddy'); user.send('', '... - Send msg to last used buddy'); } public void close() { ServiceRegistration reg; synchronized (this) { reg = registration; if (reg == null) return; registration = null; } reg.unregister(); } public String getName() { return name; } What Did We Learn:  What Did We Learn How to track services and react appropriately on their arrival and departure How to use the Service Tracker to simplify this The whiteboard pattern as a solution to many dynamic problems Section IX – Finishing Touch:  Section IX – Finishing Touch Using the Chat Library with a Window:  Using the Chat Library with a Window We now have a library bundle that is easy to use We could adapt the aQute.tutorial.telnetchat project, but that is old news Lets make a small Swing program that shows a simple chat window Call this project andlt;mynameandgt;.chatwindow Such a program is provided in the aQute.tutorial.chatwindow project Export-Package: \ aQute.tutorial.chatwindow Service-Component: \ aQute.tutorial.chatwindow.ChatWindow aQute.tutorial.chatwindow Using the Chat Library:  Using the Chat Library The activate method creates a new Chat instance from the Chat library We run the frame in the Swing thread so we do not have multithreading issues (see invokeAndWait) The deactivate method sets a quit flag protected void activate( ComponentContext context) throws Exception { = new Chat(context .getBundleContext(), this); SwingUtilities.invokeAndWait(this); } protected void deactivate( ComponentContext context) throws Exception { chat.close(); frame.setVisible(false); frame.dispose(); } Using the Chat Library:  Using the Chat Library The run method creates and opens a new window Reads quit flag to determine when to close the application The usual window verbosity … The window creates: A Frame (the window itself), A text field that will contain the chat output, and A line field that will contain the chat input The rest of the processing is handled via the Key Listener public void run() { frame = new JFrame('ChatWindow'); text = new JTextArea(); text.setEnabled(false); JScrollPane scroll = new JScrollPane( text); frame.getContentPane().add(scroll, BorderLayout.CENTER); line = new JTextField(); frame.getContentPane().add(line, BorderLayout.SOUTH); frame.setSize(400, 500); frame.setVisible(true); line.addKeyListener(this); } Using the Chat Library:  Using the Chat Library The keyTyped method of the Key Listener interface processes when the new line is entered The error method displays an error to the user The send method displays a message to the user from another client It is called via the Channel service that this Chat instance registered private void error(Exception e) { text.append('errorandgt; '); text.append(e + ''); } public void send(final String from, final String string) { text.append(from + 'andgt; ' + string + '\r\n'); } public void keyTyped(KeyEvent e) { try { if (e.getKeyChar() == '\r' || e.getKeyChar() == '\n') { String txt = line.getText(); chat.execute(txt.trim()); line.setText(''); } } catch (Exception ee) { error(ee); } } public void keyPressed(KeyEvent e) {} public void keyReleased(KeyEvent e) {} Running the Chat Window:  Running the Chat Window Run the aQute.tutorial.chatwindow in the normal way Voila! Notice that this collaborates with the aQute.tutorial.telnetchat bundle. What Did We Learn?:  What Did We Learn? That the OSGi Service Registry is a surprisingly powerful model for collaboration The decoupling that it promotes allows additional functionality without influencing existing functions Section X – Remoting:  Section X – Remoting Remoting:  Remoting The chat is kind of boring because it only works on our own laptop. Missing is discovery of each other’s bundles! Rescue is on the way … Enable the aQute.tutorial.remoting project This project can export services to other participating machines The only requirement is that you have a property remote=* on your service. See code The aQute.tutorial.remoting project will then export this service to any participating machine. Our Channel objects will therefore be spread all over the place Build the aQute.tutorial.remoting bundle, copy to work, and test with your buddies. public void login(String name, String password) throws IOException { if (registration != null) registration.unregister(); registration = null; = name; Hashtable properties = new Hashtable(); properties.put(Constants.SERVICE_PID, 'pid:chat[' + InetAddress.getLocalHost() + ']:' + name); properties.put(Channel.CH_NAME, name); properties.put('remote', '*'); registration = cntxt.registerService( Channel.class.getName(), user, properties); user.send('', 'Logged in as ' + name); } Remoting:  Remoting Machine A Machine B Machine E Machine D Machine C network Real Channel Proxy of Channel Broadcast +p2p Section XI – Final:  Section XI – Final What We Did Not Learn:  What We Did Not Learn Security Architecture Permission Management Signed Bundles Package Management Bundle Life Cycle Management Configuration Management and Preferences Servlet Support/Web Server Device Access Event Manager UPnP User Admin Wire Admin Application Model Deployment Admin and Autoconf Device Management Tree Initial Provisioning Position, Measurement, State MetaType And much, much, more Conclusion :  Conclusion The OSGi R4 Specifications consists of considerable more details than elucidated in this tutorial There are many independent OSGi implementations on the market, both commercial and open source Apache Felix, Atinav, Eclipse Equinox, Espial, IBM SMF, Knopflerfish/Ubiserv of Gatespace, ProSyst, … The OSGi specification are today running on mobile phones, PDAs, embedded computers, desktops, and mainframes Both in managed and unmanaged configurations The OSGi specifications solve real world problems The OSGi Alliance is working on making the OSGi specifications the standard for portable applications. Join us! The End:  The End Further reading:

Add a comment

Related presentations

Related pages

Wikipedia:Tutorial/1 – Wikipedia

Grundlegende Richtlinien. Bevor du in der Wikipedia mit dem Schreiben beginnst, sind hier ein paar elementare Grundsätze und Richtlinien aufgelistet, die ...
Read more

Beginner PHP Tutorial - 1 - Introduction to PHP - YouTube

Understanding PHP, MySQL, HTML and CSS and their Roles in Web Development - CodersCult Webinar 001 - Duration: 1:04:13. CodersCult 183,105 views
Read more

Tutorial - Wikipedia, the free encyclopedia

A tutorial is a method of transferring knowledge and may be used as a part of a learning process. ... 1) video tutorials that the user views, 2) ...
Read more

Jumpstyle tutorial #1 - YouTube

leren jumpen tutorial #1 suc 6 met oefenen ofsjoow
Read more

Android Tutorial - Teil 1 - Developer-Blog

In meinem Android Tutorial zeige ich euch Schritt für Schritt wie man mit der Android App Entwicklung beginnt und wie der technische Hintergrund aussieht.
Read more

HTML Tutorial - W3Schools Online Web Tutorials

This HTML tutorial contains hundreds of HTML examples. With our online HTML editor, you can edit the HTML, and click on a button to view the result.
Read more

Tutorials | Let's Play

Tutorials: Let’s Plays. Du willst eigene Let’s Plays aufnehmen, weißt aber nicht wie? Was gilt es zu beachten? Welche Tools benötigt man dazu?
Read more

Tutorials auf Pinterest

Sieh nach, was Mandy Squires auf der Pinterest-Pinnwand „Tutorials“ gepinnt hat. Pinterest ist ein visuelles Lesezeichentool, ... 4-1 Weave Chain Maille.
Read more - Tutorials, Video-Trainings ...

1. Februar 2016 0 Kommentare Regen bauen in Photoshop. ... 1; 2; 3; 4; 5 › » Letzte Tutorials. Retuschewerkzeuge in Photoshop; Weichzeichner und ...
Read more

PDF-Export - Affinity Designer Tutorial

Der PDF-Export beinhaltet nun für die Druckproduktion wichtige Einstellmöglichkeiten wie Schnittmarken, Beschnittzugabe und umfangreiche Farbmanagement ...
Read more