Der Event Admin Service

Veröffentlicht in: Eclipse, Java, RCP | 0

Bei der Entwicklung von Software-Architekturen bekommt die Verwendung von Events und EventHandlern eine immer größere Bedeutung. Betrachtet man CQRS – Axon Framework – oder die CDI Events von JEE 6, so ist hier in letzter Zeit ein klarer Trend zu erkennen.

Umso erstaunlicher, dass das Konzept der Events schon seit Oktober 2005 im OSGI Standart – OSGI Service Compendium – existiert. So wird es vom Event Admin Service ermöglicht, Events zu versenden. Diese werden von EventHandlern, die als OSGI Service registriert seien müssen, behandelt. Da es sich bei dem Event Admin Service um einen OSGI Service handelt, kann dieser z.B. über die ServiceRegistry abgefragt werden:

ServiceReference serviceReference = context.getServiceReference(EventAdmin.class.getName());
EventAdmin eventAdmin = (EventAdmin) context.getService(serviceReference);

Um nun ein Event zu versenden, wird wie bei JMS (Java Message Service) ein Topic definiert, aufgrundlage dessen sich entscheidet, welche EventHandler auf das Event reagieren. Im Vergleich hierzu haben sich die CDI- und CQRS-Events deutlich weiterentwickelt, da es sich bei diesen um POJOs handelt, die bestimmen welche EventHandler zuständig sind. Die CDI-Events können zusätzlich noch Annotations als Qualifier verwendet werden, falls zu einem Event verschiedene Handler existieren, die aber nicht alle ausgeführt werden sollen. Sowohl die CDI- als auch die CQRS-Events beinhalten die Informationen, die vom Handler zur weiteren Verarbeitung benötigt werden. Beim Event Admin Service muss stattdessen ein Dictonary erstellt werden, welches diese Informationen in Form einer Map beinhaltet:

Dictionary eventProperties = new Hashtable();
eventProperties.put(„message“, „Hello World“);
Event event = new Event(„my/topic“, eventProperties);
eventAdmin.sendEvent(event);

Der EventHandler selbst muss das gleichnamige Interface implementieren und als OSGI Service mit dem entsprechenden Topic registriert werden. Hier die recht simple Implementierung des EventHandlers:

public class MyEventHandler implements EventHandler {
@Override
public void handleEvent(Event event) {
// handle the event
}
}

Folgendermassen wird nun der EventHandler als OSGI-Service registriert:

Dictionaryproperties = new Hashtable();
properties.put(EventConstants.EVENT_TOPIC, „my/topic“);
context.registerService(MyEventHandler.class.getName(), new MyEventHandler(), properties);

Um den Event Admin Service verwenden zu können, werden folgende Bundles benötigt:

  • org.eclipse.osgi
  • org.eclipse.osgi.services
  • org.eclipse.equinox.event
  • org.eclipse.equinox.ds

Events sind ein sehr gutes Mittel um Softwarearchitekturen zu entkoppeln. So ist es recht verwunderlich, dass es so lange gedauert hat, bis sich dieses Architektur-Pattern auch in anderen Frameworks wiedergefunden hat.

Eclipse Libra

Veröffentlicht in: Eclipse, Java, RCP | 0

Bei Eclipse Libra handelt es sich um ein Unter-Projekt vom Web-Tools-Platform-Projekt (WTP), welches den Funktionsumfang von WTP und dem Plug-in Development Environment (PDE) vereint. So können in einem WTP-Projekt auch die Werkzeuge eines PDE-Projektes genutzt werden.

Für die Installation von Libra unter der aktuellen Eclipse Version Indigo reicht es, auf der Indigo Update-Site die Bundles OSGI Bundle Facet und WAR Products zu installieren.

Erstellt man ein Dynamic Web Project können auf der ersten Seite des Wizards unter Configuration die Project Facets konfiguriert werden. Nach der Installation der oben genannten Pakete ist hier der Menüpunkt OSGI Bundle hinzugekommen, den man auswählt. Dies führt dazu, dass im Wizard eine weitere Seite verfügbar ist, auf der Details für das Manifest angegeben werden können. Das Manifest selbst befindet sich im META-INF Verzeichnis des Web-Ordners, also eine Hierarchiestufe tiefer als in herkömmlichen OSGI Bundles.

Um das Web-Projekt testen zu können, ist zumindest ein Servlet nötig, welches in der web.xml definiert wird:

  <servlet>
<servlet-name>hello</servlet-name>
<servlet-class>test.TestServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>

