Erste Schritte mit OSGi – Teil II

Heiko Seeberger

Die OSGi Service Platform (OSGi) hat sich zu einem sehr bedeutenden Standard im Java-Umfeld entwickelt. Also wird es für den engagierten Java-Entwickler allerhöchste Zeit, sich damit näher auseinander zu setzen.

Diesmal soll das OSGi-Framework genauer unter die Lupe genommen werden. Um gleich im OSGi-Jargon sprechen zu können, führen wir zunächst einen zentralen Begriff ein: Ein OSGi-Modul wird Bundle genannt. Somit bestehen Systeme auf Basis von OSGi aus Bundles, für die das OSGi Framework die Laufzeitumgebung darstellt (Abb. 1).

Abb. 1: OSGi-System

Die Funktionalität des OSGi Frameworks ist auf mehrere Schichten verteilt, die in Abbildung 2 orange dargestellt sind.

Abb. 2: Schichtenarchitektur des OSGi Frameworks

Der Module Layer definiert die strukturellen Aspekte rund um Bundles, d.h. die statische Sicht auf das OSGi-Modulkonzept. Bundles sind JAR-Archive und enthalten neben Klassen und Ressourcen mit dem Bundle Manifest eine Datei, die die OSGi-Eigenschaften des Bundles beschreibt. Besonders hervorzuheben ist, dass im Bundle Manifest die Abhängigkeiten und das API, d.h. die öffentliche Schnittstelle, explizit deklariert werden. Das OSGi Framework stellt sicher, dass andere Bundles nur auf das API eines Bundles zugreifen können, und das auch nur dann, wenn sie selbst entsprechende Abhängigkeiten deklarieren. Wir werden in der kommenden Folge die Details des Module Layer betrachten.

Der Lifecycle Layer bringt die dynamische Sicht ins Spiel, indem er den Lebenszyklus von Bundles im OSGi Framework definiert. So können Bundles beispielsweise zur Laufzeit installiert und wieder deinstalliert werden. Weiterhin – dies ist für das folgende „Hello World!“-Beispiel wichtig – können Bundles auch gestartet und gestoppt werden, woraufhin in einem speziellen Objekt, dem BundleActivator, entsprechende start()- und stop()-Methoden aufgerufen werden. Auch hier sei für weitere Details auf die kommende Folge verwiesen.

Der Service Layer fügt ein serviceorientiertes Programmiermodell hinzu, sodass Bundles in bestimmten Phasen ihres Lebenszyklus Objekte als Services an der OSGi Service Registry anmelden oder abrufen können. Dabei wird das Service-Interface, das vom Service implementiert wird, als Schlüssel verwendet. Besonderes Augenmerk muss hierbei der Laufzeitdynamik gewidmet werden: Schließlich können die Bundles, die Services anbieten, jederzeit „kommen und gehen“, womit Servicekonsumenten umgehen können müssen. Daher bietet OSGi Mechanismen, um den Service Lifecycle zu verfolgen, z.B. den im „Hello World!“-Beispiel verwendeten ServiceTracker. Dieses besonders wichtige und komplexe Thema werden wir in der dritten Folge beleuchten.

Daneben stellt der Security Layer auf Basis von Java 2 Security spezifische Sicherheitsbelange zur Verfügung. Neben dem Signieren von Bundles spielen darin für OSGi spezifische Permissions eine zentrale Rolle. So kann z.B. festgelegt werden, ob ein Bundle berechtigt wird, bestimmte Services zu verwenden oder das API anderer Bundles zu nutzen.

Unterhalb der Framework-Schichten definiert OSGi in Form von Execution Environments Abstraktionen von Java-Laufzeitumgebungen. Diese können pro Bundle zur Voraussetzung gemacht werden, wobei das OSGi Framework selbst das OSGi/Minimum-1.1 Execution Environment benötigt.

Es gibt zahlreiche OSGi-Implementierungen, sowohl kommerzielle Produkte als auch kostenlose Open-Source-Lösungen, z.B. Apache Felix [1] oder Knopflerfish OSGi [2]. Wir werden für das folgendende Beispiel Eclipse Equinox [3] verwenden, weil das Eclipse SDK als Entwicklungsumgebung mit dem Plug-in Development Environment (PDE) eine hervorragende Werkzeugunterstützung anbietet, die optimal auf Equinox abgestimmt ist, sodass die ersten Schritte besonders einfach fallen. Trotzdem werden wir uns ausschließlich am aktuellen OSGi-Standard orientieren, sodass die Beispiele problemlos auf anderen Implementierungen laufen können. In den kommenden Folgen werden wir auch andere OSGi-Implementierungen verwenden.

„Hello World!“

Das Beispiel (Abb. 3) besteht aus zwei Bundles: Das eine bietet beim Starten unter dem Serviceinterface IHelloProvider einen Service an, das andere „lauscht“, sobald es gestartet wurde, auf solche Services, um diese aufzurufen und das Ergebnis „Hello World!“ auf der Konsole auszugeben (Abb. 4). In den kommenden Folgen werden wir die verwendeten Konzepte im Detail erläutern, für hier und heute dient dieses Beispiel dazu, ein erstes Gefühl für OSGi zu entwickeln.

Abb. 3: Hello World!-Architektur

Für dieses Beispiel wird Java 5 und Eclipse SDK Ganymede mit PDE benötigt, z.B. das Package Eclipse for RCP/Plug-in Developers [4]. Um Seiteneffekte zu vermeiden, sollte ein neuer Workspace verwendet werden.

Abb. 4: Hello World!-Ergebnis
Geschrieben von
Heiko Seeberger
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.