O'Reilly logo

Die OSGi Service Platform: Eine Einführung mit Eclipse Equinox by Matthias Lübken, Bernd Kolb, Nils Hartmann, Gerd Wütherich

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

363
21 Erweiterungen des
OSGi Class Loading
Motivation
In Kapitel 5 haben wir Ihnen vorgestellt, wie Package-Abhängigkeiten
zwischen Bundles explizit über entsprechende Bundle Manifest Header
spezifiziert werden. Mit dem
Dynamic-ImportPackage-Header besteht
dabei die Möglicheit, Packages zu importieren, die zur Entwicklungs-
zeit unbekannt sind, was insbesondere beim dynamischen Laden von
Klassen bspw. über
Class.forName() relevant ist. Um dabei beliebige
Packages importieren zu können, muss die Wildcard
* verwendet wer-
den, womit potenziell auf alle exportierten Packages zugegriffen wer-
den kann.
Mit dem Equinox Buddy Class Loading stellen wir Ihnen in diesem
Kapitel einen alternativen Mechanismus vor, mit dem ein Bundle ver-
schiedene Stategien spezifizieren kann, um zur Laufzeit auf zusätzliche
Packages zugreifen zu können.
Darüber hinaus zeigen wir Ihnen, wie durch die Verwendung von
Equinox-spezifischen Export-Package-Direktiven die Sichtbarkeit
exportierter Bundles gezielt eingeschränkt werden kann.
Eindordnung
Die in diesem Kapitel vorgestellten Class-Loading-Erweiterungen
ergänzen das in der Module-Schicht der OSGi-Spezifikation beschrie-
bene Class-Loading-Verhalten einer OSGi Platform, das wir Ihnen
bereits in Kapitel 5 ausführlich vorgestellt haben.
21.1 Tutorial: Grußbotschaften aus XML-Datei einlesen
Ein alternativer
Translation Service
Um Ihnen die Class-Loading-Erweiterungen von Eclipse Equinox
praktisch zu demonstrieren, modifizieren wir das »Hello World«-Bei-
spiel aus Unterkapitel 12.1. Der Translation Service soll seine lokali-
sierten Nachrichten nicht mehr aus Property-Dateien auslesen. Statt-
dessen implementieren wir ein eigenes Domain-Objekt, das Message
Dictionary, das die Nachrichten für jeweils eine Sprache verwaltet. Die
Nachrichten selber werden dabei in einer XML-Datei abgelegt (der
21 Erweiterungen des OSGi Class Loading364
Einfachheit halber verzichten wir hierbei auf die Verteilung der XML-
Dateien in unterschiedliche Fragment-Bundles).
Der XStream Service
Um die XML-Dateien einzulesen und das Message Dictionary mit
den Übersetzungen zu befüllen, benutzen wir die XStream-Bibliothek
[], die ein automatisches Deserialisieren von Objekten aus XML-
Dateien ermöglicht. Diese Bibliothek binden wir in einem eigenen
Bundle
org.osgibook.xstream ein. Um Objekte aus XML-Dateien zu
deserialisieren, implementieren wir einen XStream Service, der den
Namen einer XML-Datei entgegennimmt und ein deserialisiertes
Objekt zurückliefert (vgl. Abb. 21–1).
Problemstellung
Das konstruktive Problem, das es in diesem Beispiel zu lösen gilt, ist,
dass das Bundle
org.osgibook.xstream keinerlei Kenntnis von den
Bundles hat, die den XStream Service benutzen. Insbesondere hat es
dadurch auch keinen Zugriff auf die in diesen Bundles enthaltenen
Klassen. Trotzdem muss der XStream Service in der Lage sein, Objekte
von Klassen zu instanzieren, die sich in den nutzenden Bundles befin-
den (in diesem Fall der Klasse
MessageDictionary). Eine vergleichbare
Abb. 21–1
Überblick über die
beteiligten Bundles
TranslationService
verwendet
Klassen aus
verwendet
Service
org.osgibook.helloworld
OSGI-INF
META-INF
org.osgibook.translation
META-INF
org.osgibook.translation.impl
OSGI-INF
META-INF
translation_de_DE.xml
translation_en_US.xml
XStreamService
MANIFEST.MF
META-INF
org.osgibook.xstream
OSGI-INF
lib
36521.1 Tutorial: Grußbotschaften aus XML-Datei einlesen
Problematik stellt sich bspw. beim Einsatz von OR-Mapping-Tools
wie Hibernate [Link].
Die Plug-in-Projekte
In Abb. 21–2 sind die fertigen Plug-in-Projekte aus diesem Tutorial
dargestellt.
Schritt 1a: Anlegen der Bundles org.osgibook.xstream
Legen Sie zunächst ein neues Bundle org.osgibook.xstream an, das den
im Folgenden dargestellten Import-Package-Header besitzt. Da wir
den XStream Service in Form einer Service Component realisieren,
fügen Sie bitte den entsprechenden Service-Component-Header zum
Bundle Manifest hinzu:
Import-Package: org.osgi.framework;version="1.3.0",
org.osgi.service.component;version="1.0.0"
Service-Component: OSGI-INF/component-description.xml
Abb. 21–2
Die Plug-in-Projekte
21 Erweiterungen des OSGi Class Loading366
Schritt 1b: Einbinden der XStream-Bibliothek
Laden Sie dann von der Projekt-Homepage http://xstream.code-
haus.org/download.html das XStream-Jar-File herunter (»XStream
Core only«) und speichern Sie es im Ordner
lib des Bundles. Denken
Sie daran, das Jar-File auch in den Bundle-Klassenpfad aufzunehmen.
Bundle-ClassPath: lib/xstream-1.2.2.jar,
.
Schritt 1c: Implementierung des Interface XStreamService
Legen Sie nun Service-Interface org.osgibook.xstream.XStreamService an,
das die Methode
readObject definiert. Dieser Methode muss der Pfad
einer XML-Datei (relativ zum definierenden Bundle) übergeben wer-
den. Als Ergebnis liefert sie das deserialisierte Java-Objekt zurück (vgl.
Listing 21–1):
package org.osgibook.xstream;
public interface XStreamService {
public Object readObject(String path);
}
Fügen Sie das Package org.osgibook.xstream als exportiertes Package
zum Bundle Manifest hinzu, damit die anderen Bundles darauf zugrei-
fen können:
Export-Package: org.osgibook.xstream
Schritt 1d: Implementierung der XStream-Komponente
Die Implementierung des XStream Service realisieren wir als Service
Component innerhalb des Packages
org.osgibook.xstream.internal. Die
XStream Component wird von uns als Service Factory realisiert, d.h.,
jedes nutzende Bundle erhält eine eigene Instanz des XStream Service.
Das Bundle, für das jeweils eine konkrete Instanz erzeugt wurde, kön-
nen wir in der
activate()-Methode am Component Context abfragen.
So kann dann innerhalb der
readObject()-Methode direkt auf das nut-
zende Bundle zugegriffen werden (vgl. Listing 21–2).
package org.osgibook.xstream.internal;
[...]
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
Listing 21–1
Das Interface
XStreamService
Listing 21–2
Die Klasse
XStreamComponent
36721.1 Tutorial: Grußbotschaften aus XML-Datei einlesen
public class XStreamComponent implements XStreamService {
private XStream xstream;
private Bundle bundle;
protected void activate(ComponentContext context) {
bundle = context.getUsingBundle();
this.xstream = new XStream(new DomDriver());
}
public Object readObject(String name) {
URL url = bundle.getResource(name);
try {
return xstream.fromXML(
new InputStreamReader(url.openStream()));
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
}
Schritt 1d: Anlegen der Komponentenbeschreibung
Abschließend legen Sie die Beschreibung der XStream-Komponente
wie folgt an:
<?xml version="1.0"?>
<component name="xstreamComponent">
<implementation
class="org.osgibook.xstream.internal.XStreamComponent"/>
<service servicefactory="true">
<provide interface="org.osgibook.xstream.XStreamService"/>
</service>
</component>
Schritt 2a: Anlegen der Klasse MessageDictionary im Bundle
org.osgibook.translation.impl
Legen Sie nun im Bundle org.osgibook.translation.impl die Klasse
org.osgibook.translation.impl.MessageDictionary an, die das künftige
Wörterbuch für den Translation Service implementiert. Diese Klasse
enthält eine Map mit der lokalisierten Nachricht. Darüber hinaus gibt
es eine Methode
getMessage(), über die eine übersetzte Nachricht für
einen Key abgefragt werden kann (vgl. Listing 21–4):
Listing 21–3
Die Datei OSGI-INF/
component-
description.xml

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required