© DrHitch/Shutterstock.com
Modulare Software entwickeln mit OSGi

1 Generisches Ressourcenmodell


Viele kennen OSGi als eine dünne Schicht über Java, um modulare Software zu entwickeln. OSGi übernimmt dabei die Prüfung, ob Abhängigkeiten einzelner Module in sich konsistent sind und das System somit wie gewünscht funktioniert. Ein Blick hinter die Kulissen, wie OSGi Abhängigkeiten beschreibt, lohnt sich allemal.

Dieses Kapitel zeigt, wie OSGi auf Basis des generischen Requirement-and-Capability-Modells Abhängigkeiten zwischen Bundles beschreibt. Konzepte wie OBR (OSGi Bundle Repository), Resolving und Provisioning werden in der OSGi-Welt immer wichtiger. Finales Ziel ist, dass OSGi auf Basis dieses Modells alle Abhängigkeiten erkennt und mittels definierter Bundle Repositories automatisch installiert. Auf Resolving und Provisioning wird in diesem Kapitel nicht eingegangen. Details hierzu folgen im nächsten Kapitel.

OSGi in Kürze

OSGi basiert auf der Grundidee, Java-Applikationen in Module zu unterteilen. Jedes dieser Module (Bundle genannt) kapselt Funktionen. Ein Bundle wird durch seinen Symbolic Name und die Version eindeutig bestimmt. Im Gegensatz zu herkömmlichen JAR-Files definiert ein Bundle Schnittstellen.

Aufgrund von Einträgen im MANIFEST.MF definiert ein Bundle, welche Java-Packages nach außen sichtbar sein sollen. Ebenfalls muss ein Bundle definieren, welche sichtbaren Java-Packages es von anderen Bundles konsumieren möchte. Auf den ersten Blick scheint dies etwas umständlich. Es ergibt bei genauerer Betrachtung allerdings sehr viel Sinn. Durch diesen Mechanismus erkennt OSGi, welche Java-Packages zur einwandfreien Ausführung eines Bundles benötigt werden. Benötigt Bundle A bspw. das Package org.foo, das von OSGi jedoch nicht gefunden werden kann, wird Bundle A nicht korrekt ausgeführt, und OSGi reagiert mit einem Fehler darauf.

Die Definition von Abhängigkeiten erfüllt noch einen weiteren Zweck: Laut Java-Spezifikation darf eine Klasse nur einmal von einem Classloader geladen werden. Im klassischen SE-Ansatz, in dem die Context-Klassen immer vom gleichen Classloader geladen werden, bedeutet das, dass eine Klasse, die einmal geladen wurde, nicht wieder ausgetauscht werden kann. Die OSGi-Spezifikation umgeht dieses Problem, indem jedes Bundle seinen eigenen Classloader verwendet und Klassen eines Bundles nur mit dem jeweiligen Bundle Classloader geladen werden dürfen. Somit ist es möglich, Klassen im laufenden Betrieb auszutauschen. Ein Bundle besitzt einen Lifecycle und kann installiert, gestartet, gestoppt und deinstalliert werden. Beim Deinstallieren von Bundles wird auch der mit dem Bundle verbundene Classloader entfernt – was dazu führt, dass auch die mit dem Classloader geladenen Klassen aus der JVM entfernt werden.

Zusätzlich erlaubt diese Vorgehensweise, dass Klassen mit gleichem Namen, aber unterschiedlicher Version mehrfach im System geladen werden können. Benötigt Bundle A Klasse Foo in der Version 1 und Bundle B die gleiche Klasse in der Version 2, so ist es in OSGi möglich, dies umzusetzen. Im Gegensatz zu SE verwendet OSGi keinen globalen Klassenpfad, sondern delegiert das Laden von Klassen an Bundles. Stellt Bundle B bspw. die Klasse Bar zur Verfügung und exportiert das Java-Package, so importiert Bundle A dieses Java-Package und versucht die Klasse Bar zu laden. Der Classloader von Bundle A prüft, ob die Klasse im eigenen Bundle verfügbar ist. Falls nicht, delegiert der Classloader das Laden der Klasse an Bundle B. Der globale Klassenpfad mit all seinen Problemen gehört dank OSGi der Vergangenheit an.

pirchner_1_1.png

Abb....

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang