OSGi Tutorial

106
OSGi Tutorial Matthias lübken, akquinet www.akuinet.de & Peter Kriens, aQute www.aQute.biz

description

OSGi Tutorial. Matthias lübken, akquinet www.akuinet.de & Peter Kriens, aQute www.aQute.biz. Content. I– Setting up Eclipse and the OSGi Platform II – OSGi Background III– OSGi Technology IV– OSGi Concepts V – Hello world VI - Launching a Framework - PowerPoint PPT Presentation

Transcript of OSGi Tutorial

Page 1: OSGi Tutorial

OSGi Tutorial

Matthias lübken, akquinet

www.akuinet.de

&

Peter Kriens, aQute

www.aQute.biz

Page 2: OSGi Tutorial

Content

I – Setting up Eclipse and the OSGi PlatformII – OSGi BackgroundIII – OSGi TechnologyIV – OSGi ConceptsV – Hello worldVI - Launching a FrameworkVII - Component Interaction and CollaborationIIX – Service ComponentsIX – Using the HTTP ServiceX – Making a PortalXI – Creating a content providerXII – Final

Page 3: OSGi Tutorial

Section I – Setting up Eclipse and the OSGi

Platform

Page 4: OSGi Tutorial

Setup: Your Infrastructure

Create a new workspaceImport all the projects and make a copyFind where your Eclipse installation residesCopy the bnd.jar file to the eclipse/dropins directoryRestart EclipseSelect your new workspace

Page 5: OSGi Tutorial

Your Workspace

Page 6: OSGi Tutorial

Verify bnd is installed

Page 7: OSGi Tutorial

Section II - OSGi Background

Page 8: OSGi Tutorial

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

CollaborativeCreated through a collaboration of industry leaders

IBM, Ericsson, Nokia, Sony, Telcordia, Samsung, ProSyst, Gatespace, BenQ, Nortel, Oracle, Sybase, Espial, and many more

Spec 4.+ publicly available at www.osgi.org …Cool!

Page 9: OSGi Tutorial

Why the OSGi Service Platform?

What problems does the OSGi Service Platform address?

Modularity!

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

Page 10: OSGi Tutorial

Problems: Limited Binary Software Portability

Lack of portability causes

Market friction: No large market of reusable components and applications

Reduced qualityUnnecessary constraints on hardware and software architectures

CPUs differ widely in cost and performance

Linux is nice, but it is sub-optimal for smaller devicesBenefits 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!

Page 11: OSGi Tutorial

Problems: Complexity of Software

PR

OD

UC

TIV

ITY

COMPLEXITY AND SIZE

ASSEMBLY

STRUCTURED PROGRAMMING

SERVICE ORIENTED PROGRAMMING

OBJECT ORIENTED PROGRAMMING

Page 12: OSGi Tutorial

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 reachedFlexibility must be built in by the programmer

Plug-in architecturesComponent architectures like OSGi minimize the coupling that is created by OO

Page 13: OSGi Tutorial

Software complexity

Page 14: OSGi Tutorial

Section III - OSGi Technology

Page 15: OSGi Tutorial

Architecture

Applications / modules share a single Java VMBetter class loading e.g. versioningIsolation/security between applicationsCommunication & collaboration between applicationsLife cycle management

install, start, stop, update, etc.

Page 16: OSGi Tutorial

Layering

Defined in a number of layers

OS + Hardware

Java Execution Env

Module

Life Cycle

Service

SECURITY

Applications (bundles)

Page 17: OSGi Tutorial

Layers: Execution Environment

Provides a defined context for applicationsDefines the available class library Not bound to a concrete JREOSGi Minimum EE

Matches most Java profilesFramework need OSGi MinimumImplementations can use more

CLDC/MIDP

J2SE

CDC/FP

OSGIMIN.

Page 18: OSGi Tutorial

Layers: Module Layer

Specifies class loading and packaging Modularization with classloadersProtectionVersioning

BUNDLE

BUNDLEBUNDLE

BUNDLE

BUNDLE

BUNDLE

BUNDLE

Page 19: OSGi Tutorial

Layers: Life Cycle Layer 1

System Bundle represents the FrameworkProvides an API for managing bundles

Install

Resolve

Start

Stop

Refresh

Update

Uninstall

BUNDLE

XBUNDLE

X-V2

BUNDLEB

BUNDLEM

BUNDLEA

SYSTEMBUNDLE

STATE (ACTIVE OR NOT)

MANAGES

Page 20: OSGi Tutorial

Layers: Life Cycle Layer 2

Bundle Activator is called at startupImplements two methods:

start(): Initialize and return quickly

stop(): CleanupBundle Context to access framework Start Level service to control the start/stop of groups of applications

INSTALLED

RESOLVED

UNINSTALLED

ACTIVE

STOPPING

STARTING

Page 21: OSGi Tutorial

Layers: Service Layer

Inside-VM service modelDiscover

based on interface or propertiesBind

to one or more services by

program control,

default rules, or

deployment configurationService Oriented Architectures (SOA) confusion

Web services bind and discover over the net

OSGi binds and discovers inside a Java VM

Page 22: OSGi Tutorial

Why services?

Collaboration modelSeparate contract from implementationDynamically discover and bind available implementations Components are reusableAllows alternate implementations

SERVICE CONTRACT

COMPONENTPROVIDES

USES

1188

Page 23: OSGi Tutorial

UPNPINITIAL PROVISIONING

NAME SPACEJINI

START LEVELIO CONNECTOR

WIRE ADMINXML PARSER

MEASUREMENT & STATEPOSITION

EXECUTION ENV.

APPLICATION MANAGERFOREIGN APP. ACCESS

SIGNED BUNDLESDECLARATIVE SERVICESDEVICE MANAGEMENT

SECURITY POLICIESFRAMEWORK LAYERINGINITIAL PROVISIONING

UPNPCONDITIONAL PERMISSIONS

2000 2001 2003 2006

R1

R2

R3

R4H

OM

E A

UTO

MA

TIO

N

VEH

ICLE

MO

BIL

E

FRAMEWORKHTTPLOG

DEVICE ACCESS

PACKAGE ADMINCONFIGURATION ADMIN

PERMISSION ADMINUSER ADMIN

PREFERENCESMETATYPE

SERVICE TRACKER

STANDARD SERVICES EVOLUTION

Page 24: OSGi Tutorial

Layers: The Security Layer

Based on Java 2 security

Permissions

Bundle signing

And a number of extra rulesDynamicFully under control of the operator

Fully controlled systems

Fully open systems

Page 25: OSGi Tutorial

The OSGi Implementations

Major Framework vendors are

ProSyst

Gatespace Telematics

IBM

Siemens

EspialOpen source implementations

Apache Felix

Eclipse Equinox

Gatespace KnopflerfishSee http://www.aqute.biz/osgi for an overview

Page 26: OSGi Tutorial

Benefits

Components are small

Easier to make, maintain and understandComponents are minimally coupled to other components

Gives reusabilityCollaborative model

Allows reuseWide Adoption

Bigger market, more components availableExcellent model for customizations and variations

Page 27: OSGi Tutorial

What Did We Learn

The OSGi Service Platform is kind of a Java Operating System

Execution Environment

Module layer

Service Layer

SecurityIt simplifies:

Deployment problems

Software composition

Software managementImplemented by many vendors and open source groups

Page 28: OSGi Tutorial

Section IV - OSGi concepts

Page 29: OSGi Tutorial

Framework Entities

OSGI FRAMEWORK

BUNDLE A{…} = SERVICE, DEFINED BY

JAVA INTERFACEBUNDLE B

{…}

BUNDLE C{…}

= BUNDLE

Page 30: OSGi Tutorial

Bundles & Services

A bundle is the deliverable application

Like a Windows EXE file

Content is a JAR fileA bundle registers 0..n servicesA service ...

is specified by an interface

may be implemented by multiple bundles

is bound to the bundle life-cycle

BUNDLE A{…}

BUNDLE B{…}

Page 31: OSGi Tutorial

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)

