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.

Erstellung einer Android Anwendung

Veröffentlicht in: Android, Java | 0

Um ein Android-Projekt zu Erstellen benötigt man zunächst das Android SDK, welches zur Zeit in der aktuellen Version 3.2 zum Download unter http://developer.android.com/sdk/index.html bereit liegt.
Weiterhin wird das ADT-Plugin für Eclipse benötigt, dass die Erstellung eines Android Projektes extrem vereinfacht und das Debuggen ermöglicht. Zusätzlich kann die Anwendung zertifiziert und als apk-Datei exportiert werden, so dass diese auf einem Android Gerät installiert werden kann. Die aktuelle Version des ADT-Plugins ist 12.0.0 und kann unter folgender Update Site https://dl-ssl.google.com/android/eclipse/ installiert werden.
Anschließend stellt man nun in Eclipse unter Window, Preference, Android die SDK Location ein.

Im Anschluss kann das erste Android-Projekt erstellt werden. Hierzu reich ein Projekt- und Applikations-Name, ein Package und das gewünschte Android SDK. Bei letzterem Punkt sollte man beachten, dass für das eigene Android-Gerät meist noch nicht die neuste Firmware-Version zum Download bereit liegt. Für das Samsung Galaxy ist die Version 2.3.3 verfügbar, während man bereits das Android SDK 3.2 verwenden kann.
Sofern man sich eine Activity generieren lässt, kann nun das Projekt direkt im Emulator ausgeführt werden und man bekommt einen HelloWorld Text zu Gesicht.

Das Design der Anwendung, sofern man bei der HelloWorld Anwendung von Design reden kann, befindet sich unter /res/layout/main.xml. Es wird ein einfaches LinearLayout verwendet, welches vertikal ausgerichtet ist und die komplette Größe einnimmt. Das Layout wird einer TextView zugewiesen, die für die HelloWorld Ausgabe zuständig ist.

<?xml version=“1.0″ encoding=“utf-8″?>
<LinearLayout    xmlns:android=“http://schemas.android…“
android:orientation=“vertical“
android:layout_width=“fill_parent“
android:layout_height=“fill_parent“   >
<TextView
android:layout_width=“fill_parent“
android:layout_height=“wrap_content“
android:text=“@string/hello“
/>
</LinearLayout>

Der Text selbst ist externalisiert und befindet sich unter /res/values/strings.xml.

Schaut man sich den Erzeugten Code an, so befindet sich in der onCreate-Methode der erstellten Activity folgende Zeile:

setContentView(R.layout.main);

Die hier verwendete Klasse R wird vom ADT-Plugin angelegt und verwaltet – werden weitere grafische Komponenten im XML angelegt, werden diese hier gepflegt. Das Design kann zwar auch im Code verändert werden, aufgrund einer klaren Trennung sind die XML-Dateien aber vorzuziehen.

Will man die Anwendung nicht nur im Emulator testen, sondern auf seinem Android-Gerät, kann man diese bequem als apk-Datei exportieren, auf sein Handy einspielen und installieren.

Auch wenn es sich hierbei nur um eine HelloWorld Anwendung handelt, ist es doch erstaunlich, wie schnell man diese erstellt, auf sein Handy aufgespielt und getestet hat. Lediglich die Langsamkeit des Emulators treibt einen ab und an in die Verzweiflung. Aber der erste Start ist schnell gemacht und man kann sich um die erste richtige Anwendungen kümmern.

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/

Internationalisierung in Java

Veröffentlicht in: Java | 0

Anders als vielleicht vermutet, geht es in diesem Beitrag nicht um die obligatorischen länderspezifischen Property-Dateien, sondern um die Verwendung von Ländern, Landesvorwahlen, Währungen und  landestypischen Formattern in Java-Anwendungen.

Benötigt man innerhalb eines Java  Programmes eine vollständige Liste von Ländern, stößt man schnell auf die Klasse java.util.Locale. Die hier definierten Länder-Konstanten sind zwar recht begrenzt, es gibt hier aber die statische Methode:

Locale.getAvailableLocales()

mit der man sich – denkt man – eine vollständige Liste von allen Locales liefern lassen kann. Tatsächlich werden hier aber nur 152 Locales zurückgegeben. Verwendet man stattdessen folgenden Aufruf:

