OSGi für Praktiker - Web Applikationen und verteilte Systeme mit OSGi

  • 2,122 views
Uploaded on

 

More in: Technology , Education
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
2,122
On Slideshare
0
From Embeds
0
Number of Embeds
3

Actions

Shares
Downloads
40
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. OSGi für Praktiker - BegrüssungPatrick Baumgartner Pax
  • 2. Agenda  OSGi für Praktiker  Vorstellung  Ablauf des Workshops  AdministrativesOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  • 3. OSGi für Praktiker  Praxis Buch  OSGi im Enterprise Umfeld  Build, Run, Manage  Maven basierte Pax Tools  @OSGiBuch  http://www.osgi-buch.com/OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 3
  • 4. 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)OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  • 5. 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 OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  • 6. 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 DevelopmentOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  • 7. Ablauf des Workshops – 9:30  Begrüssung & Vorstellung 5  Einführung in OSGi 40  Projekt Setup 30  Bundle Playground 15  Web Console *  Kaffeepause 30OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  • 8. Ablauf des Workshops – 11:30  Deklarative Services 40  Blueprint Services 20  Mittagspause 60  Web Bundles 20  Fragmente & Integrationstests 40  Kaffepause 30OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  • 9. Ablauf des Workshops – 15:30  Distributed OSGi 45  Outlook Scala Modules 25  Launcher 15  Fragen  EndeOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 9
  • 10. AdministrativesOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 10
  • 11. Einleitung Oliver Braun PaxOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 1
  • 12. OSGi  JSR 291: „Dynamic Component Support for Java SE“ (= OSGi-Spezifikation 4.1)  Aktuell 4.2 – Distributed OSGi – Enterprise Edition – ...OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  • 13. 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 & EntertainmentOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 3
  • 14. ... 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 – …OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  • 15. Bundles  Entspricht einem Modul  JAR + OSGi-Manifest  Manifest-Header – Bundle-SymbolicName – Bundle-Version – Bundle-Name – ...OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  • 16. Beispiel-Manifest Bundle-Name: Hello World Bundle-SymbolicName: biz.gossipmonger.helloworld Bundle-Description: A hello world bundle Bundle-ManifestVersion: 2 Bundle-Version: 1.0.0 Export-Package: biz.gossimonger.helloworld;version=“1.0.0“ Import-Package: org.osgi.framework;version=“1.3.0“OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  • 17. 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“OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  • 18. OSGi-SchichtenmodellOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  • 19. Zustände und ÜbergängeOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 9
  • 20. BundleActivator  OSGi-Framework → Bundle public interface BundleActivator { public void start(BundleContext context) throws Exception; public void stop(BundleContext context) throws Exception; }OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 10
  • 21. BundleContext Bundle → OSGi-Framework public interface BundleContext { … public Object getService (ServiceReference ref); public ServiceRegistration registerService (String[] clazzes, Object service, Dictionary properties); … } OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 11
  • 22. 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-ObjektOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 12
  • 23. Interaktion der SchichtenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 13
  • 24. GossipMongerOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 14
  • 25. 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(); } }OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 15
  • 26. 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(); } }} OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 16
  • 27. 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) { ...OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 17
  • 28. 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 …} OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 18
  • 29. 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 …}OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 19
  • 30. Projekt SetupBernd Weber Pax
  • 31. Agenda  Werkzeuge  JobTimer Bundle erstellen  Projekt GossipMonger aufsetzen  GateKeeper Bundle integrierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  • 32. Werkzeuge – Standard  JDK 1.6.2x  2.2.x oder 3.0  3.6 mit Maven-Plugin m2eclipse http://m2eclipse.sonatype.org/sites/m2eOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 3
  • 33. Werkzeuge – OSGi  >= 2.0.x http://felix.apache.org/site/downloads.cgi  1.26.0 http://www.aqute.biz/Bnd/Download alias bnd=$JAVA_HOME/bin/java -jar /path/to/biz.aqute.bnd.jar  PaxOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  • 34. 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/DownloadOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  • 35. 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/DownloadOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  • 36. 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/DownloadOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  • 37. Agenda  Werkzeuge  JobTimer Bundle erstellen  Projekt GossipMonger aufsetzen  GateKeeper Bundle integrierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  • 38. JobTimer – Maven-Struktur  JobTimer ist erstes Bundle  mvn generate:archetype  Vorschlag (Quickstart) übernehmen  Metadaten eingeben: groupId: biz.gossipmonger artifactId: jobtimer version: 0.1.0 package: biz.gossipmonger.jobtimerOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 9
  • 39. JobTimer – POM anpassen  pom.xml in Eclipse importieren File→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 konfigurierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 10
  • 40. JobTimer – Bundle erstellen  JobTimer.java in Maven-Struktur einbetten  JAR erstellen (mvn package)  Zum Bundle erweitern mit bnd – Steuerdatei osgi.bnd erstellen Bundle-Name: GossipMonger JobTimer Bundle-SymbolicName: biz.gossipmonger.jobtimer Bundle-Version: 0.1.0 Bundle-Activator: biz.gossipmonger.jobtimer.JobTimer Private-Package: biz.gossipmonger.jobtimer -classpath: target/jobtimer-0.1.0.jar – Aufruf von bnd osgi.bndOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 11
  • 41. JobTimer-Bundle Manifest  Ergebnis: JAR mit erweiterter Manifest-Datei Bundle-ManifestVersion: 2 Bundle-Name: GossipMonger JobTimer Bundle-SymbolicName: biz.gossipmonger.jobtimer Bundle-Version: 0.1.0 Bundle-Activator: biz.gossipmonger.jobtimer.JobTimer Private-Package: biz.gossipmonger.jobtimer Import-Package: org.osgi.framework,org.osgi.service.event ,org.osgi.util.tracker  Übrigens: bnd-Steuerdateien sind – vielseitig durch Variablen, Makros, … – kaskadierbar – gut lesbarOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 12
  • 42. 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>OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 13
  • 43. 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 ablegen mvn installOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 14
  • 44. Agenda  Werkzeuge  JobTimer Bundle erstellen  Projekt GossipMonger aufsetzen  GateKeeper Bundle integrierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 15
  • 45. Gesamtprojekt anlegen  Gesamtprojekt heißt “GossipMonger“  Verwendung von Pax Construct pax-create-project  Metadaten angeben groupId: biz.gossipmonger artifactId: gossipmonger version: 0.1.0OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 16
  • 46. JobTimer importieren  JobTimer ist Taktgeber für GossipMonger  Autarkes Bundle neben dem Projekt  Import => Definition Abhängigkeit $ cd gossipmonger $ pax-import-bundle groupId: biz.gossipmonger artifactId: jobtimer version: 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>OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 17
  • 47. 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>OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 18
  • 48. Agenda  Werkzeuge  JobTimer Bundle erstellen  Projekt GossipMonger aufsetzen  GateKeeper Bundle integrierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 19
  • 49. GateKeeper Bundle  GateKeeper-Bundle ist erstes Projekt-Modul  Ziel: Unmittelbare GossipMonger-Integration  Werkzeug: pax-create-bundle (Pax Construct) $ cd gossipmonger $ pax-create-bundle package: biz.gossipmonger.gatekeeper bundleName: biz.gossipmonger.gatekeeper bundleGroupId: biz.gossipmonger version: 0.1.0 <modules> <module>poms</module> <module>provision</module> <module>biz.gossipmonger.gatekeeper </module> </modules>OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 20
  • 50. POM Zuständigkeiten  pom.xml Master-POM, allg. Definitionen, Module (Bundles)  biz.gossipmonger.gatekeeper/pom.xml Bundle-Daten  poms/pom.xml globale Abhängigkeiten (u.a. OSGi API) und Verweise auf die nachfolgenden POMs  poms/compiled/pom.xml vordefinierte OSGi-Header, Einbindung osgi.bnd  poms/wrappers/pom.xml OSGi-Wrapper für Drittbibliotheken  provision/pom.xml spezifische Abhängigkeiten -> JobTimerOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 21
  • 51. GateKeeper Metadaten  Viele Default-Werte passen bereits  Nachziehen von Activator, Sichtbarkeit (, Name)  Werkzeug: Erweiterung von osgi.bnd (, POM) Bundle-Activator: ${bundle.namespace}.GateKeeper Private-Package: ${bundle.namespace} Export-Package: Import-Package: *  Überschreibt Standardwerte von Pax Construct  GateKeeper ist nun startklar und “unsichtbar“OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 22
  • 52. Bundle PlaygroundPatrick Baumgartner
  • 53. 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.jarOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  • 54. Apache Felix – Befehle (1)  Mögliche Befehle auf der Konsole abrfagen  g!help  Apache Felix BefehleOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 3
  • 55. Apache Felix – Befehle (2)  Apache Gogo Befehle  OBR BefehleOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  • 56. Apache Felix - Status  Installierte Bundles und deren Status auf der Gogo Konsole abfragen  g!lbOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  • 57. JobTimer installieren  g!install file:/pathtofile/jobtimer.jar  g!lbOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  • 58. JobTimer starten  g!resolve 4  g!start 4OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  • 59. JobTimer deinstallieren  g!stop 4  g!start 4OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  • 60. Apache Felix – Befehle (2)  Apache Gogo Befehle  OBR BefehleOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 9
  • 61. Apache Felix - Status  Installierte Bundles und deren Status auf der Gogo Konsole abfragen  g!lbOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 10
  • 62. Pax-Runner - Apache Felix  Apache Felix mit Pax-Runner starten  $pax-runOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 11
  • 63. 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=logOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 12
  • 64. Pax-Runner - Plattformen  Pax-Runner mit Apache Felix, Equinox, Knopflerfish starten  $pax-run --platform=equinoxOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 13
  • 65. Bundles mit URL installieren  osgi>install http://www.osgi- buch.com/tutorial/jobtimer.jar  Status mit osgi>ss prüfenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 14
  • 66. Apache Felix Web ConsolePatrick Baumgartner
  • 67. Apache Felix Web Console  Weitere Informationen abrufbar unter http://felix.apache.org/site/apache-felix-web-console.html  $pax-run –-profiles=web,jsp,felix.webconsoleOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  • 68. Web Console  URL: http://localhost:8080/system/console  Benutzername/Passwort: admin/adminOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 3
  • 69. Web Console - BundlesOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  • 70. Web Console - ShellOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  • 71. Web Console – Config (1)OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  • 72. Web Console – Config (2)OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  • 73. 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!OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  • 74. Declarative ServicesBernd Weber Service Component Runtime, OSGi Service Compendium, Kap. 112
  • 75. Agenda  Überblick  Enunciator Bundle integrieren  Worker Bundle integrierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  • 76. Überblick  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)OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 3
  • 77. 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.)OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  • 78. 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, ...OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  • 79. 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>OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  • 80. Agenda  Überblick  Enunciator Bundle integrieren  Worker Bundle integrierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  • 81. Enunciator BundleOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  • 82. Enunciator Bundle  Neues Teilprojekt im gossipmonger-Verzeichnis $ pax-create-bundle package: biz.gossipmonger.enunciator bundleName: biz.gossipmonger.enunciator bundleGroupId: biz.gossipmonger version: 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); }OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 9
  • 83. 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änzenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 10
  • 84. Enunciator public 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 }OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 11
  • 85. 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."); } ...OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 12
  • 86. Dienst deklarieren  Neues Verzeichnis src/main/resources/OSGI-INF  Darin Datei EnunciatorServiceImpl.xml anlegen  Schema: http://www.osgi.org/xmlns/scr/v1.0.0OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 13
  • 87. Deklaration bekanntgeben  biz.gossipmonger.enunciator/osgi.bnd  BundleActivator-Zeile löschen  Neue (einzige) Zeile für Service-ComponentOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 14
  • 88. 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); } } }OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 15
  • 89. 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_input org.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]OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 16
  • 90. Agenda  Überblick  Enunciator Bundle integrieren  Worker Bundle integrierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 17
  • 91. Worker ServiceOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 18
  • 92. 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 anmeldenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 19
  • 93. 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-Out public 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); }OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 20
  • 94. Worker Implementierung public 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; } ... }OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 21
  • 95. 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; } }OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 22
  • 96. Worker Implementierung (3) 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; } ... In-Bundle Properties: nach der MittagspauseOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 23
  • 97. Komponente deklarieren  java/main/resources/OSGI-INF/WorkerServiceImpl.xml <?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>OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 24
  • 98. 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 EventAdminOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 25
  • 99. Test der Bundles  Aufruf von pax-provision im gossipmonger-Verz.  Ablegen beliebiger XML-Datei in render_input: GateKeeper: Processing deploy-pom.xml WorkerServiceImpl: Render from /home/osgi/osgibuch/ gossipmonger/runner/render_input/deploy-pom.xml WorkerServiceImpl: Rendering... WorkerServiceImpl: Rendered to /home/osgi/osgibuch/ gossipmonger/runner/render_outpdf/deploy-pom.pdf GateKeeper: 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 lost a LogService. Now there are 0 references. DEBUG biz.gossipmonger.enunciator - BundleEvent STOPPEDOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 26
  • 100. Blueprint ServicesPatrick Baumgartner
  • 101. Ü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)OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  • 102. 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>OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 3
  • 103. Blueprint Idee Application Application Context Context Application Context Imported Service Exported Service Bean Blueprint Framework OSGI Framework JVM Spring Dynamic Modules - OSGi with Spring FrameworkOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  • 104. Blueprint Bundle Blueprint Bundle Blueprint Bundle Metadata Metadata XML XML Blueprint ExtenderOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  • 105. Blueprint Konfiguration (Auszug)OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  • 106. Skilled Worker ServiceOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  • 107. Web BundlesPatrick Baumgartner
  • 108. Ü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 SupportOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  • 109. 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 BundleOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 3
  • 110. Applikationsarchitektur WebApp WebApp Web Container Bundle 1 Bundle 2 OSGi Framework Spring Dynamic Modules - OSGi with Spring Framework JVM  Bundles und WebApps sollen Services teilen!OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  • 111. DemoOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  • 112. WebMonitorOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  • 113. Fragmente & IntegrationstestsBernd Weber
  • 114. Agenda  Fragmente  Pax Exam  Einfacher Integrationstest  Erweiterter TestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  • 115. Fragmente  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, SkinsOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 3
  • 116. 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; }}OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  • 117. 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;}...OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  • 118. Erstellen des Fragments  pax-create-bundle im gossipmonger-Verzeichnis package: biz.gossipmonger.worker bundleName: biz.gossipmonger.worker-config bundleGroupId: biz.gossipmonger version: 0.1.0  src/main/resources/worker.properties erstellen  osgi.bnd mit Fragment-HeaderOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  • 119. 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-bundle properties to render_outfragment. WorkerServiceImpl: activated.  Fragment-Bundle bleibt im Status resolvedOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  • 120. Agenda  Fragmente  Pax Exam  Einfacher Integrationstest  Erweiterter TestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  • 121. 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) erstelltOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 9
  • 122. 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.gossipmonger artifactId: biz.gossipmonger.test.worker version: 0.1.0 package: biz.gossipmonger.test.workerOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 10
  • 123. 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 eintragenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 11
  • 124. Generierter Testfall  Verwendung des Pax Exam TestRunners  BundleContext wird „injiziert“OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 12
  • 125. Agenda  Fragmente  Pax Exam  Einfacher Integrationstest  Erweiterter TestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 13
  • 126. Einfacher IntegrationstestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 14
  • 127. 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“OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 15
  • 128. 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}OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 16
  • 129. 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); }}OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 17
  • 130. 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 TestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 18
  • 131. Agenda  Fragmente  Pax Exam  Einfacher Integrationstest  Erweiterter TestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 19
  • 132. Erweiterter TestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 20
  • 133. 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 EquinoxOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 21
  • 134. 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}OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 22
  • 135. Erweiterter Test: Setup@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}private class TestEventHandler implements EventHandler { public void handleEvent(Event event) { System.out.println(event.toString()); resultPath = (String) event.getProperty("output"); }} resultPath = Ausgabepfad der gerenderten Datei Event kommt vom GateKeeper.postResultOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 23
  • 136. 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 entsprichtOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 24
  • 137. 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 doesnt 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);} OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 25
  • 138. 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 TestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 26
  • 139. Distributed OSGi Patrick BaumgartnerOSGi Compendium Spezifikation Kapitel 13
  • 140. Überblick  RFC 119: Remote Services Produziert Konsumiert Service A Service A  Services einer Remote Maschine benutzen – Andere Maschine, verbunden über ein Netzwerk – Andere JVM, andere Adresse oder SpracheOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  • 141. 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äumenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 3
  • 142. 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.serverOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  • 143. 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 / aegisOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  • 144. 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 / aegisOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  • 145. Remote LogServer (Standalone)  LogServer implementiert mit Spring DM  META-INF/spring/bundle-context-osgi.xmlOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  • 146. 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 EnunciatorOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  • 147. Protokoll - TestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 9
  • 148. Lab - DOSGiOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 10
  • 149. DOSGi Discovery Produziert Konsumiert Service A Service A  RFC 119 beschreibt einen Weg um Metadata eines Remote Services zu publizieren/beziehen  Protokolle: Zeroconf/Bonjour, ServiceLocation Protocol (SLP), Apache Zookeper, FilesOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 11
  • 150. OutlookAliens - Bundles from Outer (Java) SpaceOliver BraunOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 1
  • 151. 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 enthaltenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  • 152. 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 { ... } OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 3
  • 153. TypsystemOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  • 154. Statisch typisiert  Lokaler Typinferenzmechanismus – Statt in Java: Map<Integer,String> myMap = new Map<Integer,String>(); – In Scala val myMap: Map[Int,String] = Map() – Oder val myMap = Map[Int,String]() – Oder sogar val myMap = Map(1 -> “eins“, 2 -> “zwei“)OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  • 155. Klassenparameter und „Operatoren“// Javaclass Rational { final int x; Rational a = new Rational(1,2); final int y; Rational a = new Rational(2,3); Rational(int x, int y) { Rational c = a.add(b) 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) { val a = new Rational(1,2); def +(other: Rational) = val b = new Rational(2,3); Rational(x+other.x, y+other.y) val c = a + b} // a + bOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  • 156. ScalaModules – DSL für OSGi // Java ServiceReference 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!"); } // Scala context findService withInterface[Greeting] andApply { _.welcome } match { case None => println("No Greeting service available!") case Some(welcome) => println(welcome) }OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  • 157. OSGi-Bundle in Scala package biz.gossipmonger.chirp import org.osgi.service.log.LogService import 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) {} }OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  • 158. 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 } …OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 9
  • 159. ... und wie gehts 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 gehtsOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 10
  • 160. LauncherBernd Weber
  • 161. Agenda  Ziele  Spezifikation  Implementierung  KonfigurationOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  • 162. Launcher - Ziele  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 – AnalogieOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 3
  • 163. Launcher – Spezifikation  OSGi Framework Launching API OSGi 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-EndeOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  • 164. Implementierung  Launcher ist eigenständiges Projekt  Keine Abhängigkeit zum GossipMonger  Neues Verzeichnis, darin Aufruf von $ mvn archetype:generate Choose a number: (...): <default Quickstart> groupId: biz.gossipmonger artifactId: biz.gossipmonger.launcher version: 0.1.0 package: biz.gossipmonger.launcherOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  • 165. 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)OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  • 166. 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 wartenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  • 167. Implementierung  Framework Factory erzeugen private 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  System Bundle erzeugen und starten FrameworkFactory factory = getFrameworkFactory(); Map<String, String> map = getFrameworkSettings(args); Framework framework = factory.newFramework(map); framework.start();OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  • 168. 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 BundlesOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 9
  • 169. Launcher – Konfiguration  Framework / Umgebung konfigurieren META-INF/settings/FrameworkSettings # The bundle cache shall be cleaned at every start org.osgi.framework.storage.clean = onFirstInit ...  Debug-Bundles konfigurieren META-INF/settings/DebugBundles  Applikations-Bundles konfigurieren META-INF/settings/ApplicationBundles # Install Apache SCR and Event Admin Service from OBR obr:org.apache.felix.scr/1.4 obr:org.apache.felix.eventadmin/1 # Install PAX Logging from Maven mvn:org.ops4j.pax.logging/pax-logging-api/1.4 mvn:org.ops4j.pax.logging/pax-logging-service/1.4 # Install the GossipMonger Bundles from Maven mvn:biz.gossipmonger/jobtimer/0.2.0 ...OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 10