Page 32: OSGi Tutorial

What Happens With a Bundle?

The framework:

Reads the manifest

Installs code and resources

Resolves dependencies

Controls life cycle

During runtime the framework:

Calls the Bundle Activator start() & stop()

Manages the class path

Handles the service dependencies

BUNDLE A{…}

Page 33: OSGi Tutorial

SECTION V - HELLO WORLD

Page 34: OSGi Tutorial

First Project:Create

Create a new Java Project

Name, up to you

(examples use my.project)

Defaults are OKNext

Page 35: OSGi Tutorial

First Project: Classpath

Source: ok

Page 36: OSGi Tutorial

First Project: Classpath

Projects: nothingLibraries, we need to addthe osgi.jar. This can be found in the aQute.tutorial.runtimeproject, in the repo directoryAdd JARs -> selectChoose the repo directory

Page 37: OSGi Tutorial

Create a Hello (and Goodbye) World Bundle

Page 38: OSGi Tutorial

Create a Hello (and Goodbye) World Bundle

Create a Java source called World.java

Select src folder * > New > Class

Page 39: OSGi Tutorial

Create a Hello (and Goodbye) World Bundle

Set package name: my.projectSet Class Name: WorldAdd Interfaces: Add …

BundleActivatorFinish

Page 40: OSGi Tutorial

Source code for Hello/Goodbye World

The source should look similar to ... fill in the // TODO blocksstart – Called when the bundle is startedstop – When the bundle is stopped Some tips