Das Servlet selber erbt von der Klasse javax.servlet.http.HttpServlet und überschreibt die doGet-Methode.

Sofern nicht bereits eine passende Target-Platform definiert wurde, wird es spätestens bei der Implementierung des Servlet zu einem Compile-Fehler kommen, da javax.servlet nicht aufgelöst werden kann. Zur Ausführung des Web-Projektes mit dem OSGI-Framework kann die Target-Platform von http://wiki.eclipse.org/Gemini/Web verwendet werden.

Bei Gemini selbst, handelt es sich um modulare Enterprise-Technologien, welche speziell für das OSGI-Framework konzipiert wurden.

Für die Installation werden folgende Archive benötigt: http://www.eclipse.org/downloads/download.php?file=/equinox/drops/R-3.7.1-201109091335/org.eclipse.osgi_3.7.1.R37x_v20110808-1106.jar und http://www.eclipse.org/downloads/download.php?file=/gemini.web/release/GW/2.0.1.RELEASE/gemini-web-2.0.1.RELEASE.zip.

Anschließend wird gemini-web in ein beliebiges Verzeichnis entpackt und org.eclipse.osgi.jar in eben dieses kopiert. Nun wird hier noch das Verzeichnis configuration erstellt und die folgenden beiden Konfigurationsdateien hinein kopiert:

http://wiki.eclipse.org/images/0/0b/Config.ini.2.0.1.zip

http://wiki.eclipse.org/images/3/32/Java6-server.profile.zip

Jetzt wird in Eclipse eine neue Target-Platform (Window / Preferences / Target Platform) erstellt, deren Location auf das gemini-web Verzeichnis verweist.

Als nächstes wird eine neue Run-Configuration unter dem Punkt OSGI Framework erstellt. Unter den VM-Arguments wird folgender Parameter hinzugefügt:

-Dosgi.java.profile=file:configuration/java6-server.profile

Außerdem muss als Working directory das gemini-web Verzeichnis angegeben werden.

Weitere Schritte sind nicht nötig, nun kann die Run-Configuration ausgeführt werden und die Web Applikation ist unter http:127.0.0.1:8080/<application-name>/hello verfügbar. Der Applikations-Name wird hier standardmäßig genommen, will man dies ändern, so ist der Parameter Web-ContextPath im Manifest anzupassen.

Die Facets von Eclipse Libra lassen sich nicht nur in WTP-Projekten nutzen. Es ist durchaus möglich, dieses Facet z.B. einem Maven-Projekt zuzuweisen, um hier die PDE Funktionalitäten nutzen zu können. Der Nachteil zu Apache-Felix ist hierbei allerdings, dass die pom.xml und das Manifest separat gepflegt werden müssen. Werden also Maven-Dependendies hinzugefügt, müssen diese auch im Manifest eingetragen werden, damit die Abhängigkeiten zur Laufzeit verwendbar sind.

Veröffentlichung einer Fremdbibliothek als OSGI Plugin

Veröffentlicht in: Eclipse, Java, RCP | 0

Wer mit OSGI arbeitet kennt das. Man findet eine Library die genau das tut, was man benötigt, es liegt nur keine OSGI-Plugin-Variante zum Download bereit.

Eine Möglichkeit ist nun das Jar-Archive zu downloaden und in Eclipse ein neues Projekt Plug-in from Existing JAR Archive zu erstellen. Im nächsten Schritt können nun External JAR Archives hinzugefügt werden. Benötigt man verschiedene Libraries, bzw. hat die gewünschte Library weitere Dependencies, können diese hier direkt hinzugefügt werden. Selbst wenn die verschiedenen Archive eine gleiche package-Struktur aufweisen, ergibt dies keine Probleme, die class-Dateien werden in die entsprechenden Packages gemergt.

Theoretisch ist man nun fertig und man kann die gewünschte Library verwenden. Allerdings werden sich dann die Kollegen bedanken, da sie nun ein weiteres Projekt auschecken müssen. Also exportiert man das soeben erstellte Projekt noch als Deployable plug-ins and fragments, legt das erstellte OSGI-Plugin in die Target-Plattform und kann nun das Projekt wieder schließen.

Sofern die Library nicht in einem Maven-Kontext benötigt wird, ist man nun tatsächlich fertig, andernfalls muss man sie noch manuell in ein Maven-Repository legen.

Eine zweite Möglichkeit, um aus einer Fremdbibliothek ein OSGI-Plugin zu erstellen, ist die Verwendung des Maven Plugins Felix von Apache. Hier wird eine pom.xml der folgenden Art benötigt:

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>de.example</groupId>
<artifactId>de.example.project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>de.example.project</name>
<packaging>bundle</packaging>