for (String country : Locale.getISOCountries()) {
Locale lc = new Locale(„“, country);
}

kommt man auf insgesamt 247 Locales. Interessant hierbei ist, dass man sich sowohl den kompletten Namen des Landes, als auch den ISO 3166-2 bzw. ISO 3166-3 Code über die Locale liefern lassen kann.

locale.getDisplayCountry() //Ländername
locale.getCountry() // ISO 3166-2 Code
locale.getISO3Country() // ISO 3166-3 Code

Außer der Klasse Locale ist auch noch die Google Library libphonenumber.jar interessant, die zur Zeit in der Version 3.8 vorliegt. Hier gibt es die PhoneNumerUtil, die über den ISO 3166-2 Ländercode die Landesvorwahl liefert:

int countryCode = PhoneNumberUtil.getInstance().getCountryCodeForRegion(locale.getCountry());

Diese Library kann über maven verwendet werden:

<dependency>
<groupId>com.googlecode.libphonenumber</groupId>
<artifactId>libphonenumber</artifactId>
<version>3.8</version>
</dependency>

Möchte man Zahlen landestypisch darstellen, kann die Klasse java.text.DecimalFormat verwenden werden, in dem man die entsprechende Locale übergibt. Als Beispiel wird hier die deutschsprachige Schweiz verwendet, da hier der Separator der 1000er Stelle abweichend zur deutschen Schreibweise ist:

