Teil 4: Enterprise-Anwendung von der Datenbank bis zur Weboberfläche

Enterprise OSGi: The Big Picture

Jan Stamer

Auf geht’s in die letzte Runde unserer modularen Enterprise-Anwendung. Unser Ziel ist eine Anwendung, die nicht nur für die Marketingbroschüren modular ist, sondern auch in der Realität. Angefangen haben wir mit der Persistenzschicht (siehe Artikel 1 dieser Reihe). Darauf setzen wir Services und Bundles und verknüpfen sie per Dependency Injection (Artikel 2 dieser Reihe). Kombiniert mit den Transaktionen aus Artikel 3 dieser Reihe nimmt unsere Enterprise-Anwendung nun langsam Form an. Jetzt machen wir uns ans große Ganze, nämlich eine Enterprise-Anwendung von der Datenbank bis zur Weboberfläche – mit Modulen.

OSGi goes Enterprise

Der Artikel „Enterprise OSGi: The Big Picture“ ist Teil der Serie „OSGi goes Enterprise“, erstmals erschienen im Eclipse Magazin.

Wie weit sind wir bis jetzt gekommen? Schauen wir dazu auf unser Beispielprojekt [1], eine einfache Anwendung zur Verwaltung von Kunden- und Kontendaten, die in einer relationalen Datenbank abgelegt sind. Die unterste Schicht bilden die JPA-Entitäten. Die binden wir mit DBAccess und Gemini JPA aus dem Eclipse-Gemini-Projekt [2] modular ein, wie im ersten Artikel dieser Serie beschrieben. In unserer Enterprise-Anwendung wollen wir jedoch nicht gegen die JPA-Entitäten programmieren, sondern nur gegen die Interfaces Customer und Account. JPA ist eine konkrete Implementierung dessen. Wir halten uns aber offen, eine andere Implementierung, beispielsweise für NoSQL, zu wählen. Wir wollen also die Domain-Objekte Kunde und Konto vom konkreten Datenzugriff trennen. Das Repository-Pattern aus Martin Fowlers Patterns of Enterprise Architecture [3] tut genau das. Implementierungen dafür lernen wir nun kennen.

Die Repository-Schicht

Wir setzen die Repository-Schicht auf die JPA-Entitäten auf. Dazu führen wir analog zu den Domain-Objekten ein API Bundle mit den Interfaces CustomerRepository und AccountRepository ein. Diese Repository Interfaces zeigen nach außen nur die Interfaces Customer und Account. So sehen die Schicht mit der Businesslogik und die Schicht mit dem User Interface nur diese Interfaces. Welche konkrete Implementierung dahinter steckt, darum müssen sie sich nicht kümmern. Die Repository Interfaces für Customer und Account bieten einfache CRUD-Funktionalitäten.

Die Implementierung ist also straightforward. Wir erstellen eine Klasse CustomerRepositorsImpl mit der konkreten Implementierung des CustomerRepository-Interfaces. Die Methode save zum Speichern eines Kunden sieht dann wie in Listing 1 aus.

Listing 1
private EntityManager entityManager;

@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
   this.entityManager = entityManager;
}
   
@Transactional
public Customer save(Customer customer) {
   CustomerImpl customerImpl = (CustomerImpl) customer;
   entityManager.persist(customerImpl);
   return customerImpl;
}

Wir verwenden den EntityManager, den wir mit Gemini JPA erzeugt und als OSGi Service veröffentlicht haben. Des Weiteren nutzen wir deklarative Transaktionen à la Spring, wie wir sie im letzten Artikel kennen gelernt haben. Die Implementierung der save-Methode beschränkt sich also aufs Wesentliche, nämlich ein persist auf dem EntityManager. So etwas brauchen wir auch für die Implementierung des AccountRepository-Interfaces. Das ist dann fast derselbe Code, nur dass wir Customer durch Account ersetzen. Damit wir das bei der nächsten Entity kein drittes Mal per Copy-and-Paste vervielfältigen, sollten wir es als abstrakte Basisklasse aller Repositories herausziehen. Aber auch dieser Code gehört zur Kategorie Boilerplate-Code, also ist Skepsis angesagt! Können wir das vermeiden? Ohne Probleme, wie wir gleich sehen werden.

Geschrieben von
Jan Stamer
Kommentare

Schreibe einen Kommentar

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