F3 > Will jump to the selected type (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

package my.project;import org.osgi.framework.BundleActivator;import org.osgi.framework.BundleContext;public class World implements BundleActivator {

public void start(BundleContext context) throws Exception {System.out.println(“Hello World”); }

public void stop(BundleContext context) throws Exception { System.out.println(“Goodbye World”); }}

Page 41: OSGi Tutorial

Manifest code for Hello/Goodbye World

Each JAR file has a manifest

http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.htmlA 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: 1Unrecognized headers are ignored by the Java VM, this makes it possible to extend the manifestThe OSGi specifications have declared manydifferent headers

Vendor information

Imported and Exported packages

Native code

Page 42: OSGi Tutorial

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

bnd.bndLikely opens a separate applications

Open with Properties Editor

You can make this an association for *.bnd files (see Eclipse Preferences)

Page 43: OSGi Tutorial

Real code! Hello World (and Goodbye)

Add:

Private-Package. Defines the packages that should be included in your bundle You can use wildcards

my.project.*

Bundle-Activator, my.project.World

Create the bundle by selecting the bnd file, then * > Make BundleThis creates a JAR file, which is your first bundle!

Private-Package: my.project.*Bundle-Activator: \ my.project.World

Page 44: OSGi Tutorial

Bnd Translation

The bnd plugin translates the bnd.bnd file to the manifest, and embeds in the JAR fileuppercase HEADERS ARE copied to the manifest

Private-Package: my.projectBundle-Activator: \ my.project.World

Manifest-Version 1.0 Bnd-LastModified 1220347055030 Bundle-Activator my.project.World Bundle-ManifestVersion 2 Bundle-Name my.project Bundle-SymbolicName my.project Bundle-Version 0 Created-By 1.5.0_13 (Apple Inc.) Import-Package org.osgi.framework;version="1.3" Private-Package my.project Tool Bnd-0.0.265

BND

Page 45: OSGi Tutorial

BND

Import-Package is calculated from the referred MATCHED classes:

* (all) is default, !com.acme.* means do not import VERY GOOD DEFAULTS!

VERY LITTLE HEADERS NEED SPECIFYINGExport package expressions are matched against all packages on the class pathSIMPLIFIED SYNTAX FOR DECLARATIVE SERVICESUSEFUL IN:

ANT, ECLIPSE, COMMAND LINE, MAVENFull manual:

http://www.aqute.biz/Code/Bnd

Page 46: OSGi Tutorial

See What We Created

Double click on the my.project.jar shows contexts of Manifest.MF.

Page 47: OSGi Tutorial

Section VI - Launch a Framework

Page 48: OSGi Tutorial

Launch a Framework

Debug -> Open Debug Dialog …Select EquinoxFw (in Java Applications)

This launch file is provided by the aQute.tutorial.runtime project.

This starts an Equinox Framework with the Apache Felix 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 a Felix bundleInstalling and uninstalling is therefore simply managing the aQute.tutorial.runtime/work directory

Copy & Paste a file: gets installed

Delete a file: gets uninstalled

Page 49: OSGi Tutorial

Launch a Framework

Debug -> Debug Dialog …-> Debug

Page 50: OSGi Tutorial

Run the Hello World bundle

The launch runs a Framework consoleJust copy (Copy and Paste) the my.project.jar to the work directory

See “Hello World” in the console

Type “ss” (show status)

Look at the active bundles

the number for the my.project bundle. This is the bundle-id.

Page 51: OSGi Tutorial

Run the Hello World bundle

Type “stop <bundle-id>”

See the “Goodbye world”

The “Hello World” appears again because the fileinstall.jar bundle starts the bundle again

Page 52: OSGi Tutorial

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

Page 53: OSGi Tutorial

What Did We Learn

The unit of deployment of an OSGi Service Platform is a bundleHow to create a bundle with the bnd pluginHow to launch an Equinox environment with a defined set of bundles, and manage it with the fileinstall.jar bundleHow to start/stop bundlesHow the Equinox console worksWhy the Eclipse Self Hosting is not used

Page 54: OSGi Tutorial

Section VII – Component collaboration

Page 55: OSGi Tutorial

Collaborative model

OSGi is more than an Applet, MIDlet, Xlet runnerBundles can collaborate through:

service objects

package sharingFind and track service objects dynamically Framework fully manages this collaboration

Dependencies, security

Page 56: OSGi Tutorial

Collaborative model

BUNDLEBUNDLE

JAVA

OPERATING SYSTEM

HARDWARE

OSGI FRAMEWORK

SERVICEREGISTRY

PACKAGESPACKAGES

Page 57: OSGi Tutorial

Collaborative model

JAVA

OPERATING SYSTEM

HARDWARE

JAVA APPLICATION MANAGER

SERVICEREGISTRY

PACKAGESPACKAGES

MIDLET,XLET,

ORAPPLET

MIDLET,XLET,

ORAPPLET

NO NATIVE CODE

NO PACKAGE MANAGEMENT(VERSIONS!)

NO COLLABORATION

NO MANAGEMENT BUNDLES

Page 58: OSGi Tutorial

Class Path Issues

Standard Java:

Linear search in jars and directories

OSGi:

Network of class loaders

controlled by manifest headers

Q

P

R

P

Q-1.0

Q

Q-2.0

EXPORTED PACKAGE

IMPORTED PACKAGE WIRE

CONSTRAINT

Page 59: OSGi Tutorial

Package Resolution example

Bundle AExport org.osgi.service.log com.ibm.service.log com.ibm.j9Import javax.management javax.servlet.http

Framework org.osgi.framework javax.management

Bundle BExport ericsson.osgi javax.servlet javax.servlet.httpImport org.osgi.service.log javax.management

B RESOLVED

A RESOLVED

Page 60: OSGi Tutorial

Service Specifics 1

A service

a POJO

registered by a bundle

used by other bundles

specified by a Java interface

SERVICE

BIND REGISTER

LISTEN

Page 61: OSGi Tutorial

Service Specifics 2

Different cardinalities

1..1, 0..1, 0..nCan be discovered dynamically

Active search with query filter

Listener interfaceDynamic! Services can go away at any time!

package org.osgi.service.log;import org.osgi.framework.ServiceReference;public interface LogService { static final int LOG_ERROR= 1; static final int LOG_WARNING= 2; static final int LOG_INFO= 3; static final int LOG_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);}

Page 62: OSGi Tutorial

Service Specifics 3

Extensive notifications for life cyclesUnique idService Permission if security is enabledProperties

Powerful query language

Page 63: OSGi Tutorial

Manipulating Services

Access service registry with the BundleContext class ServiceRegistration represents the registration of this service

for private use of the implementer

to unregister or modify properties

ServiceReference to access the service and properties

for anyone who is interessted

ServiceRegistration registerService( String clss, Object srvc, Dictionary prprts)ServiceReference[] getServiceReferences( String clss, String fltr)Object getService( ServiceReference reference)boolean ungetService( ServiceReference rfrnc);

Page 64: OSGi Tutorial

Services and Best Practice

Subsystem binding, like a Log Service for example

Put business logic in POJOs that are not coupled to OSGi

use Bundle Activator to bind the POJOs

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 situationsHandle the dynamics, dynamic things will happen

Start Level service is not a way to handle dynamics

You can not control the initialization order

Page 65: OSGi Tutorial

What Did We Learn

OSGi provides a collaboration model that is based on

Services

Package sharingSharing is complicated, but the well defined specifications make it quite painless for bundle developersServices provide a very powerful dynamic programming modelSOA, without the communication overhead!

Page 66: OSGi Tutorial

Section IIX – Service Components

Page 67: OSGi Tutorial

Service Components

The dynamic nature makes it complicatedThe declarative service model simplifies the handling

Dependencies are defined in an XML file

Use bnd to get simpler definition Declarative Services:

Optionally depend on one or more services

Optionally provide a service

Optionally lazy initialized

ConfigurableHands-On: Refactor Helloworld bundle to use Log Service

Page 68: OSGi Tutorial

Service Components

Modify your project to

Change start() to activate()

And stop() to deactivate()

Note the Component Context

use the Log Service instead of System.out

Create a setlog method so DS can give us a log ServiceNext, we need to adapt our bnd.bnd file to create a component instead of an activator

package my.project;import org.osgi.service.component.*;import org.osgi.service.log.*;public class World {

LogService log; protected void activate(ComponentContext context) throws Exception {log.log(LogService.LOG_INFO, "Hello World");

} protected void deactivate(ComponentContext context) throws Exception {log.log(LogService.LOG_INFO, "Goodbye World");

} public void setLog(LogService log) {this.log = log; }}

Page 69: OSGi Tutorial

bnd Component Header

(bnd only)Service-Component ::= clause ( ‘,’ clause ) *clause ::= definition | <resource path>definition ::= <class-name> type ? ( ‘;’ ‘dynamic:=‘ list ) ? ( ‘;’ ‘optional:=‘ list ) ? ( ‘;’ ‘multiple:=‘ list ) ? ( ‘;’ name ‘=‘ <interface-name> ) *type ::= ‘?’ /* optional dynamic */ | ‘*’ /* optional dynamic multiple */ | ‘+’ /* dynamic multiple */ | ‘~’ /* optional */

Page 70: OSGi Tutorial

Bnd generates XML

Service-Component: \ ${p}.World; \ log=org.osgi.service.log.LogServicePrivate-Package: ${p}

<?xml version="1.0" encoding="utf-8" ?> <component name="my.project.World"> <implementation class="my.project.World"/> <reference name="log" interface="org.osgi.service.log.LogService" bind="setLog" /> </component>

OSGI-INF/my.project.component.World.xml

bnd.bnd change to :

Page 71: OSGi Tutorial

Declarative Services

A component can be any class. No specific interface required.The activate() and deactivate() protected methods are calledDependencies must be resolvedReferences can be bound by the setXXX method

Example: At any moment in between activate() and deactivate() there is a valid Log Service because we use the default static policy

Page 72: OSGi Tutorial

RElation DS-XML & Code

<?xml version="1.0" encoding="utf-8" ?> <component name="my.project.World"> <implementation class="my.project.World"/> <reference name="log" interface="org.osgi.service.log.LogService" bind="setLog" /> </component>

package my.project;import org.osgi.service.component.*;import org.osgi.service.log.*;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;}

}

OSGI-INF/MY.PROJECT.COMPONENT.WORLD.XML

Page 73: OSGi Tutorial

Run the Hello World Component

Create a new JAR with bndJust copy the my.project.jar to the work directory, gets installed