DecimalFormat.getInstance(new Locale(„de“, „CH“).format(1234.123); //liefert: 1’234.123

Genauso einfach ist es, sich die passend formatierte Währung inklusive Währungssymbol an der korrekten Stelle ausgeben zu lassen:

NumberFormat.getCurrencyInstance(new Locale(„de“, „CH“).format(1234.123); // SFr. 1’234.12

In der deutschen Variante befindet sich das Euro-Symbol am Ende und die 1000er Stelle wird wie erwartet mit einem Punkt separiert:

NumberFormat.getCurrencyInstance(new Locale(„de“, „DE“).format(1234.123); // 1.234,12 €

Möchte man statt der lokalen die internationale Schreibweise verwenden, läßt man bei der Erstellung der Locale den Parameter für die Sprache weg. So ergibt sich für obige Beispiele folgende Ausgabe:

DecimalFormat.getInstance(new Locale(„“, „CH“).format(1234.123); //liefert: 1,234.123
NumberFormat.getCurrencyInstance(new Locale(„“, „CH“).format(1234.123); // CHF 1,234.12

Die in diesem Beitrag erwähnten Klassen bieten noch weitere Möglichkeiten für landesspezifische Darstellungen. Bevor man sich die Arbeit macht und hier eigene Komponenten entwickelt, lohnt sich ein Blick auf gegebenen Java Funktionalitäten.

Leider gibt es aber auch hier Grenzen. So treten grade für die Schweiz Probleme auf, da auf Schweizer Portalen eine Mischung aus Internationaler und Lokaler Darstellung gewählt wird. Aufgrund der Unterscheidung zwischen französischer, italienischer und deutscher Schweiz wird hier das internationale Währungssymbol CHF mit dem Hochkomma als Separator der 1000er Stellen kombiniert. Hierfür konnte ich leider keine fertige Java-Lösung finden.

Aufsetzten eines CQRS Projektes mit dem Axon-Framework

Veröffentlicht in: Java | 0

Das Axon-Framework ist eine Implementierung des CQRS – Command Query Responsiblity Segregation – Pattern, welches zur Erstellung von skalierbaren und erweiterbaren Software-Architekturen dient. Zum Einsatz kommen hier Commands, Events und Querys, die in verschiedenen Bereichen der Software-Architektur verwendet werden.

Will der Benutzer über die UI mit dem System interagieren, stehen zunächst nur Commands zur Verfügung, die mit Hilfe von einem CommandBus ausgeführt werden. Für die Darstellung von Informationen werden wiederum Querys verwendet, die unveränderbare DTOs – Data Transfer Objects – liefern. Für diesen Teilbereich sind im Axon-Framework keine Implementierungen verfügbar, diese müssen aufgrund verschiedenster Einsatzbereiche selbst erstellt werden.

Die Commands werden in den CommandHandlern behandelt, die sich in einem von der UI getrennten Bereich der Software-Architektur befinden.

Hier können nun entweder direkt Events über einen EventBus verbreitet werden, wobei im Gegensatz zu Commands mehrere EventHandler auf ein Event reagieren können. Die Alternative zur direkten Verwendung von Events ist die Benutzung von Aggregates. Diese können entweder neu erzeugt und anschließend in einem Repository gespeichert werden oder es wird ein bestehendes Aggregate aus einem Repository geladen. Erst nachdem alle Operationen auf einem Aggregate ausgeführt wurden, werden die dazugehörigen Events veröffentlicht und von den EventHandlern verarbeitet. Dies passiert automatisch, sofern das Aggregate aus einem Repository geladen wurde, bzw. sobald ein neu erzeugtes Aggregate gespeichert wurde.

Die EventHandler sind unter anderem für die Speicherung von Daten in einer Datenbank zuständig. Dem Benutzer werden über diesen Weg allerdings keine Daten angezeigt, sondern lediglich manipuliert. Zum Anzeigen von Datenbank-Inhalten werden die anfangs erwähnten Querys und DTOs verwendet.

Kommen wir nun zu einem Beispiel, bei dem zunächst ein Benutzer angelegt und in einem zweiten Schritt manipuliert werden. Es wird hierbei ein UserAggregate eingesetzt, d.h. die entsprechenden CommandHandler Arbeiten nicht direkt mit Events, sondern verwenden stattdessen das Domain Model.

Zunächst einmal wird folgende Dependency benötigt:

<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-core</artifactId>
<version>1.0</version>
</dependency>

Für die Integration des Axon-Frameworks in die Anwendung wird in diesem Beispiel Spring verwendet, wobei außer den Spring Bibliotheken keine weiteren Abhängigkeiten benötigt werden.

Hierfür wird der AnnotationCommandHandlerBeanPostProcessor zur Erkennung von Java-Beans mit der CommandHandler-Annotation, der CommandBus und zwei CommandHandler im Spring Kontext registriert. Letztere dienen zum Anlegen bzw. Aktualisieren des Benutzers.

<bean class=“org…AnnotationCommandHandlerBeanPostProcessor“ />

<bean id=“commandBus“ class=“org…SimpleCommandBus“/>
<bean id=“createHandler“ class=“..CreateUserHandler“ />
<bean id=“updateHandler“ class=“..UpdateUserHandler“ />

Der CreateUserHandler erzeugt zunächst ein neues UserAggregate, führt auf diesem die save-Operation aus und speichert es im UserRepository. Events die beim Erzeugen und innerhalb der save-Operation generiert werden, werden erst publiziert wenn das UserAggregate dem Repository mittels add hinzugefügt wird. Es folgt die Implementierung des CreateUserHandlers, der auf das CreateUserCommand reagiert:

@Component
public class CreateUserHandler {

@Autowired
private UserRepository userRepository;

@CommandHandler
public void handle(CreateUserCommand command) {
UserAggregate userAggregate = new UserAggregate(command.getUser());
userAggregate.save(command.getUser());
userRepository.add(userAggregate);
}
}

Das CreateUserCommand wird auf dem CommandBus ausgeführt, welcher mit Hilfe der Inject-Annotation in die gewünschte Klasse injiziert wird. Das Axon-Framework sorgt dafür, dass der gewünschte CommandHandler mit dem Command  als Übergabe-Parameter aufgerufen wird. Zum Ausführen des Commands wird folgende Zeile benötigt:

commandBus.dispatch(new CreateUserCommand(new User()));

Nun wird das UserAggregate erzeugt, dass von der Klasse AbstractEventSourcedAggregateRoot erbt. Wird ein UserAggregate erzeugt, wird gleichzeitig ein AggregateIdentifier angelegt, anhand dessen das Aggregate beim Speichern im UserRepository identifiziert wird. Jede Änderung des Aggregates die im Repository gespeichert wird, erhält eine neue Version, die von der eigenen Repository Implementierung gespeichert werden kann. Neben der Erzeugung des Identifiers wird im Konstruktor ein Event angelegt, dass in der zu implementierenden handle-Methode behandelt wird. Die Events, die in diesem Beispiel verwendet werden, erben alle vom DomainEvent, welches hier als Übergabe-Parameter dient.

Im CommandHandler wurde weiterhin die save-Methode aufgerufen, auch diese wird hier implementiert, wobei ein weiteres Event registriert wird. Hier nun der Beispiel-Code:

public class UserAggregate extends AbstractEventSourcedAggregateRoot {

public UserAggregate(User user) {
super(new UserAggregateIdentifier(user.getDsn()));
apply(new UserCreatedEvent(user));
}

@Override
protected void handle(DomainEvent event) {
// do what you have to do with the created user
}

public void save(User user) {
registerEvent(new UserSaveEvent(user));
}
}

Wie anfangs beschrieben, werden die Events erst ausgeführt, sobald das Aggregate im Repository gespeichert wird.

Folgendermaßen kann nun das UserRepositorys aussehen:

public class UserRepository extends AbstractRepository{

@Override
protected UserAggregate doLoad(AggregateIdentifier aggregateIdentifier, Long version) {
// load aggregate from a map for example
}

@Override
protected void doSave(UserAggregate aggregate) {

// save aggregate in a map for example
}
}

Im CommandHandler wird beim Aufruf der add-Methode des Repositorys die abstrakte doSave-Methode ausgeführt und das Aggregate gespeichert. Anschließend werden die registrierten Events ausgeführt. Hierbei wird das UserCreateEvent im Aggregate selber behandelt, dass UserSaveEvent aber im folgenden SaveEventListener, welcher lediglich zum Speichern des im Event befindlichen Users in der Datenbank zuständig ist:

@Component
public class SaveEventListener {

@Autowired
private HibernateTemplate hibernateTemplate;

@EventHandler
public void handle(UserSaveEvent event) {
hibernateTemplate.saveOrUpdate(event.getUser());
}
}

Für die Behandlung von Events sind folgende Spring-Konfigurationen vorzunehmen:

<bean class=“class=“org..AnnotationEventListenerBeanPostProcessor“ />
<bean id=“eventBus“ class=“org..SimpleEventBus“ />
<bean id=“updateListener“ class=“..SaveEventListener“ />

Interessant dürfte noch die Umsetzung eines UpdateUserHandler sein, da hierfür ein bestehendes Aggregate aus dem UserRepository geladen wird:

@Component
public class UpdateUserHandler {

  @Autowired
  private UserRepository userRepository;

  @CommandHandler
  public void handle(UpdateUserCommand command) {
    UserAggregate userAggregate = userRepository.load(new UserAggregateIdentifier(command.getIdentifier()), command.getVersion());
    userAggregate.save(command.getUser());
  }
}

Nachdem die save-Operation mit aktualisierten Benutzer-Daten aufgerufen wurde, muss das Aggregate nicht erneut im Repository gespeichert werden. Das Axon-Framework erkennt automatisch, dass es sich hierbei um eine neue Version des geladenen UserAggregates handelt und führt nach vollständigem Durchlauf des CommandHandlers alle registrierten Events aus.

In diesem Fall wird erneut das UserSaveEvent aufgerufen, der entsprechende Listener ausgeführt und damit die Änderung des Benutzers in der Datenbank gespeichert.

Dieses Beispiel soll einen Einblick in die Funktionsweise von CQRS und das Axon-Framework liefern, wobei einige Teilbereiche, wie z.B. der EventStore, ungenannt blieben. Ein Blick in den Reference-Guide sei allemal empfohlen.

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.

CDI Events – Das Observer Pattern in Java EE 6

Veröffentlicht in: Java, JEE 6 | 2

CDI Events können als ein neues Architekturmuster für Java EE 6 Anwendungen gesehen werden, dass am meisten dem Observer Pattern ähnelt. Auch hier gibt es ein zu überwachendes Objekt, auf welches verschiedenste Komponenten reagieren, deren Implementierung aber unbekannt bleiben soll.

Um dies zu ermöglichen benötigt das zu überwachende Objekt Möglichkeiten zum Registrieren und Entfernen von sogenannten Observern, welche bei bestimmten Änderungen des Objektes benachrichtigt werden.

Bei CDI Events reichen einfache Annotations aus, um die Observer im CDI Kontext zu registrieren. Eine Registrierung beim überwachten Objekt selbst, ist nicht mehr nötig.

Dieses Objekt, bzw. Event ist ein ganz normales POJO mit beliebigen Attributen und entsprechenden getter– und setter Methoden.

public class UserEvent {

private String username;

public UserEvent() {}

public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}

Um das Event zu feuern, auf welches anschließend von den Observern reagiert werden soll, ist folgendes Code Fragment nötig:

 @Inject
private Event<UserEvent> event;

public void doSomething() {
event.fire(new UserEvent(„Mustermann“));
}

Das Registrieren von Observern im CDI Kontext erfolgt mittels der Annotation @Observes und dem Event als Übergabe-Parameter. Der Observer kann nun seine Aufgabe verrichten und dabei auf das Event zugreifen. Die Implementierung eines Interfaces ist nicht mehr nötig:

public class UserHandler {
public void handleUser(@Observes UserEvent event) {
// do what you have to do …
}
}

Soll die Abarbeitung innerhalb eines Observers asynchron erfolgen, d.h. nach dem Aufruf der fire-Methode des Events nicht auf den Observer gewartet werden, kann dies mit der Annotation @Asynchronous innerhalb des Observers definiert werden:

@Stateless
public class UserHandler {

@Asynchronous
public void handleUser(@Observes UserEvent event) {
// do what you have to do … but asynchronously
}
}

Mit Hilfe von CDI Events kann man die Software-Architektur recht einfach entkoppeln und hat eine Möglichkeit geschaffen, leicht Funktions-Erweiterungen implementieren zu können.

Bereits vor CDI gab es Frameworks, die Events unterstützt haben. Hier sei das Axon Framework (CQRS – Command Query Responsibility Segregation) genannt, wobei hier das Event-, bzw. Command-Handling nur eine Komponente von vielen war.

Ganz neu ist die Event Idee auf jeden Fall nicht, nun hat sie aber ihren Weg in den Java EE Standard gefunden.

CDI im Tomcat verwenden

Veröffentlicht in: Java, JEE 6 | 0

Die einfachste Art die Java EE 6 Funktionalität CDI einsetzten zu können, ist die Verwendung eines vollwertigen Application Servers wie z.B. Glassfish in der aktuellen Version 3.1. Um CDI in einem Tomcat 7 verwenden zu können, ist etwas mehr Aufwand vonnöten, da dieser außer der Servlet API 3.0 keine Java EE 6 Komponenten von Haus aus mitliefert.

Um in einer Web-Applikation die innerhalb eines Tomcats läuft CDI bzw. Wend verwenden zu können, reicht ein einziges JAR-Archiv aus: weld-servlet.jar

Dieses kann bequem per Maven in einer Web-Applikation integriert werden:

<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>1.0.1-Final</version>
</dependency>

Zusätzlich wird noch folgender Eintrag in der web.xml des jeweiligen Web-Projektes benötigt:

<listener>
<listener-class>
org.jboss.weld.environment.servlet.Listener
</listener-class>
</listener>

Leider verwendet der Tomcat 6 die Servlet API 2.5, so dass hier nicht so einfach die Vorteile der Servlet API 3.0 zum Einsatz kommen können. CDI selber kann natürlich dennoch verwendet werden, hier kommt es nicht zu Konflikten mit den Libraries des Tomcats.

Quickstart in Java EE 6 und CDI

Veröffentlicht in: Java, JEE 6 | 0

Auf der JAX 2011 konnte ich mir ein paar interessante Vorträge über Java EE 6 im Allgemeinen und CDI im Speziellen anhören. Leider bin ich erst jetzt – einen guten Monat später – dazu gekommen, entsprechende Beispiele zu vertiefen.

Für einen möglichst schnellen Start empfiehlt es sich den Application Server GlassFish in der aktuellen Version 3.1 zu downloaden, bei diesem handelt es sich um die Referenz-Implementierung zu Java EE 6. Dementsprechend liefert GlassFish 3.1 bereits alle Java EE 6 Funktionalitäten inklusive der Servlet API 3.0 und CDI von Haus aus.

Aus Eclipse heraus lässt sich einfach ein Dynamic Web Project erstellen. Eclipse WTP in der aktuellen Version 3.2.3 unterstützt bereits GlassFish 3.1.

Dank der Servlet API 3.0 muss nicht länger die web.xml konfiguriert werden, eine einfache Annotation in der entsprechenden Klasse reicht aus, um das Servlet im Web Container zu registrieren.

@WebServlet(„/MyUserServlet“)
public class MyUserServlet extends HttpServlet {

}

Hier kann nun wie bereits in den Vorgängerversionen gehabt, die doGet Methode überschrieben werden. Anschließend ist das Servlet bereits über den Browser aufrufbar. Für weitere Request-Arten gibt es natürlich ebenfalls Methoden, die überschrieben werden können.

Kommen wir nun zur eigentlichen CDI Funktionalität, welche auch unter dem Namen Weld bekannt ist. Um CDI im Web Container zu aktivieren, ist es notwendig eine Datei beans.xml im WEB-INF Verzeichnis der Web Applikation zu erstellen. Eine leere Datei ist hierfür ausreichend.

Ein Beispiel von CDI ist die fachliche Dependency Injection. Hierbei wird nicht wie in der bisherigen Dependency Injection ein Service injiziert, sondern ein fachlicher Context. In einer herkömmlichen Web Applikation ist es nötig den UserService injiziert zu bekommen, ausschliesslich um an den eingeloggten Benutzer zu kommen. Statt dessen kann man sich nun einfach den Benutzer in die Applikation injizieren lassen und spart sich so den unnötigen Serveraufruf und eine Abhängigkeit auf den UserService.

Hierfür wird lediglich die Annotation @Produces über der Methode getCurrentUser benötigt, anschließend kann CDI eine @Inject Annotation auflösen, mit deren Hilfe der Benutzer an die entsprechende Stelle injiziert werden kann.

Der UserService hierfür sieht so aus:

@Produces
public User getCurrentUser() {
User user = new User(„max mustermann“);
return user;
}

Um den Benutzer in das Servlet injizieren zu lassen, reicht folgendes Code-Fragment:

@Inject User user;

Dieses Verfahren funktioniert allerdings nur, solange nicht weitere Methoden mit @Produces annotiert sind, die einen User zurück geben. Ist dies der Fall müssen diese unterschieden werden. Hierfür werden Qualifier benötigt, die mittels eigener Annotation definiert werden:

@Qualifier
@Retention(RUNTIME)
@Target( { TYPE, METHOD, PARAMETER, FIELD })
public @interface CurrentUser {
@Nonbinding String name();
}

Um das Beispiel interessanter zu machen, wird direkt in der Annotation der Name des Benutzers mit übergeben, so dass an der erzeugenden Stelle, der Name des Benutzers über die Annotation abgefragt werden kann:

@Produces
@CurrentUser(name=““)
public User getCurrentUser(InjectionPoint injectionPoint) {
String username = null;
for (Annotation qualifier : injectionPoint.getQualifiers()) {
if (qualifier instanceof CurrentUser) {
CurrentUser currentUser = (CurrentUser) qualifier;
username = currentUser.name();
}
}
User user = new User(username);
return user;
}

Die Annotation @CurrentUser zeigt an, dass diese Methode lediglich für den CurrentUser zuständig ist. Der Name der hier leer gelassen wurde, spielt keine Rolle, muss aber angegeben werden, da dies in der Annotation so gefordert ist. Der Parameter InjectionPoint wird direkt von CDI in die Methode injiziert. Über diesen Parameter kommt man an die Annotation, die im Injizierungspunkt gesetzt wurde. So kann man den Namen des Benutzers erfragen, der in der Annotation festgelegt wurde und diesen für den zu erstellenden Benutzer verwenden.

Die Stelle an der man den Benutzer injiziert bekommen möchte, sieht so aus:

@Inject @CurrentUser(name=“max mustermann“) User user;

Hier wird der Name gesetzt, der in der @Produces Methode dem Benutzer übergeben wird.

Dies war lediglich ein kleiner Teil der CDI Funktionalität. Ebenfalls sehr interessant ist das Event Konzept, die Möglichkeit einzelne Teile einer Anwendung per Annotation asynchron ausführen zu können, Aspekte unter CDI und vieles mehr.

Doch dazu zu einem späteren Zeitpunkt mehr.