Eclipse Summit Europe 08 - Aspect Weaving for OSGi
JM 01/09 - OSGi in kleinen Dosen 2
1. Core OSGi in kleinen Dosen – Teil 2
Immer in Bewegung –
Bundles und Life Cycle
Wir haben uns im vorigen Java Magazin mit den drei herausragenden
Eigenschaften von OSGi beschäftigt: Modularisierung, Laufzeitdynamik
und Serviceorientierung. Jetzt ist es an der Zeit, Modularisierung und
Laufzeitdynamik und deren Zusammenspiel unter die Lupe zu nehmen.
von Heiko Seeberger
Cohesive: Die Elemente eines Moduls
diese Form der Modularisierung zu fein-
ozu brauchen wir eigentlich
granular, um damit nicht-triviale So -
Modularisierung bzw. ein Mo- haben einen starken logischen Bezug
waresysteme adäquat zu modularisieren.
dule System? Die Antwort ist zueinander.
Loose Coupling: Module besitzen un-
Mit anderen Worten: Java fehlt ein Mo-
einfach: zur Reduktion von Komplexi-
dulkonzept „oberhalb“ der Packages.
tät. Module abstrahieren vom schwer tereinander eine geringe Kopplung.
Public API: Ein Modul besitzt eine
Bevor wir betrachten, wie OSGi
überschaubaren Problem hin zu über-
diese Lücke schließt, de nieren wir zu-
sichtlichen Herausforderungen. Diese wohl de nierte ö entliche Schnittstel-
nächst, was wir eigentlich genau unter
können isoliert voneinander und mög- le und verbirgt die Interna der Imple-
einem Modul verstehen wollen:
licherweise auch arbeitsteilig in Angri mentierung.
Dependencies: Die Abhängigkeiten ei-
genommen werden und bieten die Mög-
Self-contained: Ein Modul ist eine
lichkeit der Wiederverwendung. nes Moduls sind wohl de niert.
Deployment Format: Ein Modul „läu “
Was bedeutet das konkret für Java? Komposition aus kleineren Teilen, mit
Als objektorientierte Programmierspra- Ausnahme von wohl de nierten Ab- in einem Container bzw. einer Lauf-
che bietet Java ein Modulkonzept in Form hängigkeiten und kann nur als Ganzes zeitumgebung und wird dort in einem
von Klassen und Packages. Allerdings ist verwendet werden. wohl de nierten Format installiert.
Diese Eigenscha en führen nicht nur
Artikelserie: OSGi in kleinen Dosen dazu, dass komplexe So waresysteme
in überschaubare Module herunter-
Teil 1: Erste Schritte mit OSGi
gebrochen werden können, wodurch
Teil 2: Immer in Bewegung – Bundles und Life Cycle
zweifellos die Produktivität und Qua-
Teil 3: Was wünschen Sie? – Services a là OSGi
Teil 4: Alles XML oder was? – Services auf deklarative Weise lität in der Entwicklung gesteigert wer-
Teil 5: Hier wird „Service“ groß geschrieben – Ausgewählte OSGi-Standardservices
den kann. Sie fördern auch die Flexibili-
tät und wirken sich dadurch positiv auf
26 javamagazin 1|2009 www.JAXenter.de
2. OSGi in kleinen Dosen – Teil 2 Core
lung dieses Artikels 1.2.1) in das Projekt-
Time-to-Market und die Nutzung neuer
verzeichnis und fügen die Datei bin/felix.
Marktchancen aus.
jar unter J B P |L zu
Beispiel und Entwicklungs- den Libraries hinzu. Dann exportieren
umgebung wir diese Library unter J B P
|O E , sodass unsere Pro-
Wir beginnen mit einem Beispiel, das
jekte auf die darin enthaltene OSGi-API
wir in den folgenden Teilen dieser Ar-
Zugri haben. Anschließend erzeugen
tikelserie sukzessive ausbauen werden.
wir mittels R | R C
Dabei handelt es sich um ein „universel- Abb. 1: Struktur eines Bundles
… eine neue Run Configuration vom
les Adressbuch“, das Kontakte aus belie-
Typ Java Application, benennen Sie mit
bigen Repositories gemeinsam verwal- Layer des OSGi Frameworks, der für
org.apache.felix, wählen org.apache.felix.
ten kann. Sämtlicher Sourcecode sowie dessen weitere Schichten die Grundlage
Main als Main Class und setzen die fol-
die speziell benötigte So ware be nden bildet. Darin wird das Bundle als OSGi-
genden VM Arguments: -Dfelix.cache.
sich auf der Begleit-CD und können Einheit für Modularisierung de niert.
dir=.cache -Dfelix.cache.pro le=default.
ebenfalls heruntergeladen werden [1]. Ein Bundle besteht aus Java-Klassen und
Die Ausführung dieser Run Con gura-
Eclipse PDE wurde als Entwick- Ressourcen wie Properties-Dateien und
tion startet Apache Felix, wobei per De-
lungswerkzeug für Bundles sowie Eclip- wird als JAR-Archiv im OSGi Frame-
fault „Welcome to Felix.“ auf der Konsole
se Equinox als OSGi-Implementierung work installiert (Abb. 1).
ausgegeben wird. Die Begleit-CD enthält
bereits vorgestellt. Wir werden weiterhin Darüber hinaus enthält ein Bun-
unter anderem bereits dieses Projekt, so-
Eclipse als Java-Entwicklungswerkzeug dle Metadaten, z.B. über die ö entliche
dass wir dieses nur in unseren Workspace
verwenden, aber diesmal mit Bnd [2] Schnittstelle oder die Abhängigkeiten,
importieren müssen.
und Apache Felix [3], und Alternativen die vom OSGi Framework verwendet
für die Entwicklung bzw. die OSGi-Im- werden, um obige Eigenschaften si-
Modularisierung à la OSGi
plementierung aufzeigen. cherzustellen. Diese Metadaten wer-
Bnd wird von Peter Kriens, Director den im Bundle Manifest (META-INF/
Die OSGi-Spezi kation adressiert das
MANIFEST.MF) spezi ziert, das ohne-
of Technology der OSGi Alliance [4], Thema Modularisierung im Module
entwickelt und dient unter anderem
zum Erstellen von OSGi Bundles. Mit-
hilfe von bnd-Dateien, deren Syntax der
des Bundle Manifests ähnelt, sowie der
Analyse des Imports von Klassendatei-
en erstellt Bnd aus Java-Projekten OSGi
Bundles. Es kann per Kommandozeile
als Ant-Task oder Eclipse-Plug-in ver-
wendet werden. Wir werden es als Eclip-
se Plug-in einsetzen, indem wir die aktu-
elle produktive Version (zum Zeitpunkt
der Erstellung dieses Artikels 0.0.249, als
bnd-0.0.249.jar auf der Begleit-CD) in
das Verzeichnis dropins unserer Eclipse-
Installation kopieren und Eclipse an-
schließend neu starten. Danach stellt das
Bnd-Plug-in im Kontextmenü von bnd-
Dateien im Package Explorer den Menü- Anzeige
punkt M zur Verfügung.
Um Apache Felix ebenfalls in Eclip-
se zu integrieren, erstellen wir ein Java-
Projekt org.apache.felix und stellen in
den Project Properties (Kontextmenü
P ) unter J B P |
den Default output folder auf org.
S
apache.felix oder jeden beliebigen ande-
ren Pfad außer org.apache.felix/bin. An-
schließend entpacken wir den Download
der aktuellen produktiven Version von
Apache Felix (zum Zeitpunkt der Erstel-
www.JAXenter.de
3. Core OSGi in kleinen Dosen – Teil 2
hin Bestandteil der JAR-Spezifikation sorgt durch eine ausgeklügelte Classloa- Contact[] getAllContacts();
void remove(Contact contact);
ist. Damit ist ein Bundle außerhalb des ding-Architektur dafür, dass Bundles
}
OSGi Frameworks ein ganz gewöhnli- self-contained sind und ihr lokaler Klas-
ches JAR-Archiv und kann in jedem be- senpfad ausschließlich aus Elementen
liebigen Java-System verwendet werden. innerhalb des Bundles besteht. Wird der Das Projekt für das Implementierungs-
entsprechende Manifest Header Bundle-
So sind z.B. sämtliche Libraries des Spring Bundle benötigt natürlich eine Abhängig-
Classpath weggelassen, wird per Default
Frameworks seit Version 2.5 OSGi Bund- keit zum Projekt für das Kern-API, sodass
les, was jedoch bei „klassischer“ Verwen- das Wurzelverzeichnis des Bundles ver- wir diese über die Project Properties (J
dung völlig transparent bleibt. wendet. Dies ist empfehlenswert, um B P |P ) hinzufügen. An-
schließend erstellen wir ein InMemory-
Jedes Bundle besitzt einen obligato- Bundles als „ganz normale“ JAR-Libra-
ContactRepository, das ContactReposito-
rischen symbolischen Namen, der mit- ries verwenden zu können.
tels Bundle-SymbolicName spezifiziert ry implementiert, indem es alle Contacts
Unser Beispiel, 1. Iteration in einer Collection verwaltet:
wird. Wir empfehlen als Best Practice,
bei der Benennung die Reverse-Do- Für unser Beispiel benötigen wir zwei
public class InMemoryContactRepository implements
main-Name-Konvention zu verwenden, Bundles:
ContactRepository {
um Namenskollisionen zu vermeiden.
private final Collection<Contact> contacts;
com.weiglewilczek.example.osgi.con-
Dabei beginnt der symbolische Name
....
tacts.core: Das Kern-API des Adress-
mit dem umgekehrten Domain-Namen }
und spezi ziert dann „Sinn und Zweck“, buchs.
z.B. com.weiglewilczek.example.osgi.con- com.weiglewilczek.example.osgi.con-
Die öffentliche Schnittstelle
tacts.core. Gemeinsam mit der Version, tacts.core.inmemory: Eine nicht per-
die mittels Bundle-Version gesetzt wird, sistente Implementierung des Kern- Wie oben erläutert, kann ein Bundle a
identi ziert der symbolische Name ein APIs. priori nur auf die „eigenen“ Klassen zu-
Bundle eindeutig innerhalb des OSGi greifen. Werden andere Klassen benö-
Frameworks. Daraus wird unmittelbar Dazu erstellen wir je ein gleichnamiges tigt, so sind zweierlei Voraussetzungen
ersichtlich, dass es möglich ist, das gleiche Java-Projekt mit Eclipse. Das Kern-API- zu erfüllen. Erstens müssen nutzende
Bundle enthält im Package com.weigle-
Bundle (mit demselben symbolischen Bundles explizit ihre Abhängigkeiten im
wilczek.example.osgi.contacts.core die
Namen) in mehreren unterschiedlichen Bundle Manifest deklarieren (Import)
Versionen zu installieren. Zusammen mit Bean Contact mit Properties für Vor- und zweitens müssen Bundles, die ande-
der weiter unten erläuterten Möglich- und Nachname, Anschri etc.: ren Bundles einen Teil ihrer Klassen als
keit, bei Abhängigkeiten auf bestimmte ö entliche Schnittstelle zur Verfügung
public class Contact {
Versionen abzuzielen, bietet OSGi damit stellen, dies ebenfalls im Bundle Mani-
private String firstName;
einen Ausweg aus der leider allzu häu g fest deklarieren (Export).
private String lastName;
au retenden Java-Sackgasse, bestimmte Mit dem Manifest Header Export
...
Libraries gleichzeitig in verschiedenen Package werden die Namen sämtlicher
}
Versionen zu benötigen. Packages spezi ziert, die zur ö entlichen
Der lokale Klassenpfad eines Bund- Schnittstelle gehören. Dabei werden die
les kann aus mehreren Verzeichnissen Package-Namen mit Kommata voneinan-
Des Weiteren enthält es das Interface
der getrennt: Export-Package: p1,p2. Es ist
ContactRepository zur Verwaltung der
innerhalb des Bundles bestehen und so-
gar eingebettete JAR-Archive enthalten. möglich und empfehlenswert, pro Packa-
Kontakte:
Wichtig: Es ist nicht möglich, Klassen ge eine Versionsnummer anzugeben, was
public interface ContactRepository { durch das version-Attribut erzielt werden
oder JAR-Archive außerhalb des Bund-
void add(Contact contact);
kann: Export-Package: p;version=quot;1.0.0quot;.
les zu verwenden. Das OSGi Framework
Um Namenskollisionen bei den exportier-
Manifest Header Bedeutung ten Packages zu vermeiden, empfehlen wir
für diese ebenfalls eine Namenskonventi-
Bundle-SymbolicName Eindeutiger Name innerhalb des OSGi Frameworks. Obligatorisch!
on: Das oberste Package sollte den symbo-
Empfehlung: Reverse Domain Name Convention
lischen Namen des Bundles tragen, z.B.
Bundle-Version Dient zusammen mit dem symbolischen Namen als eindeutige ID.
Format: „major.minor.micro.qualifier“, z.B. “1.2.3.test”. Default “0.0.0” com.weiglewilczek.example.osgi.contacts.
Bundle-Classpath Listet alle Verzeichnisse und/oder eingebettete JARs auf, die zum core.inmemory. Um darüber hinaus auf
lokalen Klassenpfad des Bundles gehören. Default „.“
den ersten Blick erkennen zu können, was
Bundle-Activator Voll-qualifizierter Name eines BundleActivators, dessen Methoden
exportiert wurde und was nicht, bietet sich
beim Starten und Stoppen des Bundles aufgerufen werden
an, nicht-exportierte Packages mit einem
Import-Package Listet die Abhängigkeiten in Form von Package-Namen auf
internal im Namen zu versehen, z.B. com.
Export-Package Listet die öffentliche Schnittstelle in Form von Package-Namen auf
weiglewilczek.example.osgi.contacts.core.
inmemory.internal. Bei der Verwendung
Tabelle 1: Wichtige Manifest Header
28 javamagazin 1|2009 www.JAXenter.de
4. OSGi in kleinen Dosen – Teil 2 Core
nifest Header Import-Package werden
von Eclipse PDE bekommen wir dadurch gigkeiten, z.B. optionale Imports, spezi-
sogar den Vorteil, Compiler-Warnungen die Namen von Packages spezi ziert, die sche Attribute etc. Für diese sei auf die
für Discouraged Access zu erhalten, wenn vom Bundle benötigt werden. Alterna- hervorragende OSGi-Spezi kation [5]
tiv kann der Manifest Header Require-
wir solche Packages importieren. verwiesen.
Bundle verwendet werden, mit dem
Unser Beispiel, 2. Iteration Unser Beispiel, 3. Iteration
benötigte Bundles spezi ziert werden,
von denen alle exportierten Packages
Das Kern-API-Bundle muss natürlich das Um das Implementierungs-Bundle zu
Package com.weiglewilczek.example.osgi. genutzt werden können. Allerdings erstellen, benötigen wir zunächst die fol-
hat Require-Bundle mehrere Nachteile,
contacts.core als ö entliche Schnittstelle gende bnd-Datei:
insbesondere wird das Prinzip der lo-
deklarieren. Wie oben erläutert, erstellen
# com.weiglewilczek.example.osgi.contacts.core.
sen Kopplung verletzt. Beispielsweise
wir das Bundle Manifest nicht manuell,
inmemory.bnd
wäre es in den meisten Fällen unsinnig,
sondern verwenden Bnd als Eclipse-
Bundle-Version: 1.0.0
wenn sich ein Bundle ganz konkret von
Plug-in, um aus Java-Projekten Bundles
Private-Package: com.weiglewilczek.example.osgi.
einem MySql-Bundle abhängig macht,
einschließlich Bundle Manifest zu erzeu- contacts.core.inmemory.internal
nur weil es das JDBC API benötigt. Mit
gen. Bnd ermittelt bestimmte Informati-
Import-Package hingegen haben wir die
onen für das Bundle Manifest, z.B. die zu
Möglichkeit, die Abhängigkeiten auch
importierenden Packages, durch Analyse Da wir hier kein Package exportieren,
müssen wir Bnd mittels Private-Package
durch andere Bundles zu erfüllen, z.B.
der Klassendateien. Allerdings benötigt
mit einem Oracle-, einem Derby- oder
Bnd auch eine Reihe von Metadaten in mitteilen, welche Packages zum Bundle
Form einer bnd-Datei, die dem Bundle einem anderen Bundle, das das JDBC gehören. Alternativ zur expliziten Anga-
API exportiert. Wir werden daher im
Manifest sehr ähnelt, aber hinsichtlich be von Namen könnte auch die Wildcard
Folgenden ausschließlich Import-Pa-
der Syntax leichter handzuhaben ist. Dar- „*“ verwendet werden. Um die zu im-
ckage verwenden. Analog zu Export-Pa-
über hinaus gibt es zahlreiche Hilfsmittel, portierenden Packages müssen wir uns
ckage werden die Namen der benötigten
z.B. die Verwendung von Wildcards. Für keine Gedanken machen, weil Bnd diese
Packages kommasepariert aufgelistet:
das Kern-API-Bundle benötigen wir die anhand der Klassendateien analysiert.
Import-Package: p1,p2,p3.
folgende bnd-Datei, die wir im Wurzel- Das resultierende Bundle Manifest sieht
Mit dem version-Attribut werden
verzeichnis des Projekts ablegen: folgendermaßen aus.
Versionsintervalle spezifiziert. Dabei
# com.weiglewilczek.example.osgi.contacts.core.bnd Manifest-Version: 1.0
stehen eckige Klammern für geschlos-
Bundle-Version: 1.0.0 Bundle-ManifestVersion: 2
sene und runde Klammern für offene
Export-Package: com.weiglewilczek.example.osgi. Bundle-SymbolicName: com.weiglewilczek.example.
Intervalle, d.h. im ersten Fall gehört die
contacts.core;version=1.0.0 osgi.contacts.core.inme
betro ene Versionsnummer noch zum mory
Intervall und im zweiten Fall nicht: Bundle-Version: 1.0.0
Über M im Kontextme- Import-Package: com.weiglewilczek.example.osgi.
Import-Package: p;version=quot;[1.0.0,2.0.0)quot;
nü der bnd-Datei im Package Explorer contacts.core,org.osgi.
framework;version=quot;1.4quot;
können wir nun das Kern-API-Bundle
erstellen. Es wird unter dem Namen der
bnd-Datei ebenfalls im Wurzelverzeich- Es ist auch möglich, nur eine Versions-
Bundle Life Cycle
nis des Projekts abgelegt und enthält das nummer anzugeben, was einem nach
folgende Bundle Manifest: oben offenen Intervall entspricht, so- Das OSGi Framework stellt die Lauf-
dass alle Versionsnummern größer oder zeitumgebung für Bundles dar: Bundles
Manifest-Version: 1.0 gleich sind: können installiert, aktualisiert und wie-
Bundle-ManifestVersion: 2
der deinstalliert werden. Zudem kön-
Bundle-SymbolicName: com.weiglewilczek.example. Import-Package: p;version=quot;1.0.0quot; nen sie gestartet und wieder gestoppt
osgi.contacts.core
werden. Abbildung 2 zeigt die Zustände,
Bundle-Version: 1.0.0
die ein Bundle während seines Lebens-
Wozu dienen nun die Versionsnum-
Export-Package: com.weiglewilczek.example.osgi.
zyklus innerhalb des OSGi Frameworks
mern? Das OSGi Framework versucht,
contacts.core;version=quot;
einnehmen kann.
zu einem bestimmten Zeitpunkt im Le-
1.0.0quot;
Import-Package: com.weiglewilczek.example.osgi. Bevor wir auf die Frage eingehen,
benszyklus von Bundles deren Abhän-
contacts.core;version=quot;
wie der Lebenszyklus gesteuert wer-
gigkeiten aufzulösen, indem zu jedem
1.0.0quot;
den kann, widmen wir uns der Bedeu-
Package-Import ein passender Packa-
tung der einzelnen Zustände und deren
ge-Export gesucht wird. Dabei werden
Übergängen. Durch das Installieren
natürlich die Versionsnummern be-
Abhängigkeiten eines Bundles wird dieses innerhalb des
rücksichtigt, sofern sie spezi ziert wur-
OSGi Frameworks persistiert, d.h. in
den. Es gibt noch einige weitere Details
Für die Deklaration der Abhängigkeiten
einem lokalen Bundle Cache abgelegt.
hinsichtlich der Au ösung von Abhän-
gibt es zwei Möglichkeiten. Mit dem Ma-
javamagazin 1|2009 29
www.JAXenter.de
5. Core OSGi in kleinen Dosen – Teil 2
setzt. Wenn ein Activator spezi ziert ist,
falls auch dies ohne eindeutiges Ergebnis
wird dessen start()-Methode aufgerufen
bleibt, wird das Bundle mit der kleinsten
und wenn diese erfolgreich zurückkehrt,
ID ausgewählt. Auf diese Weise kann
wird das Bundle auf ACTIVE gesetzt,
vom OSGi Framework immer eine ein-
andernfalls wieder auf RESOLVED.
deutige Zuordnung zwischen einem
Analog verhält es sich mit dem Stoppen.
importierenden und einem exportie-
Um die Startup-Performance zu ver-
renden Bundle getro en werden: Dies
bessern, kann ein Bundle mit dem Ma-
wird Wiring genannt. Es ist jedoch emp-
nifest Header Bundle-ActivationPolicy
fehlenswert, mittels Versionsnummern
Abb. 2: Zustände innerhalb des Bundle Life Cycle
spezi zieren, dass die Aktivierung lazy
und gegebenenfalls weiterer Attribute
erfolgen soll. Dann wird der Aufruf der
möglichst genaue Vorgaben zu tre en,
Die Voraussetzung dafür ist, dass es ein
start()-Methode solange verzögert und
um „selbst die Kontrolle zu behalten“.
gültiges Format und gültige Metadaten
Wichtig: Bundles im Zustand RESOL- das Bundle verbleibt solange im Zustand
enthält. Bei der Installation wird dem
STARTING, bis zum ersten Mal eine
VED können bereits verwendet werden,
Bundle eine eindeutige ID vom Typ long
Klasse aus dem Bundle geladen wird.
indem andere Bundles ihr API benutzen.
zugewiesen und das Bundle wird in den
Zustand INSTALLED versetzt. Wenn ein Bundle deinstalliert
Es ist nicht erforderlich, jedes Bundle zu
wird, geht es zunächst in den Zustand
starten, denn dies dient einem besonderen
Dem OSGi Framework steht o en,
UNINSTALLED über. Sofern es keine
Zweck: Mit dem Manifest Header Bundle-
ob es sofort nach der Installation eines
Activator wird der voll quali zierte Name Packages exportiert, die im Wiring ver-
Bundles oder erst später versucht, des-
wendet wurden, wird es sofort aus dem
einer Klasse angegeben, die das Interface
sen Abhängigkeiten aufzulösen. Eclipse
BundleActivator implementiert: persistenten Speicher des OSGi Frame-
Equinox und Apache Felix z.B. verhalten
works gelöscht. Andernfalls bleiben die
sich hier lazy, um Ressourcen zu scho-
public interface BundleActivator { Package-Exports bis zu einem Neustart
nen. Beim so genannten Resolving ver-
void start(BundleContext context);
des OSGi Frameworks erhalten, sodass
sucht das OSGi Framework für jedes zu
void stop(BundleContext context);
durch das Deinstallieren eines Bund-
importierende Package ein passendes
}
les nicht automatisch alle abhängigen
exportiertes Package zu finden. Nur
Bundles funktionsunfähig werden.
wenn dies für alle nicht optionalen Pa-
Beim Aktualisieren wird ein Bundle
ckage-Imports gelingt, wird das Bundle Wenn ein Bundle einen Activator spe-
in den Zustand RESOLVED versetzt, erneut eingelesen und persistiert. Dabei
zifiziert, wird beim Starten vom OSGi
andernfalls bleibt es INSTALLED und bleibt die Bundle ID erhalten, wohinge-
Framework eine Instanz erzeugt und des-
sen start()-Methode und beim Stoppen gen durch Deinstallieren und anschlie-
kann nicht verwendet werden, bis mög-
dessen stop()-Methode aufgerufen. Da ßendes erneutes Installieren eine neue
licherweise zu einem späteren Zeitpunkt
Bundle ID vergeben wird. Das OSGi
alle Abhängigkeiten aufgelöst werden diese Aufrufe synchron vom Framework
Framework versetzt das Bundle beim
können. read erfolgen, ist es wichtig, dass sie so
Aktualisieren wieder in den Ausgangs-
Falls mehrere passende exportier- schnell wie möglich zurückkehren, um die
zustand, sodass z.B. ein ursprünglich
te Packages vorliegen, wird das mit der Ausführung des Systems nicht zu blockie-
gestartetes Bundle zunächst gestoppt,
höchsten Version verwendet. Falls im- ren. Lang laufende Vorgänge sollten daher
dann erneut eingelesen und aufgelöst
mer noch kein eindeutiger Bezug herge- in eigenen reads ausgeführt werden.
und danach wieder gestartet wird. Auf
stellt werden kann, wird die Version der Beim Starten wird das Bundle zu-
nächst in den Zustand STARTING ver- diese Weise kann ein So waresystem im
exportierenden Bundles verglichen und
laufenden Betrieb feingranular – näm-
lich auf Ebene von Bundles – aktualisiert
Befehl Bedeutung
werden. Mit anderen Worten bietet OSGi
Ps Listet die installierten Bundles mit Basisinformationen auf
ein Hot Deployment auf Modulebene.
install <url> Installiert das Bundle von der angegebenen URL
Life Cycle Management
update <id> Aktualisiert das angegebene Bundle
Wie kann nun der Lebenszyklus von
resolve <id> Löst das angegebene Bundle auf
Bundles gesteuert werden? Dazu bietet
refresh <id> Führt ein Package Refresh für das angegebene Bundle
das OSGi Framework ein schlankes API
start <id> Startet das angegebene Bundle
an, das im Wesentlichen aus den folgen-
den drei Klassen besteht: BundleContext,
stop <id> Stoppt das angegebene Bundle
Bundle, BundleListener.
uninstall <id> Deinstalliert das angegebene Bundle
Der BundleContext stellt die einzige
Shutdown Beendet das OSGi Framework
Schnittstelle zur Interaktion mit dem
Help Listet die verfügbaren Befehle mit Erläuterungen auf
OSGi Framework dar. Um eine Refe-
renz auf den BundleContext zu erhalten,
Tabelle 2: Wichtige Befehle der Apache Felix Text Shell
30 javamagazin 1|2009 www.JAXenter.de
6. OSGi in kleinen Dosen – Teil 2 Core
Sowohl Eclipse Equinox als auch Apache
muss ein Activator verwendet werden, nen Activator (Listing 1) hinzu, der in der
in dessen start()- und stop()-Methoden start()- und stop()-Methode Tracing-Aus-
Felix enthalten diesen Service.
der BundleContext für das jeweilige gaben nach System.out schreibt. Weiter er-
Für das Life Cycle Management bieten
die OSGi-Implementierungen in der Re-
Bundle übergeben wird. Mit dessen
installBundle()-Methoden kann ein gel so genannte Management Agents als
Bestandteil der Implementierung oder als
Bundle im OSGi Framework installiert Listing 1
separate Bundles an. Eclipse Equinox ent-
werden. Als Rückgabe erhalten wir eine public class Activator implements BundleActivator {
Referenz vom Typ Bundle, mit der wir hält die Equinox Console und Apache Fe-
lix bringt per Default die Bundles Shell und
den Lebenszyklus des Bundles steuern public void start(final BundleContext context) {
Shell Text UI mit. Beides sind textbasierte
können, z.B. mit den Methoden start(), System.out.println(MessageFormat.format(”[{0}] starting ...“,
context
stop(), update() und uninstall(). Um Management Agents mit sehr ähnlichen
.getBundle().getSymbolicName()));
Funktionen. Darüber hinaus gibt es weite-
den Lebenszyklus beliebiger Bundles final ContactRepository repository = createRepository();
re Management Agents auf Basis von Swing
zu verfolgen und gegebenenfalls darauf for (final Contact contact : repository.getAllContacts()) {
zu reagieren, können BundleListener oder webbasierte Agents. Letztendlich System.out.println(contact);
}
über den BundleContext beim OSGi kann jedes So waresystem auf Basis von
}
OSGi einen eigenen Management Agent
Framework registriert werden. An die-
se werden BundleEvents versendet, die in Form eines oder mehreren Bundles public void stop(final BundleContext context) {
implementieren. Da wir für unser Beispiel
Informationen über die Änderung im System.out.println(MessageFormat.format(”[{0}] stopping ...“,
Apache Felix verwenden, stellen wir in Ta-
Lebenszyklus enthalten. context
.getBundle().getSymbolicName()));
belle 2 die wichtigsten Befehle für dessen
Wichtig: Es gibt kein API im OSGi
}
Text Shell vor.
Framework zur Steuerung des Resol-
ving. Dazu gibt es einen optionalen private ContactRepository createRepository() {
Unser Beispiel, 4. Iteration
Standardservice, den Package Admin ...
}
Service, der Operationen wie refreshPa- Damit unser Beispiel bereits in diesem
ckages() und resolveBundles() anbietet. Stadium aktiv werden kann, fügen wir ei-
Anzeige
javamagazin 1|2009 31
www.JAXenter.de
7. Core OSGi in kleinen Dosen – Teil 2
Abschließend zeigen wir noch eines
contacts.core.inmemor
y.internal.Activator der OSGi-Highlights schlechthin: Wir
aktualisieren das Implementierungs-
Bundle im laufenden Betrieb. Dazu
Nun ist es an der Zeit, unsere beiden
passen wir dessen Activator an, sodass
Bundles im OSGi Framework zu instal-
er eine andere Menge von Kontakten
lieren, zu starten, zu aktualisieren etc.
Abb. 3: Installierte Bundles auflisten
enthält, lassen Bnd das Bundle erneut er-
Dazu starten wir zunächst Apache Felix
mittels der Run Con guration org.apa- stellen und führen dann in der Konsole
das Kommando update aus.
che.felix aus dem gleichnamigen Projekt.
In der Konsole geben wir ps ein, um die Wie Abbildung 7 zeigt, wird das
Bundle zunächst gestoppt, dann transpa-
aktuell installierten Bundles aufzulisten
rent aktualisiert und anschließend wie-
(Abb. 3).
Abb. 4: Bundles installieren
der gestartet. Und tatsächlich nden wir
Anschließend verwenden wir das
Kommando install, um die Bundles zu einen neuen Kontakt in der Ausgabe.
installieren und listen danach wieder die
Schlussbemerkung und Ausblick
installierten Bundles auf (Abb. 4).
Unsere beiden neu installierten Wir haben die wichtigsten Details des
Abb. 5: Bundles auflösen
Bundles be nden sich nun im Zustand Module und Life Cycle Layer kennen-
INSTALLED. Um sie aufzulösen, geben gelernt: Bundles sind JAR-Archive mit
wir das Kommando resolve mit der ID zusätzlichen Metadaten. Diese werden
Abb. 6: Bundles starten
des Implementierungs-Bundles ein. Da- im Bundle Manifest spezi ziert und de-
durch wird auch das Kern-API-Bundle klarieren u.a. die ö entliche Schnittstelle
aufgelöst, um die Abhängigkeiten er- und die Abhängigkeiten eines Bundles.
füllen zu können, d.h. unsere beiden Das OSGi Framework bietet Bundles ei-
Abb. 7: Bundles aktualisieren Bundles be nden sich nun im Zustand ne Laufzeitumgebung, wo diese u.a. ins-
RESOLVED (Abb. 5). talliert, gestartet und aktualisiert werden
Nun starten wir das Implementie- können. Dazu dient ein Management
zeugen wir beim Starten eine Instanz des
InMemoryContactRepository und geben rungs-Bundle mit dem Kommando Agent der OSGi-Implementierung, z.B.
start. Dadurch wird der Activator ins-
dessen Kontakte nach System.out aus. eine textbasierte Konsole. Im nächsten
tanziiert und dessen start()-Methode
Die zugehörige bnd-Datei muss nun Teil dieser Artikelserie werden wir die
noch um die Bundle-Activator-Direktive ausgeführt, sodass die Tracing-Ausgabe dritte wesentliche Eigenscha von OSGi
sowie die Liste der Kontakte ausgegeben unter die Lupe nehmen: Das OSGi Ser-
erweitert werden, die – abgesehen von
werden (Abb. 6). vice Model.
der Umformatierung in das spezielle
Manifest-Format – in das Bundle Mani-
fest übernommen wird:
# com.weiglewilczek.example.osgi.contacts.core.
inmemory.bnd
Heiko Seeberger ist als Technical Director für die Weigle Wilczek GmbH
Bundle-Version: 1.0.0
tätig. Sein technischer Schwerpunkt liegt in der Entwicklung von Unterneh-
Private-Package: com.weiglewilczek.example.osgi.
mensanwendungen mit OSGi, Eclipse RCP, Spring, AspectJ und Java EE.
contacts.core.inmemory.internal
Seine Erfahrungen aus über zehn Jahren IT-Beratung und Softwareentwick-
Bundle-Activator:
lung fließen in die Eclipse Training Alliance ein. Zudem ist Heiko Seeberger
com.weiglewilczek.example.osgi.contacts.core. aktiver Committer in Eclipse-Projekten, Autor zahlreicher Fachartikel und
inmemory.internal.Activator Redner auf einschlägigen Konferenzen.
Das resultierende Bundle Manifest sieht
nun folgendermaßen aus:
Links & Literatur
Manifest-Version: 1.0
[1] WeigleWilczek-Examples: www.weiglewilczek.com/examples/
Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.weiglewilczek.example. [2] Bnd: www.aqute.biz/Code/Bnd
osgi.contacts.core.inme
[3] Apache Felix: felix.apache.org
mory
[3] OSGi Alliance: www.osgi.org
Bundle-Version: 1.0.0
[3] Manifest Format: java.sun.com/j2se/1.4.2/docs/guide/jar/jar.html
Import-Package: com.weiglewilczek.example.osgi.
[3] OSGi-Spezifikation: www.osgi.org/Specifications/
contacts.core,org.osgi.
[3] Seeberger, OSGi in kleinen Dosen, Teil, Java Magazin 12.08
framework;version=quot;1.4quot;
Bundle-Activator: com.weiglewilczek.example.osgi.
32 javamagazin 1|2009 www.JAXenter.de