Nothing happensType “ss” (show status)

Type log, …, no good

Copy from repo to work the org.osgi.impl.service.log bundle.

Type now log in console

Notice that the Hello world message appears after the log service is started

Page 74: OSGi Tutorial

What Did We Learn

Programming with services can be complicatedThe Declarative Services model makes service programming simplerHow the component XML is constructedHow bnd provides a simplified syntaxHow to use the Log Service

Page 75: OSGi Tutorial

Section IX – Using the Http Service

Page 76: OSGi Tutorial

Using The Http Service

1 LISTEN FOR HTTP SERVICE

2 REGISTER AN HTTP SERVICE

3 REGISTER AN HTTP-SERVLET WITH HTTP SERVICE

4 CALL BACK WITH REQUESTS

1

23

4

Page 77: OSGi Tutorial

Using the Http Service: a Servlet

Create a servletA Servlet must implement a doGet methodJust say “Hello World”You should add ./repo/servlet.jar from the aQute.runtime project to your classpath

package my.project;import java.io.*;import javax.servlet.http.*;class HelloServlet extends HttpServlet { public void doGet(HttpServletRequest rq,

HttpServletResponse rsp)throws IOException {

PrintWriter pw = rsp.getWriter();pw.println("Hello World");

rsp.setContentType("text/plain"); }}

Page 78: OSGi Tutorial

Using the Http Service: The Component

We have a static dependency on the Http Service

When it is registered, we add our servlet

We log any errors, but we assume the log can be absent, so it will be optional

package my.project;import org.osgi.service.http.*;import org.osgi.service.log.*;public class World {

volatile LogService log; HttpService http; public void setHttp(HttpService http) {

this.http = http; try {http.registerServlet("/web", new

HelloServlet(), null, null); } catch (Exception e) {

LogService log = this.log;if (log != null) {

log.log( LogService.LOG_ERROR, "Registering /web", e);} } }…

Page 79: OSGi Tutorial

Using the Http Service: The Component

We need the unsetters and ungetters.The unsetHttp is not strictly needed because we will have a static depenencyNotice that the log is volatile because we can change it dynamically

… public void unsetHttp(HttpService http) {http.unregister("/web"); }

public void setLog(LogService log) {this.log = log; } public void

unsetLog(LogService log) {this.log = null; }}

Page 80: OSGi Tutorial

Using the Http Service: The bnd.bnd file

We use ${p}, bnd sets this to the bundle symbolic name/project name.The reference to the Http Service is mandatoryThe reference to the Log Service is optional, note the ‘?’ at the end of the service nameCopy the jar to the work dirTry the web at

http://localhost:8081/web

Private-Package: ${p}Service-Component: \${p}.World; \ http= org.osgi.service.http.HttpService; \ log = org.osgi.service.log.LogService?

Page 81: OSGi Tutorial

Web Component

Ah! There is no Http Service available!

Page 82: OSGi Tutorial

Web Component

Install a web server from the repo directory (in aQute.runtime): (osgi Http jar)

This will register an Http Service at port 8081

Try to reload the pageWorks!

Page 83: OSGi Tutorial

Section X – Making a Portal

Page 84: OSGi Tutorial

White Board Pattern

Htpp Service is wrongly designed:

Get Http Service

Register Servlet

Track that Http Service goes away

And, Http Service must track bundle to go awayWhite Board pattern reverses this model

Register a content provider

Http Service tracks all content providers

Content provider has nothing to do except register

Page 85: OSGi Tutorial

White Board Pattern

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 itThe 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 boardThere is a white-paper comparing a whiteboard approach with a non whiteboard approach.

http://www.osgi.org/documents/osgi_technology/whiteboard.pdf

Page 86: OSGi Tutorial

WhiteBoard Pattern for our Portal

Page 87: OSGi Tutorial

Portal

Designing our HtmlFragment serviceWe can use properties to provide a name and title for the HtmlFragment, so we can list themCommon practice is to define these on the service interfaceClients must register a service with this interface + the title and name property