<dependencies>
<dependency>
<groupId>de.example</groupId>
<artifactId>de.example.dependency</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/xxx.jar</systemPath>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Export-Package>*</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

Wichtig ist hierbei, dass packaging den Wert bundle erhält, wofür allerdings das Plugin org.apache.felix korrekt eingebunden seien muss. Zu beachten ist hier der Wert true für Extensions.

Als dependency wird im obigen Beispiel die Library de.example.dependency benötigt, die sich in dem aktuellen Maven-Projekt in dem Jar-Archive xxx.jar befindet. Der Ort des Jar-Archives wird im systemPath definiert.

Die class-Dateien der auf diese Weise angegebenen Dependencies werden beim Bauen des Maven-Projektes mittels package mit ins target gelegt. Weiterhin erstellt bei obiger Definition das Plugin Felix ein Manifest in dem alle packages der eingebundenen Libriries exportiert werden. Möchte man diese Einschränken, so können die zu exportierenden packages explizit in der pom-Datei unter Export-Package definiert werden.

Als Fazit lässt sich sagen, dass beide Varianten Arbeit bedeuten und man stehts hoffen sollte, dass die benötigten Libraries bereits als OSGI-Plugin zur Verfügung stehen. So lohnt sich immer zuerst ein Blick auf das SpringSource Enterprise Bundle Repository, da hier bereits viele Libraries als OSGI-Bundle vorliegen: http://ebr.springsource.com/repository/app/

Migration eines Eclipse RCP Projektes auf 4.x

Veröffentlicht in: Eclipse, Java, RCP | 0

Zur Zeit liegt das Eclipse SDK in Version 4.1 zum Download unter http://www.eclipse.org/eclipse4/ bereit. Im Gegensatz zum Early Adopter Release (Version 4.0) verwendet die Version 4.1 die neuere Indigo Update Seite, die seit dem 22 Juni 2011 zur Verfügung steht. Der Vorgänger verwendete hier noch die Update Seite von Helios.

Für die Migration eines bestehenden RCP Projektes auf das Eclipse SDK 4.1 habe ich mich dazu entschieden, dass Produkt Plugin komplett zu ersetzten, um die Vorteile von Eclipse 4.x direkt verwenden zu können. Insgesamt besteht das Projekt aus 13 reinen Plugin Projekten und weiteren 3 Projekten, die sowohl dem Server als auch dem Client zur Verfügung stehen. Hierbei handelt es sich um Maven Projekte, das Manifest wird mit dem Maven Plugin Felix erstellt. Weiterhin wird in den Client Projekten Spring DM eingesetzt, die OSGI Services werden hierüber veröffentlicht.

Nachdem das Eclipse SDK installiert ist fällt einem neben dem veränderten Aussehen vor allem die Geschwindigkeit auf, mit der sich nun die Plugins installieren lassen. Selbst die Installation von größeren Plugins wie WTP gehen extrem schnell vonstatten. Nach der Installation der benötigten Plugins (Eclipse e4 Tools, Subclipse, WTP, Maven, Maven Extras) werden zunächst alle Projekte in den aktuellen Workspace ausgecheckt, mit Ausnahme von der Target Plattform und dem Produkt Plugin.

Schnell ist ein neues Projekt angelegt, welches als neues Target dienen soll. Hier werden nun die benötigten neuen Eclipse SDK 4.1 Plugins rein kopiert und natürlich alle anderen verwendeten OSGI Libraries. Nun fügt man dem Projekt noch die Target Definition hinzu und konfiguriert sie entsprechend. Nachdem nun die von Eclipse verwendete Target Plattform auf das neu angelegte Target gewechselt wurde, dürften die Compile-Fehler in den Projekten verschwunden sein.

Anschließend kann das neue Produkt Plugin erstellt werden, hierbei handelt es sich zunächst um ein ganz normales „Plug-in Project“, welches als OSGI Framework Equinox verwendet. Öffnet man nun das Manifest kann man mit einem Klick auf Extensions den entsprechenden Reiter sichtbar machen. Nun fügt man als Abhängigkeit org.eclipse.equinox.app hinzu und setzt das Häkchen bei „This plug-in is a singleton“. Anschließend fügt man die Extension org.eclipse.core.runtime.products
hinzu und trägt bei ID product ein. Dem Feld wird nun ein Product hinzugefügt mit der Application org.eclipse.e4.ui.workbench.swt.E4Application und einem beliebigen Namen. Dem Product wiederum wird die Property appName mit einem entsprechenden Namen hinzugefügt. Es wird noch eine zweite Property mit dem Namen applicationXMI benötigt, mit dem Wert <Projektname>/Application.e4xmi. Die entsprechende Datei existiert zum jetzigen Zeitpunkt noch nicht, wird aber im folgenden Schritt angelegt.

