Die anpassbare Anwendung

Anwendungsmodularisierung

In einem klassischen Application-Server wird die Anwendung üblicherweise als Ganzes deployt, was grundsätzlich im OSGi-Container auch möglich ist. Allerdings bietet es sich an, die eigene Anwendung in mehrere Bundles aufzuteilen und diese einzeln in den Container zu deployen. Ein Beispiel dafür wäre ein DAO Bundle, das lediglich die DAO-Objekte beinhaltet und diese als OSGi-Services bereitstellt. Die DAOs könnten anschließend von jedem Bundle referenziert werden, wodurch nicht nur die eigene Anwendung Zugriff darauf hat, sondern auch jedes Plug-in, das nachträglich installiert wird. Ein typischer Anwendungsfall dafür wäre z. B. ein Reporting-Plug-in, das auf die Daten zur Analyse zugreifen muss. Wurde erst mal mit dem Auslagern in separate Bundles begonnen, wird schnell der Punkt erreicht, an dem im ursprünglichen WAR nur noch eine dünne Webschicht übrig bleibt, eben gerade der Teil, der einen Servlet-Container benötigt. Neben dem Servlet-Kontext bzw. dem Spring-Kontext ist durch die Modularisierung auch ein Bundle-Kontext in jedem neuen Bundle hinzugekommen. In der Vergangenheit war es durchaus aufwändig, den Kontext eines Bundles mit Leben zu füllen, bis schließlich SpringSource mit Spring DM einen innovativen Ansatz wagte. Plötzlich war es möglich, Dependency Injection innerhalb eines Bundles zu nutzen und auf deklarative Art die Spring Beans als OSGi-Services zu exportieren bzw. umgekehrt, Services als Beans zu referenzieren. Das Konzept hat schließlich so überzeugt, dass Spring DM in den OSGi-4.2-Standard unter dem Namen Blueprint aufgenommen wurde. Die Blueprint-Konfiguration in Listing 4 zeigt sehr schön, dass selbst das Spring-typische XML-Format in den Standard eingeflossen ist und der Unterschied zu einer klassischen Spring-DM-Konfiguration lediglich in den verwendeten Namespaces liegt.

Listing 4

In dem Beispiel wird ein DAO-Objekt erzeugt, ein JPA Entity Manager injiziert und nachfolgend das DAO als Service exportiert. Da die meisten Container, Apache Aries als Blueprint-Implementierung einsetzen, kann problemlos der Aries-eigene Namespace für die JPA-Integration verwendet werden. Leider unterstützt Blueprint keine Servlets und es gibt auch keine direkte Integration mit anderen Frameworks wie Spring MVC. Aus diesem Grund muss der Zugriff auf OSGi-Services aus einem WAR Bundle über JNDI stattfinden. Listing 5 zeigt eine Spring-Konfiguration, die das DAO von oben per JNDI referenziert.

Listing 5
Das Plug-in-System implementieren

Plug-ins sollen die Funktionalität einer Anwendung erweitern und benötigen daher ein API, das das erlaubt. Über dieses API muss es natürlich möglich sein, bestimmte Daten und bestehende Funktionen zu nutzen, was durch die Verwendung von OSGi-Services relativ gut sichergestellt werden kann. Zugleich muss es der Anwendung selbst aber auch möglich sein, auf die Funktionen der installierten Plug-ins zuzugreifen. Das geschieht über so genannte Erweiterungspunkte, die als solche klar definiert werden und für die es entsprechende Java-Interfaces geben muss. Ein Plug-in kann damit eine Implementierung eines solchen Interface bereitstellen und sie als OSGi-Service exportieren, während die Anwendung das Serviceobjekt referenziert. Blueprint unterstützt ebenfalls das Referenzieren einer Liste von OSGi-Serviceobjekten, wie in Listing 6 dargestellt ist.

Listing 6

Dadurch kann eine Anwendung in die Lage versetzt werden, viele Erweiterungen aus unterschiedlichen Plug-ins für einen Erweiterungspunkt zu laden. Schwierig ist es jedoch, eine Anwendung so zu entwerfen, dass sie die richtigen Erweiterungspunkte bereitstellt. Der erste Schritt ist also zu klären, was überhaupt erweiterbar sein soll. Bei einer Webanwendung mit einer klassischen, menügeführten Navigation könnte ein Plug-in einen weiteren Menüpunkt bereitstellen und somit einen neuen Seitentyp definieren. Das kann auch für die Erweiterung einer Administrationsoberfläche sehr nützlich sein, denn ein Plug-in muss auch konfiguriert werden. Auch das oben erwähnte Beispiel mit der Projektliste, die auf der Detailseite in einem Mitarbeiterverzeichnis angezeigt werden soll, wirft eine Reihe von Fragen auf, denn schon beim Entwurf des UIs muss die Möglichkeit für weitere Inhalte eingeräumt werden. Dazu kommt, dass diese Inhalte vom Plug-in bereitgestellt werden und sich trotzdem gut in die Anwendung integrieren müssen. Eine Lösung wäre ein Erweiterungspunkt, der Linklisten liefert. Zu einer Benutzerkennung, z. B. einer E-Mail-Adresse, würde ein Plug-in eine HashMap liefern, deren Einträge URLs und Linknamen sind. Eine derartige Erweiterung zu implementieren, dürfte vom Aufwand her überschaubar sein. Genauso ist das Bereitstellen derartiger Erweiterungspunkte gut zu realisieren, denn das Rendern einer HashMap als Linkliste ist womöglich bereits an anderer Stelle implementiert. Vor allem behält ein Entwickler hierbei die volle Kontrolle über die Darstellung der Inhalte, schließlich liefert das Plug-in nur ein paar Rohdaten. Der Mechanismus ist selbstverständlich erweiterbar und so könnte das Abrufen weiterer Informationen über die Links hinzukommen. Wichtig ist nur, dass die Schnittstelle nicht zu speziell wird, denn ein Erweiterungspunkt, der beliebige Linklisten liefert, ist weit häufiger einsetzbar als einer, der sich nur auf Projektlinks spezialisiert hat. Ein anderer Mechanismus, der vor allem bei Anwendungen wie Blogs oder Wikis zur Erweiterung gerne genutzt wird, sind Filter. Wird das HTML für einen Bereich gerendert, ruft die Anwendung alle bereitgestellten Filter auf. Diese können das HTML bearbeiten, indem sie auf bestimmte Muster im gefilterten Inhalt reagieren. Ein Beispiel wäre eine Projektmanagementanwendung, in der auch die beteiligten Mitarbeiter namentlich aufgeführt werden. Ein Plug-in könnte wiederum einen Filter für die Mitarbeiternamen bereitstellen, der aus den Namen Links macht, um auf die Profilseite im Mitarbeiterverzeichnis zu verweisen.

Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.