package my.service;import java.io.*;import javax.servlet.http.*;public interface HtmlFragment { String NAME = "aQute.fragment.name"; String TITLE = "aQute.fragment.title"; void write(

HttpServletRequest request,PrintWriter pw) throws Exception;}

Page 88: OSGi Tutorial

Portal

We create the servlet as inner class so that it can refer to the Bundle Context we get in the component classNotice that log is volatile because we will make it optional in the bnd.bnd file

DS can set and unset it at will from different threads

package my.project;import java.io.*;import javax.servlet.http.*;import org.osgi.framework.*;import org.osgi.service.component.*;import org.osgi.service.http.*;import org.osgi.service.log.*;import my.service.*;public class World {volatile LogService log; HttpService http; BundleContext context; protected void activate(ComponentContext context) {this.context = context

.getBundleContext(); }public void setLog(LogService log) {

this.log = log; } public void unsetLog(LogService log) {this.log = null; }…

Page 89: OSGi Tutorial

Portal

Register the servlet and log any errors during the registration

Dont forget to unregister

public void setHttp(HttpService http) { this.http = http; try { http.registerServlet("/portal", new PortalServlet(), null, null); } catch (Exception e) { LogService log = this.log; if (log != null) { log.log(LogService.LOG_ERROR, "Registering /portal", e); } } } public void unsetHttp(HttpService http) { http.unregister("/portal"); }

Page 90: OSGi Tutorial

Portal

The PortalServlet is where the main code is.The doGet method gets called by the Http Service implementation when a request comes inFirst we get the name and then a list of HtmlFragments.Just some HTML cruft …Print the references

…class PortalServlet extends HttpServlet { public void doGet( HttpServletRequest rq, HttpServletResponse rsp) throws IOException { PrintWriter pw = rsp.getWriter(); try { String path = getPath(rq); ServiceReference[] refs = getHtmlFragmentReferences(); pw.println( "<html><head><link rel='stylesheet' href='http://www.osgi.org/www/ osgi.css' type='text/css' / ><title>Portal</title></head>"); pw.println( "<body><table><tr><td><a href='/ portal'>Portal</a></br>\n"); ServiceReference found = doBody( pw, path, refs);…

Page 91: OSGi Tutorial

Portal

Close the left columIf we found a matching name, let the HtmlFragment do its workClose the HTML page

… pw.println("</td><td>"); if (found != null) doHtmlFragment(rq, pw, found); pw.println( "</td></tr></table></body>"); } catch (Exception e) { doError(rsp, pw, e); } }…

Page 92: OSGi Tutorial

Portal

getPath makes the remainder of the request path clean of slashes

Get the HtmlFragment references by creating a filter, looking for all HtmlFragment services that have the name set

private String getPath( HttpServletRequest rq) { String path = rq.getPathInfo(); if (path != null && path.startsWith("/")) path = path.substring(1); return path; } private ServiceReference[] getHtmlFragmentReferences() throws InvalidSyntaxException { String filter = String.format( "(%s=*)", HtmlFragment.NAME); ServiceReference refs[] = context .getServiceReferences( HtmlFragment.class.getName(), filter); return refs; }

Page 93: OSGi Tutorial

Portal

The error handling to get a nicely formatted stack trace

Notice how we carefully check if the log is null. The log variable is volatile, but it could change to null between the null check and the use of it

private void doError( HttpServletResponse rsp, PrintWriter pw, Exception e) throws IOException { pw.println("<pre>"); pw.println("Error occurred\n"); e.printStackTrace(pw); pw.println("</pre>"); rsp.sendError( HttpServletResponse. SC_SERVICE_UNAVAILABLE); LogService x = log; if (x != null) { x .log( LogService.LOG_ERROR, "Error during http request", e); } }

Page 94: OSGi Tutorial

Portal

Give the HtmlFragment a chance to write the output

private void doHtmlFragment( HttpServletRequest rq, PrintWriter pw, ServiceReference found) throws Exception { HtmlFragment HtmlFragment = (HtmlFragment) context .getService(found); if (HtmlFragment != null) { try { HtmlFragment.write(rq, pw); } finally { context.ungetService(found); } } }

Page 95: OSGi Tutorial

Portal

Print the titles of the HtmlFragments in the service registry

private ServiceReference doBody( PrintWriter pw, String path, ServiceReference[] refs) { ServiceReference found = null; for (int i = 0; refs != null && i < refs.length; i++) { String name = (String) refs[i] .getProperty(HtmlFragment.NAME); String title = (String) refs[i] .getProperty(HtmlFragment.TITLE); if (name.equals(path)) { pw.printf("%s</br>\n", title); found = refs[i]; } else { pw .printf( "<a href=\"/portal/%s\"> %s</a></br>\n", name, title); } } return found; } }}