Dem Projekt wird nun ein neues Application Model hinzugefügt. Dies ist nur möglich, wenn vorher die Eclipse e4 Tools erfolgreich installiert worden sind. Als Container wird das Produkt Projekt angegeben, der Dateiname Application.e4xmi sollte beibehalten werden.

In dem sich nun öffnenden Editor fügt man unter Windows ein Trimmed Window hinzu, hier kann der Titel und die gewünschte Fenster-Größe definiert werden. Nun benötigt das Projekt noch eine Product-Configuration. Sobald sich der entsprechende Editor geöffnet hat, fügt man neben den eigenen Projekten noch folgende Abhängigkeiten hinzu:

  • org.eclipse.equinox.ds
  • org.eclipse.equinox.event
  • org.eclipse.e4.ui.workbench.renderers.swt

Nun kann das neu erstellte Produkt zum ersten Mal gestartet werden, es wird sich ein leeres Fenster in der gewünschten Größe mit dem angegebenen Titel öffnen.

Will man nun noch Spring DM verwenden, muss anschließend noch das Bundle org.springframework.osgi.extender gestartet werden. Werden jetzt die eigenen Bundle gestartet, erkennt Spring DM – sofern vorhanden – die XML-Konfigurationsdateien im META-INF Ordner und fährt für die jeweiligen Bundle den Spring Context hoch.

Jetzt erst wird die erste Java Klasse im Product Projekt erstellt, die bisher benötigten Standard Implementierungen von

  • ActionBarAdvisor
  • WorkbenchAdvisor
  • WorkbenchWindowAdvisor
  • IApplication
  • IPerspectiveFactory

sind endlich nicht mehr nötig.

Stattdessen kann direkt mit der Implementierung von Funktionalitäten begonnen werden, für ein simples Beispiel reicht zunächst einmal ein ExitHandler zum Beenden der Workbench aus.

public class ExitHandler {

@Execute
public void execute(IWorkbench workbench) {
workbench.close();
}

}

Die Workbench selber, wird dem ExitHandler hierbei von OSGI per Dependency Injection übergeben. Es können beliebige weitere Parameter verwendet werden, wie z.B. in Spring DM exportierte OSGI Services oder andere OSGI Komponenten. Kann OSGI die entsprechenden Klassen nicht injizieren kommt es zu einer RuntimeException.

Um den ExitHandler zu verwenden müssen nun noch ein paar Einstellungen in der Application.e4xmi vorgenommen werden.  Zunächst wird ein Command erstellt mit der Id app.exit und dem Namen Exit. Jetzt wird ein Handler erstellt, der das gerade erstellte Command verwendet und der auf den ExitHandler als Implementierung verweist.

In dem Trimmed Window kann anschließend ein Main Menu erzeugt werden, dieses wiederum erhält ein Menu und dieses schlussendlich ein HandledMenuItem, welches das Exit Command Aufruft.

Natürlich soll das Applikations-Fenster entsprechenden Inhalt bekommen. Hierzu wird, wie in der Vorgänger Version, eine View benötigt. Mittlerweile muss diese aber nicht von ViewPart Erben, ein ganz normales POJO reicht als View aus. Lediglich über dem Konstruktor wird eine @Inject Annotation benötigt, so dass das Parent Composite vom OSGI Framework übergeben werden kann.

  @Inject
public MyView(Composite parent) {
// do what you have to do – something with ui for example
}

Um die View zu verwenden muss auch diesmal eine Anpassung in der Application.e4xmi vorgenommen werden. Unterhalb des Trimmed Window befindet sich der Punkt Controls, hier kann nun ein Part Stack erstellt werden. Dieser bekommt wiederum einen Part der die soeben erstellte MyView Klasse zur Ausführung erhält.

Dieser Artikel soll einen kurzen Einblick in Eclipse SDK 4.x vermitteln und erläutern wie man einfach ein bestehendes RCP Projekt migrieren kann. Grade die endlich in OSGI integrierte Dependency Injection und das neue Application Model mit dem hilfreichen und einfach zu bedienenden e4xmi-Editor machen Freude.