OSGi für Praktiker - BegrüssungPatrick Baumgartner
Pax
2OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Agenda
OSGi für Praktiker Vorstellung Ablauf des Workshops Administratives
3OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
OSGi für Praktiker
Praxis Buch OSGi im Enterprise Umfeld Build, Run, Manage Maven basierte Pax Tools
@OSGiBuch http://www.osgi-buch.com/
Vorstellung – Bernd Weber
Senior Consultant (Enterprise Backends) Co-Autor von OSGi für Praktiker
Interessens-Schwerpunkte– Öffentlicher Bereich– OpenSource Software– Infrastruktur-Projekte– IT-Standards (SAGA, V-Modell XT)
4OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Vorstellung – Oliver Braun
Professor für Programmierung und Verteilte Systeme Co-Autor von OSGi für Praktiker Autor von Scala – Objektfunktionale Programmierung
Interessens-Schwerpunkte– Funktionale Programmierung in Haskell– Objektfunktionale Programmierung in Scala– Entwicklung verteilter Systeme
5OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Vorstellung – Patrick Baumgartner
Senior Software Consultant @ Swiftmind Co-Autor von OSGi für Praktiker Initiator des OSGi Users' Forum Switzerland
Architektur, Coaching, Workshops, Trainings, Reviews & Entwicklung– Java Web Entwicklung mit Spring– OSGi mit Spring DM & Spring – Agile Software Development
6OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Ablauf des Workshops – 9:30
Begrüssung & Vorstellung 5' Einführung in OSGi 40' Projekt Setup 30' Bundle Playground 15' Web Console *
Kaffeepause 30'
7OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Ablauf des Workshops – 11:30
Deklarative Services 40' Blueprint Services 20'
Mittagspause 60'
Web Bundles 20' Fragmente & Integrationstests 40'
Kaffepause 30'
8OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Ablauf des Workshops – 15:30
Distributed OSGi 45' Outlook Scala Modules 25' Launcher 15' Fragen
Ende
9OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Administratives
10OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
11OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
EinleitungOliver Braun
Pax
22OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
OSGi
JSR 291: „Dynamic Component Support for Java SE“ (= OSGi-Spezifikation 4.1)
Aktuell 4.2– Distributed OSGi– Enterprise Edition– ...
33OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Die ersten Schritte
1999 Gründung OSGi Alliance– Open Service Gateway Initiative
(heute nur OSGi) 2000 Release 1– Fokus: Home Network Gateways
… 2003 Release 3– Fokus auch auf Automotive & Entertainment
44OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
... und die nächsten
2004 Eclipse Release 3 2005 Release 4– Mobile Devices
2009 Release 4.2 2010 Enterprise Edition– Web Applications– Distributed OSGi– JMX– …
55OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Bundles
Entspricht einem Modul JAR + OSGi-Manifest Manifest-Header– Bundle-SymbolicName– Bundle-Version– Bundle-Name– ...
66OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Beispiel-Manifest
Bundle-Name: Hello WorldBundle-SymbolicName: biz.gossipmonger.helloworldBundle-Description: A hello world bundleBundle-ManifestVersion: 2Bundle-Version: 1.0.0Export-Package:
biz.gossimonger.helloworld;version=“1.0.0“Import-Package:
org.osgi.framework;version=“1.3.0“
77OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Sichtbarkeit
Bei einem JAR ist der gesamte Inhalt sichtbar Ein OSGi-Bundle exportiert nur explizit
angegebene Packages Analog muss ein OSGi-Bundle auch explizit
exportieren Dies geschieht im Manifest:
Export-Package:biz.gossimonger.helloworld;version=“1.0.0“
Import-Package: org.osgi.framework;version=“1.3.0“
88OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
OSGi-Schichtenmodell
99OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Zustände und Übergänge
1010OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
BundleActivator
OSGi-Framework Bundle→
public interface BundleActivator {public void start(BundleContext context)
throws Exception;public void stop(BundleContext context)
throws Exception;}
1111OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
BundleContext
Bundle → OSGi-Framework
public interface BundleContext {…public Object getService
(ServiceReference ref);public ServiceRegistration registerService
(String[] clazzes, Object service, Dictionary properties);
…}
1212OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Serviceorientierung
Zusammenarbeit von Bundles über Dienste Ein Bundle kann n Dienste bereitstellen Dienst = Java-Objekt Schnittstelle = Java-Interface Ein Objekt kann mehrere Dienste bereitstellen
= mehrere Interfaces implementieren Dienste werden bei der ServiceRegistry– registriert– angefragt
Gekapselt in ServiceReference-Objekt
1313OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Interaktion der Schichten
1414OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
GossipMonger
1515OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
JobTimerpublic class JobTimer implements BundleActivator { private Thread t = null; public void start(BundleContext context) { Runnable task = new JobTimerRunnable(context); t = new Thread(task); t.start(); } public void stop(BundleContext context) { t.interrupt(); try { t.join(); } catch (InterruptedException e1) { e1.printStackTrace(); } }
1616OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
JobTimerRunnableprivate class JobTimerRunnable implements Runnable {
public void run() {ServiceTracker tracker = new
ServiceTracker(context, EventAdmin.class.getName(), null);
tracker.open();try {
// do something → next slide} catch (InterruptedException e) {
Thread.currentThread().interrupt(); } finally { tracker.close(); }
}}
1717OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
JobTimerRunnable (2) ...
try {while (true) {
// … time = …EventAdmin ea = (EventAdmin)
tracker.getService(); if (ea != null) { Event ev = new Event("jobtimer", time); ea.sendEvent(ev); } Thread.sleep(10000); } } catch (InterruptedException e) { ...
1818OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
GateKeeperpublic class GateKeeper
implements BundleActivator, EventHandler { public void start(BundleContext ctx) throws Exception { String[] topics = new String[]
{"biz/gossipmonger/jobtimer" }; Dictionary<String, Object> dict =
new Hashtable<String, Object>(); dict.put(EventConstants.EVENT_TOPIC, topics); ctx.registerService(EventHandler.class.getName(), this, dict); } public void stop(BundleContext ctx) throws Exception {} // … implements Eventhandler …}
1919OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
GateKeeper (2) private File watchedDir = new File("render_input");
public void handleEvent(Event event) { prepareWatchedDir(); String list[] = watchedDir.list(); System.out.println("GateKeeper found " + list.length + " entries in " + watchedDir); } private void prepareWatchedDir() { // … mkdir and stuff like that … }
Projekt SetupBernd Weber
Pax
2OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Agenda
Werkzeuge JobTimer Bundle erstellen Projekt GossipMonger aufsetzen GateKeeper Bundle integrieren
3OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
JDK 1.6.2x
2.2.x oder 3.0
3.6 mit Maven-Plugin m2eclipse http://m2eclipse.sonatype.org/sites/m2e
Werkzeuge – Standard
4OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Werkzeuge – OSGi
>= 2.0.xhttp://felix.apache.org/site/downloads.cgi
1.26.0http://www.aqute.biz/Bnd/Download
alias bnd='$JAVA_HOME/bin/java -jar /path/to/biz.aqute.bnd.jar'
Pax
5OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Werkzeuge – Pax Construct
Erzeugen und Verwalten von OSGi-Projekten und Bundles
Archetypen & Shell Skripte, z.B.:– pax-create-project– pax-create-bundle– pax-provision
Herunterladen, auspacken,bin-Verzeichnis in Suchpfad
http://wiki.ops4j.org/display/paxconstruct/Download
6OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Werkzeuge – Pax Runner
Zentrales Pax-Werkzeug Startet die wichtigsten OSGi
Plattformen Konfiguration über Profile Kann als Hintergrunddienst
gestartet werden Herunterladen, auspacken,bin-Verzeichnis in Suchpfad
http://paxrunner.ops4j.org/display/paxrunner/Download
7OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Werkzeuge – Pax Exam
Framework für Integrationstests Basiert auf JUnit und Pax Runner Konfiguration von Bundles,
Umgebungsparametern, Plattformen
Verwendung über Maven2-Dependencies oder Download
http://wiki.ops4j.org/display/paxexam/Download
8OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Agenda
Werkzeuge JobTimer Bundle erstellen Projekt GossipMonger aufsetzen GateKeeper Bundle integrieren
9OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
JobTimer – Maven-Struktur
JobTimer ist erstes Bundle mvn generate:archetype Vorschlag (Quickstart) übernehmen Metadaten eingeben:
groupId: biz.gossipmongerartifactId: jobtimerversion: 0.1.0package: biz.gossipmonger.jobtimer
10OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
JobTimer – POM anpassen
pom.xml in Eclipse importierenFile Import. . . Maven Existing Maven Project→ → →
Abhängigkeiten zu OSGi-APIs definieren<dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.core</artifactId> <version>4.2.0</version></dependency><dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.compendium</artifactId> <version>4.2.0</version></dependency>
Java-Version definieren Automatisiertes Testen konfigurieren
11OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
JobTimer.java in Maven-Struktur einbetten JAR erstellen (mvn package) Zum Bundle erweitern mit bnd– Steuerdatei osgi.bnd erstellen
JobTimer – Bundle erstellen
Bundle-Name: GossipMonger JobTimerBundle-SymbolicName: biz.gossipmonger.jobtimerBundle-Version: 0.1.0Bundle-Activator: biz.gossipmonger.jobtimer.JobTimerPrivate-Package: biz.gossipmonger.jobtimer-classpath: target/jobtimer-0.1.0.jar
– Aufruf von bnd osgi.bnd
12OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
JobTimer-Bundle Manifest
Ergebnis: JAR mit erweiterter Manifest-DateiBundle-ManifestVersion: 2Bundle-Name: GossipMonger JobTimerBundle-SymbolicName: biz.gossipmonger.jobtimerBundle-Version: 0.1.0Bundle-Activator: biz.gossipmonger.jobtimer.JobTimerPrivate-Package: biz.gossipmonger.jobtimerImport-Package: org.osgi.framework,org.osgi.service.event,org.osgi.util.tracker
Übrigens: bnd-Steuerdateien sind– vielseitig durch Variablen, Makros, …– kaskadierbar– gut lesbar
13OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
bnd-Steuerdatei integrieren
Ziel: Automatisierte Bundle-Erstellung Werkzeug: maven-bundle-plugin Verwendet bnd-Steuerdatei
<plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <version>2.1.0</version> <extensions>true</extensions> <configuration> <instructions> <_include>osgi.bnd</_include> </instructions> </configuration></plugin>
14OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
JobTimer-POM abrunden
Verpackungsart auf “Bundle” einstellen<packaging>bundle</packaging>
Hübschen Namen vergeben <name>GossipMonger JobTimer</name>
Bundle erstellen und in lokalem Maven-Repository ablegenmvn install
15OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Agenda
Werkzeuge JobTimer Bundle erstellen Projekt GossipMonger aufsetzen GateKeeper Bundle integrieren
16OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Gesamtprojekt anlegen
Gesamtprojekt heißt “GossipMonger“ Verwendung von Pax Constructpax-create-project
Metadaten angebengroupId: biz.gossipmongerartifactId: gossipmongerversion: 0.1.0
17OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
JobTimer importieren
JobTimer ist Taktgeber für GossipMonger Autarkes Bundle neben dem Projekt Import => Definition Abhängigkeit
$ cd gossipmonger$ pax-import-bundlegroupId: biz.gossipmongerartifactId: jobtimerversion: 0.1.0
Ergebnis: Erweiterung von provision/pom.xml<dependencies> <dependency> <groupId>biz.gossipmonger</groupId> <artifactId>jobtimer</artifactId> <version>0.1.0</version> </dependency></dependencies>
18OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Abhängigkeiten-Automatik
JobTimer nutzt u.a. EventAdmin=> Laufzeit-Abhängigkeit zu API und Impl.
Ziel: beim Plattformstart mitladen Werkzeuge: maven-pax-plugin, Profile
<plugin> <groupId>org.ops4j</groupId> <artifactId>maven-pax-plugin</artifactId> <version>1.4</version> <configuration> <provision> <param>--platform=felix</param> <param>--profiles=compendium,event</param> </provision> </configuration></plugin>
19OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Agenda
Werkzeuge JobTimer Bundle erstellen Projekt GossipMonger aufsetzen GateKeeper Bundle integrieren
20OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
GateKeeper Bundle
GateKeeper-Bundle ist erstes Projekt-Modul Ziel: Unmittelbare GossipMonger-Integration Werkzeug: pax-create-bundle (Pax Construct)
$ cd gossipmonger$ pax-create-bundlepackage: biz.gossipmonger.gatekeeperbundleName: biz.gossipmonger.gatekeeperbundleGroupId: biz.gossipmongerversion: 0.1.0
<modules> <module>poms</module> <module>provision</module> <module>biz.gossipmonger.gatekeeper </module></modules>
21OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
POM Zuständigkeiten
pom.xmlMaster-POM, allg. Definitionen, Module (Bundles)
biz.gossipmonger.gatekeeper/pom.xmlBundle-Daten
poms/pom.xmlglobale Abhängigkeiten (u.a. OSGi API) und Verweise auf die nachfolgenden POMs
poms/compiled/pom.xmlvordefinierte OSGi-Header, Einbindung osgi.bnd
poms/wrappers/pom.xmlOSGi-Wrapper für Drittbibliotheken
provision/pom.xmlspezifische Abhängigkeiten -> JobTimer
22OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
GateKeeper Metadaten
Viele Default-Werte passen bereits Nachziehen von Activator, Sichtbarkeit (, Name) Werkzeug: Erweiterung von osgi.bnd (, POM)
Bundle-Activator: ${bundle.namespace}.GateKeeperPrivate-Package: ${bundle.namespace}Export-Package:Import-Package: *
Überschreibt Standardwerte von Pax Construct GateKeeper ist nun startklar und “unsichtbar“
Bundle PlaygroundPatrick Baumgartner
2OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Apache Felix - Installation
Apache Felix Framework Distribution 3.0.7 herunterladen (http://felix.apache.org/site/downloads.cgi)
Entpacken Ins Verzeichnis felix-framework-3.0.7 wechseln
Apache Felix Framework starten java -jar bin/felix.jar
3OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Apache Felix – Befehle (1)
Mögliche Befehle auf der Konsole abrfagen g!help
Apache Felix Befehle
4OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Apache Felix – Befehle (2)
Apache Gogo Befehle
OBR Befehle
5OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Apache Felix - Status
Installierte Bundles und deren Status auf der Gogo Konsole abfragen
g!lb
6OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
JobTimer installieren
g!install file:/pathtofile/jobtimer.jar
g!lb
7OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
JobTimer starten
g!resolve 4
g!start 4
8OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
JobTimer deinstallieren
g!stop 4
g!start 4
9OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Apache Felix – Befehle (2)
Apache Gogo Befehle
OBR Befehle
10OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Apache Felix - Status
Installierte Bundles und deren Status auf der Gogo Konsole abfragen
g!lb
11OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Pax-Runner - Apache Felix
Apache Felix mit Pax-Runner starten $pax-run
12OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Pax-Runner - Profile
Pax-Runner mit bereits vorbereiteten Profilen starten http://paxrunner.ops4j.org/space/Pax+Runner+profiles+list https://scm.ops4j.org/repos/ops4j/projects/pax/runner-
repository/org/ops4j/pax/runner/profiles/
$pax-run --profiles=log
13OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Pax-Runner - Plattformen
Pax-Runner mit Apache Felix, Equinox, Knopflerfish starten
$pax-run --platform=equinox
14OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Bundles mit URL installieren
osgi>install http://www.osgi-buch.com/tutorial/jobtimer.jar
Status mit osgi>ss prüfen
Apache Felix Web ConsolePatrick Baumgartner
2OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Apache Felix Web Console
Weitere Informationen abrufbar unter http://felix.apache.org/site/apache-felix-web-console.html
$pax-run –-profiles=web,jsp,felix.webconsole
3OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Web Console
URL: http://localhost:8080/system/console Benutzername/Passwort: admin/admin
4OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Web Console - Bundles
5OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Web Console - Shell
6OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Web Console – Config (1)
7OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Web Console – Config (2)
8OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Security
Konsole unterstützt momentan sehr wenig Security:– Authentifizierung per HTTP Basic– Kein SSL– Standard User/Passwort
Für den sicheren Einsatz in Produktion muss noch einiges getan werden!
Declarative ServicesBernd Weber
Service Component Runtime, OSGi Service Compendium, Kap. 112
2OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Agenda
Überblick Enunciator Bundle integrieren Worker Bundle integrieren
3OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
OSGi APIs: mächtig, Verwendung teils schwierig API-Verwendung => Starke Kopplung => Widerspruch zu OSGi-Prinzipien => Maximale Forderung: POJOs ohne API-Bezug
Optimum: Deklaration von Verhalten/Bezügen Verschiedene deklarative Ansätze– Apache iPOJO– OSGi Declarative Services– OSGi Blueprint Container (Spring-DM)
Überblick
4OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Declarative Services Spec.
Teil des OSGi Standards Ausgereifte Technologie Konfiguration einzelner Komponenten per XML Verweis in Bundle-Header Service-Component
z.B. Service-Component: OSGI-INF/worker.xml
BundleActivator wird nicht benötigt Friedliches Nebeneinander von – Declarative Services (DS),– Blueprint Service Container und– Direkter API-Verwendung (BundleActivator
u.a.)
5OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Declarative Services Spec.
Komponenten-Deklaration in XML, u.a.– Komponenten-Name– Implementierungsklasse– Deklarieren angebotener Dienste (Interface)– Deklarieren referenzierter Dienste, jeweils• Interface• Kardinalitäten (optional)• bind / unbind-Methoden (optional)
– Laufzeitverhalten: statisch oder dynamisch– Konfigurationsdaten, ...
6OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Laufzeitumgebung (SCR)
DS-Bundles benötigen Laufzeitumgebung(Service Component Runtime, SCR)– Initialisieren– Herstellen / Aktualisieren von Referenzen– Aktivieren / Deaktivieren
SCR ist ein Bundle – was sonst :-) Manuelle Installation z.B. mittels
install http://archive.apache.org/dist/felix/ org.apache.felix.scr-1.0.8.jar
Verwendung Pax Runner Profil– Ergänzen von gossipmonger/pom.xml um<param>--profiles=[...],ds</param>
7OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Agenda
Überblick Enunciator Bundle integrieren Worker Bundle integrieren
8OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Enunciator Bundle
9OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Enunciator Bundle
Neues Teilprojekt im gossipmonger-Verzeichnis$ pax-create-bundlepackage: biz.gossipmonger.enunciatorbundleName: biz.gossipmonger.enunciatorbundleGroupId: biz.gossipmongerversion: 0.1.0
In Eclipse importieren, Beispiel-Dateien löschen Schnittstellen-Datei Enunciator.java erstellen in
src/main/java/biz/gossipmonger/enunciator
public interface EnunciatorService { void enunciate(String text);}
10OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Enunciator Bundle
EnunciatorServiceImpl erstellen– Package biz.gossipmonger.enunciator.internal– Entspricht Pax-Hierarchie der Bundle-Packages
Implementiert die Schnittstelle EnunciatorService Enthält optionale de-/activate-Methoden (DS) Nutzt dynamisch auftretende LogServices– Kein LogService vorhanden => Konsole
Ggf. Master-POM um Compiler-Einstellung >= Java 1.5 ergänzen
11OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Enunciatorpublic class EnunciatorServiceImpl implements EnunciatorService { List<LogService> logServices = new ArrayList<LogService>(); public void addLogService(LogService ls) { logServices.add(ls); enunciate("Enunciator got a LogService. Now there are " + logServices.size() + " references."); } public void removeLogService(LogService ls) { logServices.remove(ls); enunciate("Enunciator lost a LogService. Now there are " + logServices.size() + " references."); }
// further methods -> next slide}
12OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Enunciator (2)...public void enunciate(String text) { if (logServices.size() > 0) { for (LogService ls : logServices) { ls.log(LogService.LOG_INFO, text); } } else { System.out.println("Enunciator has no LogService; Message is: " + text);}protected void activate(ComponentContext cc) { System.out.println("Enunciator activated.");}protected void deactivate(ComponentContext cc) { System.out.println("Enunciator deactivated.");}...
13OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Dienst deklarieren
Neues Verzeichnis src/main/resources/OSGI-INF Darin Datei EnunciatorServiceImpl.xml anlegen Schema: http://www.osgi.org/xmlns/scr/v1.0.0
14OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Deklaration bekanntgeben
biz.gossipmonger.enunciator/osgi.bnd BundleActivator-Zeile löschen Neue (einzige) Zeile für Service-Component
15OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
GateKeeper 0.2.0
Abhängigkeit in GateKeeper-POM aufnehmen start/stop: ServiceTracker enunciatorTracker
private void enunciate(String text) { if (enunciatorTracker == null) { System.out.println([...]"No EnunciatorService tracker[...]" + text); } else { EnunciatorService enunciator = null; try { Object obj = enunciatorTracker.waitForService(500); enunciator = (EnunciatorService)obj; } catch (InterruptedException e) { System.out.println([...]"interrupted while waiting for Enunciator"); } if (enunciator != null) { enunciator.enunciate(ENUNCIATE_PREFIX+text); } else { System.out.println(ENUNCIATE_PREFIX+"(no EnunciatorService): " + text); } } }
16OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Test der Bundles
Wechsel in gossipmonger-Verzeichnis Aufruf von pax-provision Ergebnis:
Welcome to Felix================-> Bundle is starting...Bundle has started.Enunciator activated.Enunciator has no LogService; Message is: GateKeeper created watched directory [...]/runner/render_inputorg.osgi.service.event.Event [topic=biz/gossipmonger/jobtimer][FelixStartLevel] INFO biz.gossipmonger.enunciator - Enunciator got a LogService. Now there are 1 references.org.osgi.service.event.Event [topic=biz/gossipmonger/jobtimer]
17OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Agenda
Überblick Enunciator Bundle integrieren Worker Bundle integrieren
18OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Worker Service
19OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Worker Service Bundles
Worker-Zweck: XML in Ausgabeformat rendern Je ein Bundle für API und Implementierung Beide: package biz.gossipmonger.worker bundleName biz.gossipmonger.worker-api / -impl -api in biz/gossipmonger/worker -impl in biz/gossipmonger/worker/internal Worker-Service deklarativ anmelden
20OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Worker API
POM: nur Metadaten, gener. Properties und Name Private-/Export-Package in osgi.bnd anpassen
(Warnungen wegen gelöschtem internal-Verzeichnis)
Service: Schnittstelle für XML-In und File-Outpublic interface WorkerService { File process(File file); File process(File file, String outputDir); File process(InputStream is, String inputFilename); File process(InputStream is, String inputFilename, String outputDir);}
21OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Worker Implementierungpublic final class WorkerServiceImpl implements WorkerService { ... protected void activate(ComponentContext context) { enunciate("activating..."); configuredOutput = getConfiguredOutput(context); enunciate("activated."); } protected void deactivate(ComponentContext context) { enunciate("deactivated."); } public void setEnunciatorService(EnunciatorService es) { if (es != null) { enunciator = es; enunciate("EnunciatorService set."); } else { enunciate("setEnunciatorService called with null argument."); } } public void unsetEnunciatorService(EnunciatorService es) { enunciate("EnunciatorService unset."); enunciator = null; } ...}
22OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Worker Implementierung (2)public File process(File file) { return process(file, configuredOutput);}public File process(File file, String outputDir) { enunciate("Render from "+file.getAbsolutePath()); try { return process(new FileInputStream(file), file.getName(), outputDir); } catch (FileNotFoundException e) { enunciate(file.getAbsolutePath() + " is not there!"); return null; }}...public File process(InputStream is, String inputFilename, String outputDir) { enunciate("Rendering..."); try { File output = renderer.render(is, inputFilename, outputDir); enunciate("Rendered to "+output.getAbsolutePath()); return output; } catch (Exception ex) { enunciate("Error while rendering: "+ex.getMessage()); return null; }}
23OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Worker Implementierung (3)
In-Bundle Properties: nach der Mittagspause
private String getConfiguredOutput(ComponentContext context) { String setBy = "default"; Properties props = getBundleContainedProperties(context); String outputDir = props.getProperty(PROPERTYNAME_OUTPUT_DIR); if (outputDir != null && outputDir.isEmpty() == false) { setBy = "in-bundle properties"; } else { outputDir = (String) context.getProperties().get(PROPERTYNAME_OUTPUT_DIR); if (outputDir != null && outputDir.isEmpty() == false) { setBy = "service properties"; } else { outputDir = DEFAULT_OUTPUT_DIR; } } enunciate("Output Directory is set by "+setBy+" to "+outputDir+"."); return outputDir;}...
24OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
<?xml version="1.0" encoding="UTF-8"?><component name="biz.gossipmonger.worker"> <implementation class="biz.gossipmonger.worker.internal.WorkerServiceImpl"/> <reference name="Enunciator" interface="biz.gossipmonger.enunciator.EnunciatorService" cardinality="0..1" policy="dynamic" bind="setEnunciatorService" unbind="unsetEnunciatorService"/> <service> <provide interface="biz.gossipmonger.worker.WorkerService"/> </service> <property name="worker.outputDir" type="String" value="render_outpdf"/></component>
Komponente deklarieren
java/main/resources/OSGI-INF/WorkerServiceImpl.xml
25OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Sonstige Anpassungen
Worker-Impl POM– Name– Abhängigkeiten (Worker-API, Enunciator, iText)
GateKeeper– ServiceTracker für WorkerService– processFile ruft nächstbesten WorkerService auf– postResult verkündet asynchron per EventAdmin– POM: Abhängigkeiten zu Worker-API und OSGi
Service Compendium wegen EventAdmin
26OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Test der Bundles
Aufruf von pax-provision im gossipmonger-Verz. Ablegen beliebiger XML-Datei in render_input:
GateKeeper: Processing deploy-pom.xmlWorkerServiceImpl: Render from /home/osgi/osgibuch/gossipmonger/runner/render_input/deploy-pom.xmlWorkerServiceImpl: Rendering...WorkerServiceImpl: Rendered to /home/osgi/osgibuch/gossipmonger/runner/render_outpdf/deploy-pom.pdfGateKeeper: Moving processed file to archive dir ./render_archive
Enunciator-Bundle anhalten (stop <bundle-id>):stop 5[...] WorkerServiceImpl: EnunciatorService unset.Enunciator deactivated.Enunciator has no LogService; Message is: Enunciator losta LogService. Now there are 0 references.DEBUG biz.gossipmonger.enunciator - BundleEvent STOPPED
Blueprint ServicesPatrick Baumgartner
2OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Überblick
Sehr ähnlich zu Declarative Services Standard seit OSGi R4.2 Basiert auf den Ideen von Spring DM 1.0 Spring DM 2.0 ist die Referenzimplementation (RI) Aktuelle Implementationen sind Apache Aries Blueprint
& Eclipse Gemini Blueprint (Incubator)
3OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Einführung
Verwendung von Legacy Code Keine Abhängigkeit zur OSGi API Konstruktor & Setter Injection Behandlung von OSGI Dynamics XML-Files befinden sich in OSGI-INF/blueprint– Alternativer Pfad im Manifest Header definiert:– Bundle-Blueprint: OSGI-INF/blueprint/config.xml
Verwendung Pax Runner Profil– Ergänzen von gossipmonger/pom.xml um<param>--profiles=[...],blueprint</param>
4OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Blueprint Idee
Spring Dynamic Modules - OSGi with Spring Framework
Imported Service
Exported Service
Bean
Blueprint Framework
OSGI Framework
JVM
Application Context
Application Context
Application Context
5OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Blueprint Bundle
Blueprint Bundle
Blueprint Extender
Metadata
XML
Blueprint Bundle
Metadata
XML
6OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Blueprint Konfiguration (Auszug)
7OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Skilled Worker Service
Web BundlesPatrick Baumgartner
2OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Überblick
RFC 66: OSGi Web Container Spezifikation Mächtiger als OSGi HttpService Web Bundle = Web-Applikation mit OSGi WAR + OSGi Metadata + Web-ContextPath Header JEE APIs wie z.B. JPA mit LazyLoading verwendbar Wrapped WAR Support
3OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Einführung
Unterstützt WAR und WAB Dateien WAB benötigt zusätzlichen Manifest Header– Web-ContextPath: /myServlet
WAR mit URL Handler in ein WAB gewandelt– Webbundle:file:///myWebapp.war?Web-
ContextPath=/myServlet Implementation von Spring DM (RI) und Pax Web Deployment wie jedes andere Bundle
4OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Applikationsarchitektur
Spring Dynamic Modules - OSGi with Spring Framework
OSGi Framework
JVM
Web Container Bundle 1 Bundle 2
WebApp WebApp
Bundles und WebApps sollen Services teilen!
5OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Demo
6OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
WebMonitor
Fragmente & IntegrationstestsBernd Weber
2OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Agenda
Fragmente Pax Exam Einfacher Integrationstest Erweiterter Test
3OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Ergänzen oder erweitern ein Wirts-Bundle Sind selbst ein Bundle, aber– nur mit Wirt lebensfähig– ohne eigenen Class Loader– ohne BundleActivator
Können beliebigen Inhalt haben Werden beim Resolve dem Wirt hinzugefügt Wirt + Fragment = Laufzeit-Bundleinhalt Einsatz: Übersetzungen, Konfigurationen,
Stylesheets, Skins
Fragmente
4OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Worker-Konfiguration
Ausgabeordner von WorkerService konfigurierbarpublic final class WorkerServiceImpl implements WorkerService { private static final String BUNDLE_PROPERTIES_FILE = "worker.properties"; private static final String PROPERTYNAME_OUTPUT_DIR = "worker.outputDir"; private static final String DEFAULT_OUTPUT_DIR = "render_output"; String configuredOutput = DEFAULT_OUTPUT_DIR; ... private String getConfiguredOutput(ComponentContext context) { String setBy = "default"; Properties props = getBundleContainedProperties(context); String outputDir = props.getProperty(PROPERTYNAME_OUTPUT_DIR); if (outputDir != null && outputDir.isEmpty() == false) { setBy = "in-bundle properties"; } else { ... } enunciate("Output Directory is set by "+setBy+" to "+outputDir+"."); return outputDir; }}
5OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Worker-Konfiguration (2)...private Properties getBundleContainedProperties(ComponentContext context) { Properties properties = new Properties(); URL url = context.getBundleContext().getBundle(). getResource(BUNDLE_PROPERTIES_FILE); if (url == null) { enunciate(BUNDLE_PROPERTIES_FILE+" file not found in bundle."); } else { try { InputStream is = url.openStream(); properties.load(is); is.close(); } catch (IOException e) { enunciate("Error reading bundle properties file: "+ e.getMessage()); } } return properties;}...
6OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Erstellen des Fragments
pax-create-bundle im gossipmonger-Verzeichnispackage: biz.gossipmonger.workerbundleName: biz.gossipmonger.worker-configbundleGroupId: biz.gossipmongerversion: 0.1.0
src/main/resources/worker.properties erstellen
osgi.bnd mit Fragment-Header
7OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Fragment nutzen
worker-config POM– <name>GossipMonger Worker Configuration</name>– Abhängigkeiten löschen
Aufruf von pax-provision lädt Fragment mit =>
WorkerServiceImpl: EnunciatorService set.WorkerServiceImpl: activating...WorkerServiceImpl: Output Directory is set by in-bundleproperties to render_outfragment.WorkerServiceImpl: activated.
Fragment-Bundle bleibt im Status resolved
8OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Agenda
Fragmente Pax Exam Einfacher Integrationstest Erweiterter Test
9OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Integrationstests
Manuelles Bundle-Testen ist ineffizient pax-provision ist kein Testverfahren Bundle-Aktionen sind mit Unit-Tests nicht testbar– Ausgehende JobTimer-Events– Reaktion GateKeeper auf JobTimer-Events– Versand von Nachrichten über den Enunciator– Korrektes WorkerService-Ausgangsverzeichnis– Datei für WorkerService bereitstellen– Renderer-Artefakt (PDF) erstellt
10OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Pax Exam
Automatisiertes Testen von Bundle-Aktionen Bundle erstellen für Integrationstest-Modul:
$ mvn archetype:generate \ -DarchetypeGroupId=org.ops4j.pax.exam \ -DarchetypeArtifactId=maven-archetype-paxexam-junit \ -DarchetypeVersion=1.2.0
Metadaten angeben:groupId: biz.gossipmongerartifactId: biz.gossipmonger.test.workerversion: 0.1.0package: biz.gossipmonger.test.worker
11OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
POM anpassen
Parent-Abschnitt wie übrige Bundles ändern Compiler-Plugin, osgi-core und logging-
Dependency entfernen SNAPSHOP-Postfixes von Pax-Exam-Deps
entfernen Alle Projekt-Bundles als Deps eintragen
12OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Generierter Testfall
Verwendung des Pax Exam TestRunners BundleContext wird „injiziert“
13OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Agenda
Fragmente Pax Exam Einfacher Integrationstest Erweiterter Test
14OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Einfacher Integrationstest
15OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Einfacher Integrationstest
Test für WorkerService Soll PDF-Erstellung anhand InputStream prüfen Bundles im Test: Enunciator, Worker-API, -Impl
und iText als PDF-Renderer JobTimer, GateKeeper, Fragment bleiben außen vor
Inputdatei src/test/resources/test.txt anlegen mit beliebigem Inhalt
SimpleWorkerServiceTest.java im Package biz.gossipmonger.test.worker erstellen
Benötigte Bundles werden „konfiguriert“
16OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
SimpleWorkerServiceTest@RunWith(JUnit4TestRunner.class)public class SimpleWorkerServiceTest { @Configuration public static Option[] configure() { return options( provision( // Infrastructure bundles mavenBundle().groupId("org.osgi").artifactId("org.osgi.compendium"), mavenBundle().groupId("org.apache.felix"). artifactId("org.apache.felix.eventadmin"), mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.scr"), // Project bundles mavenBundle().groupId("biz.gossipmonger"). artifactId("biz.gossipmonger.worker-api").versionAsInProject(), mavenBundle().groupId("biz.gossipmonger"). artifactId("biz.gossipmonger.worker-impl").versionAsInProject(), mavenBundle().groupId("biz.gossipmonger"). artifactId("biz.gossipmonger.enunciator").versionAsInProject(), mavenBundle().groupId("biz.gossipmonger.com.itextpdf"). artifactId("biz.gossipmonger.com.itextpdf.itext").versionAsInProject() ) ); } // Test method see next slide}
17OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Inhalt Test-Methode
@Testpublic void workerServiceResultExists(final BundleContext bundleContext) { ServiceReference ref = bundleContext.getServiceReference( biz.gossipmonger.worker.WorkerService.class.getName()); Assert.assertNotNull(ref); WorkerService worker = (WorkerService) bundleContext.getService(ref); Assert.assertNotNull(worker); try { String filename = "test.txt"; URL url = bundleContext.getBundle().getResource(filename); InputStream is = url.openStream(); File file = worker.process(is, filename); Assert.assertNotNull(file); String filePath = file.getAbsolutePath(); Assert.assertTrue(filePath + " does not exist", file.exists()); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); }}
18OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Integrationstest ausführen
Ggf. Bundles in lokalem Maven-Repo installieren(mvn install)
Wechsel in Verz. biz.gossipmonger.test.worker Aufruf von mvn test
Oder: Eclipse -> Run As -> JUnit Test
19OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Agenda
Fragmente Pax Exam Einfacher Integrationstest Erweiterter Test
20OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Erweiterter Test
21OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Erweiterter Test
Test der automatisierten Verarbeitung Input-Datei in Eingangsverzeichnis erzeugen Nach spätestens 12 Sekunden muss Ergebnisdatei
in konfig. Verzeichnis da sein!
ExtendedWorkerServiceTest.java im Package biz.gossipmonger.test.worker erstellen
Bundles: wie vorher, zudem JobTimer, GateKeeper, Worker-Config
Log-Profil Test auf Felix und Equinox
22OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Erweiterter Test: Beteiligte@RunWith(JUnit4TestRunner.class)public class ExtendedWorkerServiceTest { @Configuration public static Option[] configure() { return options( felix(), equinox(), logProfile(), provision( ... mavenBundle().groupId("biz.gossipmonger"). artifactId("jobtimer").versionAsInProject(), mavenBundle().groupId("biz.gossipmonger"). artifactId("biz.gossipmonger.gatekeeper").versionAsInProject(), mavenBundle().groupId("biz.gossipmonger"). artifactId("biz.gossipmonger.workerconfig"). versionAsInProject().noStart(), ... ) ); } // See next slides}
23OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Erweiterter Test: Setup
private class TestEventHandler implements EventHandler { public void handleEvent(Event event) { System.out.println(event.toString()); resultPath = (String) event.getProperty("output"); }}
@Beforepublic void setup(final BundleContext context) { ... // clean or create input dir String[] top = new String[] { "biz/gossipmonger/gatekeeper" }; Map<String, Object> map = new Hashtable<String, Object>(); map.put(EventConstants.EVENT_TOPIC, top); context.registerService(EventHandler.class.getName(), new TestEventHandler(), (Dictionary<String, Object>) map); ... // create test file from scratch in input dir}
resultPath = Ausgabepfad der gerenderten Datei Event kommt vom GateKeeper.postResult
24OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Test-Methode
@Test(timeout=12000) klappt leider nicht wegen Laden der Plattform und Bundles
=> Eigener Sekundenzähler bis 12 (sollte für JobTimer und zum Rendern reichen)
Zu jeder Sekunde wird resultPath auf Inhalt geprüft Steht was drin:– Pfad-Existenz prüfen– Prüfen, ob Datei– Prüfen, ob Verzeichnis der Fragment-
Konfiguration entspricht
25OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Test-Methode@Testpublic void workerServiceResultEventOccurs(final BundleContext bundleContext) { synchronized (this) { int i = 0; while (i < 12 && resultPath == null) { try { System.out.println("Wait a second (" + ++i + ")"); wait(1000); } catch (InterruptedException e) { assertTrue("Testcase was interrupted", false); } } if (i == 12) { assertTrue("Testcase has timed out", false); } } File file = new File(resultPath); assertTrue("Result path doesn't exist.", file.exists()); assertTrue("Result path is no file.", file.isFile()); String parentName = file.getParentFile().getName(); assertEquals("Result path is not configured by in-bundle properties file", "render_outfragment", parentName);}
26OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Erweiterten Test ausführen
Ggf. Bundles in lokalem Maven-Repo installieren Wechsel in Verz. biz.gossipmonger.test.worker Aufruf von mvn test
Oder: Eclipse -> Run As -> JUnit Test
Distributed OSGiPatrick Baumgartner
OSGi Compendium Spezifikation Kapitel 13
2OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Überblick
RFC 119: Remote Services
Services einer Remote Maschine benutzen– Andere Maschine, verbunden über ein Netzwerk– Andere JVM, andere Adresse oder Sprache
ProduziertService A
KonsumiertService A
3OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Einführung
Sehr dynamisches System Implementiert durch Eclipse ECF und Apache CXF (RI) RFC übernimmt die Spezifikation der Schnittstelle Transport ist Sache des Frameworks– z.B. Apache CXF → WebServices
Zusätzliche Schritte im vergleich zu lokalen Services– Registration / Security– Lookup (Network Discovery)– Aufräumen
4OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Konfiguration (Service und Konsument)
service.exported.interfaces– *– org.example.BarService,org.example.FooService
service.exported.configs– org.apache.cxf.ws – org.apache.cxf.rs– ecf.generic.server
5OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Konfiguration (Apache CXF WS)
org.apache.cxf.ws.httpservice– http://localhost:9090/myRemoteService
org.apache.cxf.ws.httpservice.contex– /myRemoteService
org.apache.cxf.ws.frontend – jaxws
org.apache.cxf.ws.databinding– jaxb / aegis
6OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Konfiguration (Apache CXF RS)
org.apache.cxf.ws.httpservice– http://localhost:9090/myRemoteService
org.apache.cxf.ws.httpservice.contex– /myRemoteService
org.apache.cxf.rs.provider – true / false
org.apache.cxf.rs.provider.expected – true / false
org.apache.cxf.rs.provider.globalquery – true / false
org.apache.cxf.ws.databinding– jaxb / aegis
7OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Remote LogServer (Standalone)
LogServer implementiert mit Spring DM META-INF/spring/bundle-context-osgi.xml
8OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Remote LogClient (enunciator-remote)
Declarative Services– Default: OSGI-INF/remote-service/remote-services.xml – Manifest: Remote-Service: META-INF/osgi
Z.B.: Fragment für Enunciator
9OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Protokoll - Test
10OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Lab - DOSGi
11OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
DOSGi Discovery
RFC 119 beschreibt einen Weg um Metadata eines Remote Services zu publizieren/beziehen
Protokolle: Zeroconf/Bonjour, ServiceLocation Protocol (SLP), Apache Zookeper, Files
ProduziertService A
KonsumiertService A
11OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Outlook
Aliens - Bundles from Outer (Java) Space
Oliver Braun
22OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Scala
Vielversprechende Sprache auf der JVM Hybridsprache OOP + FP– Objektfunktional / Postfunktional
Natürliche Integration mit Java Interfaces mit Implementierung -> Traits Funktionale Programmierung– Funktionen– Higher Order Functions– Pattern Matching („verallgemeinertes switch“)
(fast) Alles kann Alles enthalten
33OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Reine Objektorientierung Alles ist ein Objekt– Keine Primitives in der Sprache (aber auf der JVM)
Int, Float, ...– Keine besondere Behandlung von Arrays– Keine static Member => Singleton Objekte
class Example { ...}object Example { ...}
44OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Typsystem
55OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Statisch typisiert
Lokaler Typinferenzmechanismus– Statt in Java:Map<Integer,String> myMap =
new Map<Integer,String>();– In Scalaval myMap: Map[Int,String] = Map()
– Oderval myMap = Map[Int,String]()
– Oder sogarval myMap = Map(1 -> “eins“, 2 -> “zwei“)
66OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Klassenparameter und „Operatoren“// Javaclass Rational {
final int x;final int y;Rational(int x, int y) {
this.x = x;this.y = y;
}public Rational add(Rational other) {
return new Rational(x+other.x,y+other.y);}
}// Scalaclass Rational(x: Int, y: Int) {
def +(other: Rational) =Rational(x+other.x, y+other.y)
} // a + b
Rational a = new Rational(1,2);Rational a = new Rational(2,3);Rational c = a.add(b)
val a = new Rational(1,2);val b = new Rational(2,3);val c = a + b
77OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
ScalaModules – DSL für OSGi// JavaServiceReference reference = context.getServiceReference(Greeting.class.getName());if (reference != null) { try { Object service = context.getService(reference); Greeting greeting = (Greeting) service; if (greeting != null) { System.out.println(greeting.welcome()); } else { System.out.println("No Greeting service available!"); } } finally { context.ungetService(reference); }} else { System.out.println("No Greeting service available!");}// Scalacontext findService withInterface[Greeting] andApply { _.welcome } match { case None => println("No Greeting service available!") case Some(welcome) => println(welcome)}
88OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
OSGi-Bundle in Scalapackage biz.gossipmonger.chirp
import org.osgi.service.log.LogServiceimport org.osgi.framework.{ BundleActivator, BundleContext, ServiceReference }import org.eclipse.scalamodules._
import com.tedneward.scitter._
class Chirp extends BundleActivator {
override def start(context: BundleContext) { // → next Slide }
override def stop(context: BundleContext) {}
}
99OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
OSGi-Bundle in Scala… override def start(context: BundleContext) { val chirp = new LogService { override def log(level: Int, message: String) { log(null, level, message, null) } override def log(level: Int, message: String, exception: Throwable) { log(null, level, message, exception) } override def log(sr: ServiceReference, level: Int, message: String) { log(sr, level, message, null) } override def log(sr: ServiceReference, level: Int, message: String, exception: Throwable) { val twitter = new Scitter("enunciator","geheim") twitter update message } } context createService chirp }…
1010OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
... und wie geht's weiter
Anpassen des POM– Abhängigkeiten zur Scala-Bibliothek, ...
Übersetzen mit Maven ScalaModules und ScalaBibliothek-Bundles in die
Datei für den Pax Runner Wegen Scitter noch zusätzliche Abhängigkeiten Pax Runner starten und los geht's
LauncherBernd Weber
2OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Agenda
Ziele Spezifikation Implementierung Konfiguration
3OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Java-Applikation Kein Pax Runner o.ä. notwendig Selbständiges Laden/Starten der Bundles Verschiedene Bundle-Quellen nutzbar Erweiterbar Wahl der OSGi-Plattform Debug-Unterstützung WebStart – Analogie
Launcher - Ziele
4OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Launcher – Spezifikation
OSGi Framework Launching APIOSGi Core Specification, Kap. 4.2 Frameworks und 6.2 org.osgi.framework.launch
FrameworkFactory erzeugt System Bundle Framework-Interface = Bundle-Methoden +
init/start/stop/... BundleContext nach init() vorhanden Bundles installieren nach init() möglich Bundles starten nach start() möglich waitForStop() blockiert bis Framework-Ende
5OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Implementierung
Launcher ist eigenständiges Projekt Keine Abhängigkeit zum GossipMonger Neues Verzeichnis, darin Aufruf von
$ mvn archetype:generateChoose a number: (...): <default Quickstart>groupId: biz.gossipmongerartifactId: biz.gossipmonger.launcherversion: 0.1.0package: biz.gossipmonger.launcher
6OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
POM Abhängigkeiten
Framework-Klasse sollte im ClassPath liegen => Framework-Abhängigkeit definieren<dependency> <groupId>org.apache.felix</groupId> <artifactId>org.apache.felix.framework</artifactId> <version>2.0.2</version></dependency>
Infrastruktur-Abhängigkeiten definieren– Maven-Dependencies mit scope „runtime“– org.ops4j.pax.url / pax-url-mvn (URL-Handler)– org.ops4j.pax.url / pax-url-obr (URL-Handler)– org.apache.felix / org.osgi.service.obr (OBR API)– org.apache.felix / org.apache.felix.bundlerepository (OBR Admin)
7OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Der Launcher im Groben
System Bundle erzeugen und starten Bundle-Locations ermitteln und Bundles
aktivieren (installieren und starten) für– Infrastruktur-Bundles– Ggf. Debug-Bundles– Applikations-Bundles
Auf Framework-Ende warten
8OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Implementierung Framework Factory erzeugenprivate FrameworkFactory getFrameworkFactory() throws Exception { String filename = "META-INF/services/org.osgi.framework.launch. FrameworkFactory"; List<String> content = getResourceContent(filename); ... // check for exactly one entry return (FrameworkFactory) Class.forName(content.get(0)).newInstance();}– Class.forName für Java < 6– ServiceLoader.load für Java >= 6
FrameworkFactory factory = getFrameworkFactory();Map<String, String> map = getFrameworkSettings(args);Framework framework = factory.newFramework(map);framework.start();
System Bundle erzeugen und starten
9OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Implementierung
Locations der Infrastruktur-Bundles ermitteln– Methode getInfrastructureBundles– liefert List<String> mit Bundle Locations– Ergebnis: JARs aus „lib“ außer System Bundle
Bundles starten– Methode activate(context, locations)– 1. Schleife installiert Bundles:
Bundle b = context.installBundle(location);– 2. Schleife startet Bundles (Fragmente nicht)
bundle.start(); Analog für Debug und Application Bundles
10OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun
Launcher – Konfiguration
# The bundle cache shall be cleaned at every startorg.osgi.framework.storage.clean = onFirstInit...
Framework / Umgebung konfigurierenMETA-INF/settings/FrameworkSettings
Debug-Bundles konfigurierenMETA-INF/settings/DebugBundles
Applikations-Bundles konfigurierenMETA-INF/settings/ApplicationBundles# Install Apache SCR and Event Admin Service from OBRobr:org.apache.felix.scr/1.4obr:org.apache.felix.eventadmin/1# Install PAX Logging from Mavenmvn:org.ops4j.pax.logging/pax-logging-api/1.4mvn:org.ops4j.pax.logging/pax-logging-service/1.4# Install the GossipMonger Bundles from Mavenmvn:biz.gossipmonger/jobtimer/0.2.0...