Page 96: OSGi Tutorial

Portal

bnd.bnd fileHttp Service is mandatoryLog Service is optional and dynamic (?)Run itTry it on http://localhost:8081/portal

Private-Package: ${p}Export-Package: my.serviceService-Component: ${p}.World; \

http=org.osgi.service.http.HttpService; \log =org.osgi.service.log.LogService?

Page 97: OSGi Tutorial

Portal

Page 98: OSGi Tutorial

What Did We Do?

Page 99: OSGi Tutorial

Section XI –Creating a Content Provider

Page 100: OSGi Tutorial

An Agent

OSGi has an extensive API for managing the bundles in the systemWe can use our portal to show the set of bundles. All we need to do is register a HtmlFragment serviceCreate a new project:

my.agentAdd to classpath:

the my.project

osgi.jar from repo

servlet.jaradd the COmponent class

package my.agent;import my.service.*;import java.io.*;import java.util.*;import javax.servlet.http.*;import org.osgi.framework.*;import org.osgi.service.component.*;public class Component implements HtmlFragment { BundleContext context; protected void activate( ComponentContext context) { this.context = context .getBundleContext(); }

Page 101: OSGi Tutorial

An Agent

And print the installed bundles

public void write( HttpServletRequest request, PrintWriter pw) throws Exception { pw.println("Bundles</br><table>"); Bundle[] bundles = context .getBundles(); pw.printf( "<tr><th>Id</th><th>Symbolic Name</ th><th>Location</th><th>Last Modified</th></tr>\n"); for (Bundle b : bundles) { pw.printf( "<tr><td>%s</td><td>%s</td><td> %s</td><td>%s</td></tr>\n", b.getBundleId(), b .getSymbolicName(), b .getLocation(), new Date(b .getLastModified())); } pw.println("</table>"); }}

Page 102: OSGi Tutorial

An Agent

Create a bnd.bnd fileThe provide: directive is used to specify the service it is registered underThe properties allow you to specify propertiesTry it!

Private-Package: ${p}Service-Component: ${p}.Component;\ provide:= \ my.service.HtmlFragment; \ properties:= \"aQute.fragment.name=agent,aQute.fragment.title=Agent"

Page 103: OSGi Tutorial

An Agent

Page 104: OSGi Tutorial

What We Did Not Learn

Security ArchitecturePermission ManagementSigned BundlesPackage ManagementBundle Life Cycle ManagementConfiguration Management and PreferencesServlet Support/Web ServerDevice AccessEvent Manager

UPNPUSER ADMINWIRE ADMINAPPLICATION MODELDEPLOYMENT ADMIN AND AUTOCONFDEVICE MANAGEMENT TREEINITIAL PROVISIONINGPOSITION, MEASUREMENT, STATEMETATYPEAND MUCH, MUCH, MORE...

Page 105: OSGi Tutorial

Conclusion

The OSGi R4 Specifications consists of considerable more details than elucidated in this tutorialThere 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 mainframesBoth in managed and unmanaged configurationsThe OSGi specifications solve real world problemsThe OSGi Alliance is working on making the OSGi specifications the standard for portable applications. Join us!

Page 106: OSGi Tutorial

The End

Further reading:

www.aQute.biz/OSGi/Resources

www.osgi.org

bundles.osgi.org

www.eclipse.org/osgi

www.ProSyst.com

www.osgibook.org