osgi component programming | oopsla 2006 © 2006 by ibm, aqute & osgi alliance; made available...
TRANSCRIPT
1 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Copyright is held by the OSGi Alliance, IBM and aQute
This presentation is made available under the EPL v1.0
OOPSLA'06, October 22–26, 2006,
Portland, Oregon, USA.
2006 ACM 06/0010.
2
© 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
OOPSLA 2006 Portland
© 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
OOPSLA 2006 Portland
OSGi Component Programming
Peter KriensOSGi Technical DirectorOSGi EvangelistCEO [email protected]
3 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
4 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Section I – Setting up Eclipse and the OSGi Platform
5 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Setup: A Clean Workspace in Eclipse
6 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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) (http://www.eclipse.org) The tutorial projects from CVS:
Server: bundles.osgi.org Repository /cvshome/bundles User tutorial Password fun Projects tutorial-01
The bnd plugin installed
You can install all this from CVS or from the CD
This tutorial assumes the PC for user interface interactions. You must translate this to your environment if you run Linux or have a Mac
7 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Loading the Tutorial Projects from CVS
In Navigation View, open context menu, and select Import (* > Import
* is context menu, select file, use right mouse (on the PC)
This opens a dialog
Select CVS > Projects from CVS, then Next
You might get a window to choose from a repository, create a new repository in that case
Fill in the repository information from the previous slide (password=fun) > Next
8 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Loading the Tutorial Projects from CVS
In CVS Repositories view, expand: tutorial-01
Click on + to expand
Select all projects under tutorial-01
Select with the mouse and hold the shift key pressed to select multiple
choose Next > Check Out > Finish
9 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Your Workspace (More or Less)
10 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 directoryCopy this from your operating system
Exit Eclipse and restart
Verify: Help > About > 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” extensionThe bnd file contains all the information a requires, it calculates defaults for undefined informationThe bnd.jar is also usable as a command line option
For more documentation, http://www.aqute.biz/bnd
11 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Section II - OSGi Background
12 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 www.osgi.org …
Cool!
13 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
14 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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!
15 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Problems: Complexity of SoftwareP
rodu
ctiv
ity
Complexity and Size
Assembly
Structured Programming
Service Oriented Programming
16 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
17 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Section III - OSGi Technology
18 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 & collaborations between applications
Provides life cycle management (install, start, stop, update, etc).
Policy free Policies are provided by bundles
Operating SystemOperating SystemOperating SystemOperating SystemOperating SystemOperating System
Operating SystemOperating System
JavaJavaVMVMJavaJava
VMVMJavaJavaVMVMJavaJava
VMVM
JavaJavaVMVMJavaJava
VMVMJavaJavaVMVMSystem Class LibrariesSystem Class Libraries
OSGiOSGi
OSGiOSGiOSGiOSGi
OSGiOSGi
ApplicationApplicationApplicationApplication
ApplicationApplication
ApplicationApplicationApplicationApplication
ApplicationApplicationApplicationApplication
LibraryLibrary
19 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
Componentprovides
uses
20 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
Sec
urity
Execution EnvironmentA
pplic
atio
ns
21 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
OSGiMin.
22 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
bundlebundle
bundle
bundle
bundle
bundle
23 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Layers: OSGi Life Cycle Layer
System Bundle represents the OSGi Framework
Provides an API for managing bundles
Install
Resolve
Start
Stop
Refresh
Update
Uninstall
BundleX
BundleX-v2
BundleB
BundleM
BundleA
Systembundle
State (active or not)
Manages
24 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
25 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
26 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Layers: The OSGi Service Layer Evolution
UPnPInitial ProvisioningName SpaceJiniStart LevelIO ConnectorWire AdminXML ParserMeasurement & StatePositionExecution Env.
Application ManagerForeign App. AccessSigned BundlesDeclarative ServicesDevice ManagementSecurity PoliciesFramework LayeringInitial ProvisioningUPnPConditional Permissions…
2000 2001 2003 2006
R1
R2
R3
R4H
om
e A
uto
ma
tio
n
Ve
hic
le
Mo
bil
e
FrameworkHttpLogDevice Access
Package AdminConfiguration AdminPermission AdminUser AdminPreferencesMetaTypeService Tracker
R5
27 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
28 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
The OSGi Implementations
Major Framework vendors are
ProSyst,
Gatespace Telematics, and
IBM
Siemens
Espial
Open source implementations
Apache Felix
Eclipse Equinox
Gatespace Knopflerfish
See http://www.aqute.biz/osgi for an overview
29 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
30 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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.
31 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Section IV - Fundamental OSGi concepts
32 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Framework Entities
OSGi Framework
Bundle A{…}
= service, defined by java interface
Bundle B{…}
Bundle C{…}
= bundle
33 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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{…}
34 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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{…}
35 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Create a Hello (and Goodbye) World Bundle
* > New > Project
Java Project > Next
Fill in the information, defaults are likely to be ok. As name you can use my.world, then > Next
For each tab:Source, just infoProjects, for dependent projects. We have none nowIn Libraries > 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
> Finish
36 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Create a Hello (and Goodbye) World Bundle
37 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Create a Hello (and Goodbye) World Bundle
Create a Java source called World.java
Select src folder * > New > Class
Set the package to something like my.world
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 my.world. You should choose your own naming to not conflict with the provided source code.
38 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 > Will jump to the selected type (try, click BundleActivator, and then F3)
Control-Shift-T > Will show a source of a type (class)
Control-Shift-R > Will show a source of a resource (not a class)
package aQute.tutorial.world;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}
}
Activator.java
39 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Manifest code for Hello/Goodbye World
Each JAR file has a manifest
Basic format of the manifest is defined by Sun http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html
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 …
40 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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. * > New > File
aQute.world.bnd, pick your own name if you want
Add:Export-Package. Defines the packages that should be included in your bundle You can use wildcardsBundle-Activator, aQute.tutorial.world.Activator
Adjust the package names to your earlier choice!
Create the bundle by selecting the bnd file, then * > Make Bundle
This creates a JAR file, which is your first bundle!
Export-Package: aQute.tutorial.worldBundle-Activator: \ aQute.tutorial.world.Activator
aQute.tutorial.world.bnd
41 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Bnd Plugin Translation
The bnd plugin translates the aQute.tutorial.world.bnd 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: http://www.aqute.biz/bnd
Manifest-Version: 1Bundle-Name: aQute.tutorial.worldBundle-Activator: \ aQute.tutorial.world.ActivatorImport-Package: aQute.tutorial.world, \ org.osgi.framework;version=1.3Bundle-ManifestVersion: 2Bundle-SymbolicName: \ aQute.tutorial.worldExport-Package: \ aQute.tutorial.world; \ uses:=org.osgi.framework
META-INF/MANIFEST.MF
Export-Package: aQute.tutorial.worldBundle-Activator: \ aQute.tutorial.world.Activator
aQute.tutorial.world.bnd
bnd
42 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Launch a Framework
Run -> 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
43 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Launching EquinoxFw
44 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Run the Hello World bundle
The launch runs a Framework console
Just copy (drag and drop or * > Copy and > Paste) the aQute.tutorial.world.jar to the work directory
See the “Hello World” appear in the console
Type “ss” (show status)Look at the active bundlesNotice the number for the aQute.tutorial.world.jar bundle. This is the bundle-id.
Type “stop <bundle-id>”
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.
45 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 form 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
46 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
47 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Section V – Component interaction and collaboration
48 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
49 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Collaborative model
BundleBundle
JAVA
Operating System
Hardware
OSGi Framework
Serviceregistry
packagespackages
50 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Collaborative model
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
51 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
52 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
OSGi Package Dependency Resolution
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
53 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 useImports packages that are never used
Import-Package creates a dependency on just a package
Creates less brittle bundles because of substitutabilityMore 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
54 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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);}
55 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
56 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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);
57 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
58 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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!
59 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Section VI – Service Components
60 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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.LogServiceExport-Package: aQute.tutorial.component
aQute.tutorial.component.bnd
(bnd only)Service-Component ::= clause ( ‘,’ clause ) *clause ::= definition | <resource path>definition ::= <class-name> ( ‘;’ ‘dynamic:=‘ list ) ? ( ‘;’ ‘optional:=‘ list ) ? ( ‘;’ ‘multiple:=‘ list ) ? ( ‘;’ name ‘=‘ <interface-name> ) *
<?xml version="1.0" encoding="utf-8" ?> <component name="aQute.tutorial.component.World"> <implementation class="aQute.tutorial.component.World"/> <reference name="log" interface="org.osgi.service.log.LogService" bind="setLog" /> </component>
OSGI-INF/aQute.tutorial.component.World.xml
61 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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; }}
<?xml version="1.0" encoding="utf-8" ?> <component name="aQute.tutorial.component.World"> <implementation class="aQute.tutorial.component.World"/> <reference name="log" interface="org.osgi.service.log.LogService" bind="setLog" /> </component>
OSGI-INF/component.xml
Component.java
62 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Launching
Launch the EquinoxFw launch configuration
You can look in the log with the log command. Enter:
osgi> logLast event is at bottom, so scroll back
Find the “Hello World”
Stop the bundle
Enter in the console: osgi> stop <bundle-id>
Run log again
63 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
64 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Section VII – Use Case: Developing a Chat Service
65 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 servicesend(from,msg)
Chatsend
Chat receive
Petersession
Petersession
Thomas session
Thomas session
Channel services
message
66 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Channel Service Design
Create a new project to hold our service interface
Call this project <myname>.chatThis 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_NAMEmsg – The message to be send
Export the aQute.tutorial.chat package in the bnd file.
Create your JAR with * > Make Bundle, and copy it to the runtime work directory to install it.
package aQute.service.channel;import java.io.*;public interface Channel {
String CH_NAME="channel.name";
void send(String from, String msg) throws IOException ;}
Channel.java
Export-Package: aQute.service.channel
aQute.tutorial.chat.bnd
67 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 youIt is very effective because it reduces the number of couplings between bundles
Pattern:Register a serviceLet 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.
http://www.osgi.org/documents/osgi_technology/whiteboard.pdf
Bundle A{ }
register
Serverbundle
Events: register,unregister,modified
Bundle C{ }
Bundle B{ }
Publisher
bind
68 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 userThe 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
TelnetChatTelnetChat
HandlerHandler
ChannelChannel
LogServiceLogService
Activated by Declarative Services
ThreadThread
User
For each session1
*
Class Diagram
= Service Interface
69 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
The TelnetChat Manifest
Create a new Java project for a telnet chat
Call this project <myname>.telnetchat
Add the osgi.jar from the aQute.tutorial.runtime/work directory to your project for the OSGi interfaces
Define the <myname>.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
70 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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) i.next(); try { handler.close(); } catch (Throwable e) { // We are closing } } server.close();}
TelnetChat.java
71 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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.java
72 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
TelnetChat convenience methods
Convenience methods void remove(Handler handler) { handlers.remove(handler);}void sleep(int ms) { try { Thread.sleep(ms); } catch (InterruptedException e1) {}}
TelnetChat.java
73 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
The Handler Source Code
Create a Handler.java file
The constructor receives the Socket for the session with the end user. It initializes:
The fieldsA 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 flagBy 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 + "> " + msg); writer.flush();}void close() { try { quit = true; writer.close(); socket.close(); } catch (IOException e) { // Ignore in close }}
Handler.java
74 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 && (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(); }}
Handler.java
75 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 <name>"); 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);}
Handler.java
76 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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); }}
Handler.java
77 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 < line.length(); in++) { char c = line.charAt(in); if (c == '\b') // backspace out--; else if (c >= 32 && c < 0x7F) buf[out++] = (byte) c; } return new String(buf, 0, out);}
Handler.java
78 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Run the Telnet Chat
Do * > 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
receiverpeter Hello!
See if you can send messages.
Check the services in the console, and see that two channel services are registered
osgi> services (objectclass=*Channel)
79 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
80 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Section VIII – Service Tracking
81 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 aQute.tutorial.chat project a new package: aQute.tutorial.chat
For this example, we create a Chat class that works on a command line basis
The Chat class will be added to the <myname>.chat bundle (we use aQute.tutorial.chat)
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 aQute.tutorial.chat project
Export-Package: aQute.tutorial.chat, \ aQute.service.channel
aQute.tutorial.chat
aQute.service.channel
aQute.tutorial.chat
aQute.tutorial.chat
aQute.tutorial.telnetchat
aQute.service.channel
aQute.tutorial.chat
aQute.tutorial.telnetchat
82 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
83 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Chat Library: The Case for the ServiceTracker: create
Framework BundleA
BundleB
BundleC
84 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Chat Library: The Case for the ServiceTracker: open
Object addingService(ServiceReference r){…}
Framework BundleA
BundleB
BundleC
addServiceListener
Object addingService(ServiceReference r){…}
85 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Chat Library: The Case for the ServiceTracker: adding
Framework BundleA
BundleB
BundleC
addServiceListener
Object addingService(ServiceReference r){…}
86 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Chat Library: The Case for the ServiceTracker: removing
Framework BundleA
BundleB
BundleC
addServiceListener
void removedService(ServiceReference r,Objecto){…}
87 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Chat Library: The Case for the ServiceTracker: modified
Framework
BundleB
BundleC
addServiceListener
void modifiedService(ServiceReference r, Object o){…}
BundleA
88 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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); channels.open();}
Chat.java
89 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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); }}
Chat.java
90 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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; this.name = 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);}
Chat.java
91 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
/<buddy> 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 < 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()));}}}}
Chat.java
92 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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); }}
Chat.java
93 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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(i.next()); del = ", "; } user.send("", sb.toString()); } public synchronized String[] getBuddies() { return (String[]) bdds.keySet().toArray( new String[0]); }
Chat.java
94 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 <id> - Login under id"); user.send("", "/<name> ... - 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; }
Chat.java
95 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
96 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Section IX – Finishing Touch
97 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 <myname>.chatwindow
Such a program is provided in the aQute.tutorial.chatwindow project
Export-Package: \ aQute.tutorial.chatwindowService-Component: \ aQute.tutorial.chatwindow.ChatWindow
aQute.tutorial.chatwindow
98 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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 { this.chat = new Chat(context .getBundleContext(), this); SwingUtilities.invokeAndWait(this);}protected void deactivate( ComponentContext context) throws Exception { chat.close(); frame.setVisible(false); frame.dispose();}
ChatWindow.java
99 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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);}
ChatWindow.java
100 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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("error> "); text.append(e + ""); } public void send(final String from, final String string) { text.append(from + "> " + 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) {}
ChatWindow.java
101 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Running the Chat Window
Run the aQute.tutorial.chatwindow in the normal way
Voila!
Notice that this collaborates with the aQute.tutorial.telnetchat bundle.
102 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
103 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Section X – Remoting
104 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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; this.name = 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);}
Chat.java
105 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Remoting
Machine A
Machine B
Machine E
Machine D
Machine C
network
Real Channel
Proxy of Channel
Broadcast +p2p
106 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
Section XI – Final
107 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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
108 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0 OSGi Component Programming | OOPSLA 2006 © 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
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!
109
© 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
OOPSLA 2006 Portland
© 2006 by IBM, aQute & OSGi Alliance; made available under the EPL v1.0
OOPSLA 2006 Portland
The End
Further reading:
http://www.osgi.org
http://bundles.osgi.org
http://www.eclipse.org/osgi
http://www.aqute.biz
http://www.ProSyst.com