Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

  • Login to see the comments

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

  1. 1. OSGi für Praktiker - BegrüssungPatrick Baumgartner Pax
  2. 2. Agenda  OSGi für Praktiker  Vorstellung  Ablauf des Workshops  AdministrativesOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  3. 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. 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. 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. 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. 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. 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. 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. 10. AdministrativesOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 10
  11. 11. Einleitung Oliver Braun PaxOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 1
  12. 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. 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. 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. 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. 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. 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. 18. OSGi-SchichtenmodellOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  19. 19. Zustände und ÜbergängeOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 9
  20. 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. 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. 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. 23. Interaktion der SchichtenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 13
  24. 24. GossipMongerOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 14
  25. 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. 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. 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. 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. 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. 30. Projekt SetupBernd Weber Pax
  31. 31. Agenda  Werkzeuge  JobTimer Bundle erstellen  Projekt GossipMonger aufsetzen  GateKeeper Bundle integrierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  32. 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. 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. 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. 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. 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. 37. Agenda  Werkzeuge  JobTimer Bundle erstellen  Projekt GossipMonger aufsetzen  GateKeeper Bundle integrierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  38. 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. 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. 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. 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. 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. 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. 44. Agenda  Werkzeuge  JobTimer Bundle erstellen  Projekt GossipMonger aufsetzen  GateKeeper Bundle integrierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 15
  45. 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. 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. 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. 48. Agenda  Werkzeuge  JobTimer Bundle erstellen  Projekt GossipMonger aufsetzen  GateKeeper Bundle integrierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 19
  49. 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. 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. 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. 52. Bundle PlaygroundPatrick Baumgartner
  53. 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. 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. 55. Apache Felix – Befehle (2)  Apache Gogo Befehle  OBR BefehleOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  56. 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. 57. JobTimer installieren  g!install file:/pathtofile/jobtimer.jar  g!lbOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  58. 58. JobTimer starten  g!resolve 4  g!start 4OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  59. 59. JobTimer deinstallieren  g!stop 4  g!start 4OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  60. 60. Apache Felix – Befehle (2)  Apache Gogo Befehle  OBR BefehleOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 9
  61. 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. 62. Pax-Runner - Apache Felix  Apache Felix mit Pax-Runner starten  $pax-runOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 11
  63. 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. 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. 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. 66. Apache Felix Web ConsolePatrick Baumgartner
  67. 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. 68. Web Console  URL: http://localhost:8080/system/console  Benutzername/Passwort: admin/adminOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 3
  69. 69. Web Console - BundlesOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  70. 70. Web Console - ShellOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  71. 71. Web Console – Config (1)OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  72. 72. Web Console – Config (2)OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  73. 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. 74. Declarative ServicesBernd Weber Service Component Runtime, OSGi Service Compendium, Kap. 112
  75. 75. Agenda  Überblick  Enunciator Bundle integrieren  Worker Bundle integrierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  76. 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. 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. 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. 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. 80. Agenda  Überblick  Enunciator Bundle integrieren  Worker Bundle integrierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  81. 81. Enunciator BundleOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  82. 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. 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. 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. 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. 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. 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. 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. 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. 90. Agenda  Überblick  Enunciator Bundle integrieren  Worker Bundle integrierenOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 17
  91. 91. Worker ServiceOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 18
  92. 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. 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. 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. 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. 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. 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. 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. 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. 100. Blueprint ServicesPatrick Baumgartner
  101. 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. 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. 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. 104. Blueprint Bundle Blueprint Bundle Blueprint Bundle Metadata Metadata XML XML Blueprint ExtenderOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  105. 105. Blueprint Konfiguration (Auszug)OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  106. 106. Skilled Worker ServiceOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 7
  107. 107. Web BundlesPatrick Baumgartner
  108. 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. 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. 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. 111. DemoOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 5
  112. 112. WebMonitorOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 6
  113. 113. Fragmente & IntegrationstestsBernd Weber
  114. 114. Agenda  Fragmente  Pax Exam  Einfacher Integrationstest  Erweiterter TestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  115. 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. 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. 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. 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. 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. 120. Agenda  Fragmente  Pax Exam  Einfacher Integrationstest  Erweiterter TestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 8
  121. 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. 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. 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. 124. Generierter Testfall  Verwendung des Pax Exam TestRunners  BundleContext wird „injiziert“OSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 12
  125. 125. Agenda  Fragmente  Pax Exam  Einfacher Integrationstest  Erweiterter TestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 13
  126. 126. Einfacher IntegrationstestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 14
  127. 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. 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. 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. 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. 131. Agenda  Fragmente  Pax Exam  Einfacher Integrationstest  Erweiterter TestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 19
  132. 132. Erweiterter TestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 20
  133. 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. 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. 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. 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. 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. 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. 139. Distributed OSGi Patrick BaumgartnerOSGi Compendium Spezifikation Kapitel 13
  140. 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. 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. 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. 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. 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. 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. 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. 147. Protokoll - TestOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 9
  148. 148. Lab - DOSGiOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 10
  149. 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. 150. OutlookAliens - Bundles from Outer (Java) SpaceOliver BraunOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 1
  151. 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. 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. 153. TypsystemOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 4
  154. 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. 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. 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. 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. 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. 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. 160. LauncherBernd Weber
  161. 161. Agenda  Ziele  Spezifikation  Implementierung  KonfigurationOSGi für Praktiker - Bernd Weber, Patrick Baumgartner, Oliver Braun 2
  162. 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. 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. 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. 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. 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. 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. 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. 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

×