ekkes corner - ekkes ecke
ekkes corner - ekkes ecke

PDE und 3rdParty Bundles
Dienstag, 9. September 2008
Wer eine OSGI - basierte Enterprise Anwendung entwickelt, wird immer an einen Punkt kommen, wo es um das Einbinden externer Bibliotheken, Bundles oder ganzer Projekte geht. Das PDE Tooling bietet vielfältige Unterstützung.
Es sind dabei aber einige Regeln zu beachten, auf die ich in den letzten Monaten schon öfter hingewiesen habe in meinen Blogs, da ansonsten das Zusammenbauen von OSGI Anwendungen in Chaos ausartet.
1. Bibliotheken (JAR Files) als Bundles
Als guter Bürger der OSGI Welt gibt es eine Grundregel:
Regel 1: Abhängige Bibliotheken (JAR - Files) nicht im eigenen Bundle „verstecken“, sondern auslagern in ein separates Bundle und die Abhängigkeiten in der MANIFEST.MF beschreiben.
Dies macht es leichter, Bundles wiederzuverwenden und eigene Bundles mit anderen zusammenspielen zu lassen.
PDE macht es sehr einfach, aus JAR - Files Bundles (Plug-Ins) zu erzeugen: New - Plug-In Development - Plug-in from existing JAR - archives aufrufen, die JAR File auswählen und das wars schon. Aber ACHTUNG - diese komfortable Möglichkeit nur als letzte Variante nutzen !
Die nächste Regel für OSGI Bürger lautet:
Regel 2: Gibt es für eine JAR - File bereits ein Bundle in einem der grossen Repositories, dann wird dieses genutzt und kein eigenes erzeugt.
Woher weiss ich, ob es schon ein Bundle für JAR - Files gibt ? Ich gehe bei meiner Suche wie folgt vor:
a)gibt es das Bundle schon im SpringSource Enterprise Bundle Repository ? SpringSource ist meine erste Wahl, da hier alle Bundles mit Abhängigkeiten sehr übersichtlich beschrieben sind. Ein Dank an das SpringSource Team für diese hervorragende Arbeit.
b)gibt es das Bundle im Orbit Repository ? Eine Übersicht findet sich hier.
c)zur Sicherheit nochmal bei OSGI suchen unter OBR Bundle Repository.
d)wenn alle Suchen erfolglos sind, dann baue ich das Bundle selbst mit PDE Tooling wie oben beschrieben. Handelt es sich um ein allgemeines JAR - File, das auch in anderen Projekten genutzt wird, dann erstelle ich bei SpringSource im JIRA einen Eintrag und wünsche mir dort dieses Bundle. Vor einiger Zeit benötigte ich Bundles für die Drools Regelmaschine, die es in keinem der Repositories gab. Daher habe ich einen Eintrag erstellt im JIRA des SpringSource Repositories. Nach kurzer Zeit: „Mission completed“ - wer jetzt sucht, findet zB: Drools Rules Engine Core.
2. Nutzung fremder Bundles
Jetzt haben wir also Bundles gefunden, die unsere Funktionalität und API zur Verfügung stellen und wir können die Bundles in unser eigenes OSGI Projekt einbauen.
Der einfachste Weg, den ich immer wieder sehe: Ein Bundle wird benötigt, also mit Require-Bundle einbauen. Und da es so einfach und schnell geht, alles gleich wieder Exportieren durch Anclicken von „Re-Export this dependency“.
Eine saubere OSGI Architektur erfordert etwas mehr Denkarbeit - man wird dafür dann mit einer Lösung belohnt, die sich besser mit anderen Bundles kombinieren lässt.
Meine nächste Regel, über die sicher kontrovers diskutiert werden kann:
Regel 3: Wenn möglich Abhängigkeiten über Import-Package definieren. Nur die Packages exportieren, die „public“ sind - keine internen. Require-Bundle nur verwenden bei Abhängigkeiten innerhalb des eigenen „Universum“, nicht gegen allgemeine Bundles. Require-Bundle, Import-Package und Export-Package immer versionieren.
Require-Bundle bezieht sich immer auf ein Bundle mit einem ganz speziellen Namen und z.B. ein Eclipse Orbit Bundle (org.apache.commons.logging) kann dann nicht gegen ein SpringSource Bundle (com.springsource.org.apache.commons.logging) ausgetauscht werden.
Import-Package dagegen ist nicht abhängig vom Namen des Bundles, also flexibler. Natürlich ist es mehr Arbeit, sich die genauen Package - Abhängigkeiten auszuarbeiten, als über Require-Bundle mit einem Click automatisch alles zu importieren (inklusive interner Klassen !).
Ein weiterer Vorteil von Import-Package: Eclipse Riena benötigt beispielsweise ein spezielles Hessian Bundle mit Eclipse Buddy Policy. Versucht jetzt ein Bundle, Hessian per Require-Bundle zu verwenden und verweist nicht auf das von Riena genutzte, dann kann dies - je nach Anwendungsfall - ein grosses Problem sein. Import-Package vermeidet diesen Trouble.
Aufgrund meiner Erfahrungen mit PDE sollten auf jeden Fall folgende Regeln beachtet werden:
Regel 4: Niemals in einem Bundle Packages, die das Bundle selbst beinhaltet, gleichzeitig über Import-Package und Export-Package in der MANIFEST.MF definieren. Das kann dazu führen, dass PDE Cycles erkennt und nicht mehr alle Funktionalitäten des Toolings erlaubt sind.
s.a. Bugzilla 246615, 246617 und 208011.
Regel 5: Vor dem Erzeugen eines Bundles, das Export-Package beinhaltet, die Package-Uses neu ermitteln lassen. Fehlerhafte Package-Use Eintragungen hindern PDE am Export von Plug-Ins.
s.a. Bugzilla 246615.
Regel 6: Vermeide verschachtelte JAR - Files - besser sind mehrere separate Bundles.
s.a. Bugzilla 157375. - besonders Kommentar #31.
Wenn eine Abhängigkeit zu einem „fremden“ binären Bundle mit verschachtelten JAR Files zu PDE Build - Problemen führt, hilft es meist, ein anderes Plug-In, das die entsprechende Klasse exportiert, in den Workspace zu laden. Achtung: Dieses Plug-In wird nur zum Build / Compile benötigt - nicht fürs Runtime oder OSGI Launch Configurations, da Equinox kein Problem mit verschachtelten JAR Files hat.
Wer sich an diese DOs & DON‘Ts hält, sorgt dafür dass sich die Bundles des eigenen Projekts leicht von fremden Projekte integrieren lassen.
3.Integration anderer (fremder) OSGI Projekte
Aber die Welt ist nicht so einfach, wenn komplexe OSGI Enterprise Anwendungen gebaut werden. Wir müssen damit leben, dass sich nicht alle anderen Projekte an diese Regeln halten.
Ein kleines Beispiel ist die Einbindung des OSGI EJB3 Containers EasyBeans. EasyBeans besteht aus verschiedenen Komponenten, Utilities, einem Agent, verschiedenen Examples, sowie einem Core Bundle.
Verstoss gegen Regel 1 und Regel 2:
Das Bundle org.ow2.easybeans.core enthält eine Unmenge an JAR Files (das Bundle ist 12 MB gross), wobei eine Vielzahl dieser JAR Files in den OSGI Repositories bereits als Bundle vorliegt. Dies erschwert eine eigene saubere Architektur. Das Problem ist bei EasyBeans erkannt und wird hoffentlich in Zukunft verbessert.
Verstoss gegen Regel 4 und Regel 5:
org.ow2.easybeans.core verursacht Probleme bei der PDE Dependency Analyse: PDE stellt cycles fest. Solange ich die EasyBeans Bundles nur nutze, z.B. in OSGI Launch Configurations, läuft alles einwandfrei.
Die Probleme treten dann auf, wenn ich eigene Bundles habe mit Abhängigkeiten zum org.ow2.easybeans.core Bundle: PDE lässt keinen Export als Deployable Plug-In mehr zu, wenn Cycles oder inkorrekte Package - Uses festgestellt werden. (s.a. Bugzilla 246615)
Ein kleiner Tip, wie es doch geht:
Zunächst das Bundle org.ow2.easybeans.core als Source Projekt in den Workspace laden.
a)PDE stellt beim Export eines Bundles als Deployable Plug-In mit Abhängigkeiten zu org.ow2.easybeans.core inkorrekte Package-Uses fest. Die MANIFEST.MF vom org.ow2.easybeans.core Bundle im Workspace öffnen und unter Karteireiter Runtime - Exported Üackages die Uses neu kalkulieren. Dann die MANIFEST.MF speichern und unser Bundle nochmal als Deployable Plug-In exportieren.
b)PDE stellt jetzt Cycles fest. Wiederum die MANIFEST.MF öffnen, Karteireiter Dependencies und unter Dependency Analysis „Find unused Dependencies“ aufrufen und alle gefundenen löschen. Die MANIFEST.MF speichern und nochmals exportieren als Deployable Plug-In für unser Bundle aufrufen.
Jetzt lässt sich unser von easybeans.core abhängiges Bundle exportieren.
Hinweis: Mit diesem manipulierten core Bundle ist PDE zufrieden - es ist aber nicht lauffähig ! Daher in OSGI Launch Configurations nicht das in den Workspace kopierte org.ow2.easybeans.core Bundle auswählen.
Probleme mit Bundle - Dateinamen:
Die Dateinamen der Bundles bei EasyBeans sind z.B.
easybeans-component-hsqldb-1.1.0-SNAPSHOT
während Eclipse dieses Format erwartet:
easybeans-component-hsqldb_1.1.0-SNAPSHOT
Sehen Sie den Unterschied ? Eclipse hat vor der Versionsnummer 1.1.0 ein Underline (_) und EasyBeans hat einen Bindestrich (-).
Ich ändere daher nach dem Download von EasyBeans jeweils die Dateinamen. Dann kann ich z.B. in der bundle.info der config.ini Datei nur den Plugin - Namen angeben. Mit Bindestrich muss ich den ganzen Dateinamen angeben, d.h. bei jedem Versionswechsel anpassen (Bug JIRA).
Probleme mit Bundle - Symbolic Names:
PDE hat ein Problem mit Bindestrichen im Symbolic Name. (s.a. Blog A dash of legacy von Chris Aniszczyk).
EasyBeans hat einige Util Bundles, die Bindestriche enthalten (z.B.org.ow2.bundles.ow2-util-event-api). Wenn solche Bundles in den Workspace geladen werden, erhalten sie sofort einen Error Marker (Bundle symbolic name contains illegal characters. Legal characters are A-Z a-z 0-9 . _). Die Änderung von Bindestrich in Underline behebt das Problem.
Fazit:
Die hier vorgestellten Lösungen sollten auch bei anderen OSGI Enterprise Projekten helfen, die „fremde“ Bundles oder Projekte integrieren müssen.
Häufig treten Probleme mit dem Logging auf: dazu bitte auch meine Blogs zum Logging in OSGI Projekten lesen.
Follow - Up:
Es folgen noch einige Blogs, die konkret den Einsatz von EasyBeans 1.1.0 zusammen mit Equinox 3.4 und Eclipse Riena 1.0.0 M4 erläutern.
Eclipse Plug-In Development Environment (PDE) bietet eine sehr gute Toolunterstützung bei der Entwicklung von OSGI Enterprise Anwendungen.