Ratgeber

Equinox modernisiert Java-Legacy

09.11.2010
Von Jörg Viola

Zwei Wege bei der Modularisierung

Der Unterschied zum eingangs erwähnten Information Hiding auf Objektebene liegt in der Granularität. Entwickler sind nun gehalten, die gesamte Anwendung in Module zu unterteilen, deren gegenseitige Nutzung vergleichsweise einfach strukturiert ist. Während man dies auf der grünen Wiese von vornherein berücksichtigen kann - und hoffentlich auch ohne OSGi bereits getan hat -, ist die Modularisierung einer Altanwendung eine größere Herausforderung. Entgegen der häufig zu beobachtenden Praxis, eine große Anwendung gleich zu Beginn in viele kleine Teile zu zerlegen, bis sie letztlich völlig destabilisiert ist, raten wir zu einem Vorgehen in kleinen Schritten. Generell wählt man dafür ein iteratives Vorgehen, trennt also Modul um Modul aus der Anwendung heraus, definiert seine Schnittstelle und prüft nach jedem Schritt die korrekte Funktion der Anwendung.

Dabei muss klar sein, dass die Modularisierung zur Laufzeit ein OSGi-Container übernimmt, in dem die Module (OSGi-Jargon: "Bundles") installiert werden. Es gibt also prinzipiell zwei Möglichkeiten, die Modularisierung vorzunehmen:

1. Container-in-App:

Bei dieser Vorgehensweise wird ein zunächst leerer OSGi-Container in die Altanwendung eingebunden, und anschließend wird getestet, ob die Anwendung in dieser Konfiguration problemlos startet. Ist das der Fall, beginnt man schrittweise, kleine Funktionen aus der Anwendung zu isolieren und als Bundle in den Container zu packen. Nach jedem dieser "Umzüge" ist ein Test angeraten. Da OSGi selbst keinen Aufruf der Anwendungs-Bundles von außerhalb des Containers vorsieht, muss für die Kommunikation von Altanwendung und Bundle ein Dispatcher-Dienst im Container vorhanden sein. Er sorgt dafür, dass ein Aufruf von der Altanwendung OSGi-konform an ein Container-Bundle delegiert wird. Entsprechend sind die Aufrufe der Altanwendungsrümpfe zu ändern und die isolierten Bundles mit einer Schnittstelle zum Dispatcher-Dienst zu versehen.

2. App-in-Container:

Auf einem etwas radikaleren Weg kann man die gesamte Altanwendung zu einem großen Bundle schnüren und in den Container packen - der eigentlich von OSGi vorgesehene Ansatz. Das Anwendungs-Bundle startet daraufhin die Anwendung wie gewohnt. Der Anwender startet statt der Anwendung den Container, was typischerweise in Start-up-Skripten verborgen wird.

Anschließend beginnt die eigentliche Arbeit, indem Anwendungscode aus dem großen Bundle extrahiert und als weiteres Bundle installiert wird.

Während der erste Ansatz die Installationsumgebung unangetastet lässt, ist der zweite mit weniger Aufwand für die Kommunikation des Altanwendungsrumpfes mit den Bundles verbunden. In beiden Fällen erhält man ein Geschenk: die einfache Erweiterbarkeit der Anwendung durch Plug-ins. Dies gilt insbesondere, wenn man sich für den OSGi-Container Equinox aus dem Eclipse-Projekt entscheidet. Außerdem gibt es eine Reihe von Standarddiensten, die ein OSGi-basierendes Projekt nutzen kann: Remoting, Logging und Benutzerverwaltung sind nur einige Beispiele.

Eclipse Equinox

Die beliebte Java-Entwicklungsumgebung Eclipse bringt ihren eigenen OSGi-Container mit. Zusätzlich bietet er zum Beispiel:

  • Plug-ins: Module können "Extensions" deklarieren, die die Anwendung abfragen und aufrufen kann.

  • Module können "Buddy"-Modulen tiefere Einsichten erlauben.

  • Mit P2 steht eine mächtige Provisioning (Installations- und Update)-Umgebung zur Verfügung.