JAXenter.de

Das Portal für Java, Architektur, Cloud & Agile

Persistenz-Framework Warp auf der Basis von Google Guice

X

Vorfreude auf Java 9: Die ersten Features sind bekannt.

Warp 1.0 - beschleunigen!

Persistenz-Framework Warp auf der Basis von Google Guice

Uwe Schäfer

Google Guice beschränkt sich im Gegensatz zum Konkurrenten Spring, der eine Vielzahl so genannter Vorlagen für jeden möglichen Anwendungszweck bereit hält, im Wesentlichen auf zwei Funktionalitäten: Dependency Injection und Interception. Dies lässt Raum für kleine Frameworks, die - genau wie Guice selbst - exakt einer Aufgabe dienen. Als Vertreter dieser Gattung soll hier das Persistenzframework Warp-persist vorgestellt werden.

"Write programs that do one thing and do it well". Diese oft zitierte Losung aus UNIX-Zeiten scheint in Zeiten leichtgewichtiger Softwareentwicklung wichtiger denn je. Google Guice qualifiziert sich hier in besonderer Weise als ein Framework, das sich auf die Dependency Injection und - im Zuge dessen - die Erzeugung von Proxy-Objekten beschränkt. Hierbei unterscheidet sich Guice von Spring unter anderem dadurch, dass es dem Entwickler freistellt, wie der Aspekt der Persistenz in die Anwendung einzubetten ist. Um genau dieses (und nur dieses) Problem kümmert sich Warp-persist. Warp-persist liegt seit einigen Wochen in der Version 1.0 vor und arbeitet mit JPA, Hibernate und db4o zusammen. Auf Basis von Guice verwaltet Warp die jeweiligen Persistenzkontexte, bietet die Möglichkeit zur Transaktionsabgrenzung und vereinfacht die Implementierung von Abfragen durch so genannte "Dynamic Finders".

Beispiel JPA

Vergegenwärtigen wir uns zunächst an einem simplen Beispiel, welche Schritte nötig sind, um eine Entität (hier eine Instanz der Klasse Brand) mittels JPA zu speichern (Listing 1).

Listing 1 « Speichern einer Entität via JPA »
public void persistBrand(Brand brand) {
  EntityManagerFactory emf = Persistence.createEntityManagerFactory("example");
  try {
    EntityManager entityManager = emf.createEntityManager();
    try {
      EntityTransaction transaction = entityManager.getTransaction();
      transaction.begin();
      try {
        entityManager.persist(brand);
        transaction.commit();
      } catch (Throwable e) {
        transaction.rollback();
        throw new RuntimeException(e);
      }
      finally {
        entityManager.close();
      }
    } finally {
      emf.close();
    }
}

Hier wird also zunächst eine EntityManagerFactory und daraus ein EntityManager erzeugt. Zusätzlich wird noch eine Transaktion benötigt, um das Schreiben in die Datenbank zu ermöglichen. All diese Ressourcen auch im Fehlerfall korrekt wieder zu schließen, ist ein aufwändiges und - vor allem für weniger erfahrene Entwickler - fehlerträchtiges Unterfangen. Vor allem aber erzeugt diese Art von Umgang mit der JPA schwer lesbaren und somit auch schwer zu wartenden Quellcode.

Definition des Persistenz-Dienstes

Da Warp-persist auf Guice aufsetzt, wird die Konfiguration in der bei Guice üblichen Weise, nämlich durch die Bindung von Klassen und durch die Installation von Modulen, vorgenommen. Sollten Sie mit dieser Art der Anwendungskonfiguration nicht vertraut sein, möchte ich hiermit auf das Handbuch zu Guice, beziehungsweise auf den einführenden Artikel zu Guice aus dem JavaMagazin 07/2007 verweisen.

Die wesentliche Schnittstelle zur Verwendung von JPA ist der EntityManager, der den Kontext der persistenten Objekte bereitstellt. Implementierungen eines solchen Persistenzkontexts zu erzeugen und zu verwalten ist eine der Aufgaben, für die Warp-persist den PersistenceService bereithält (Listing 2).

"Persistenzkontext Lebenszyklus"

Zurzeit kennt Warp zwei verschiedene Lebenszyklen für diese Persistenzkontexte: den von EJB-Containern bekannten transaktionsgebundenen (transaction-scoped) und die bei Webapplikationen beliebten requestgebundenen (request-scoped) Persistenzkontext.

Transaktionsgebundener Persistenzkontext

Hier wird ein Kontext pro Transaktion verwendet. Dies stellt sicher, dass verschiedene Transaktionen sich nicht gegenseitig beeinflussen.

Requestgebundener Persistenzkontext

Bei Webapplikationen sind häufig viele Zugriffe auf die Persistenzschicht der Anwendung innerhalb der Abarbeitung einer Http-Anfrage notwendig. Um an Performanz zu gewinnen und vom Level-1 Caching des Persistenzkontexts zu profitieren, ist hier ein Lebenszyklus beliebt, der erst mit der Abarbeitung der Http-Anfrage abgeschlossen ist [www.hibernate.org/42.html und www.hibernate.org/43.html].

Um den requestgebundenen Persistenzkontext zu verwenden, ist ähnlich wie bei Spring, die Deklaration eines zusätzlichen Filters in der web.xml notwendig [siehe auch hier].

Andere Lebenszyklen, zum Beispiel der einer Konversation, sind durchaus möglich und in Warp bereits vorgesehen, aber noch nicht implementiert.

Listing 2 « Definition eines PersistenceService »
Module module = new AbstractModule() {
  protected void configure() {
    bindConstant().annotatedWith(JpaUnit.class).to("example");
    install(PersistenceService.usingJpa().across(UnitOfWork.TRANSACTION)
.buildModule());
    bind(PersistenceServiceInitializer.class).asEagerSingleton();
  }
  static class PersistenceServiceInitializer {
    @Inject 
    public PersistenceServiceInitializer(final PersistenceService service) {
      service.start();
    }
  }
}

Zunächst wird Guice der Name der zu verwendenden PersistenceUnit (wie in der persistence.xml definiert) mitgeteilt. Daraufhin wird ein Modul installiert, das einen PersistenceService unter Verwendung von JPA definiert. Der Aufruf .across(UnitOfWork) legt hierbei den Lebenszyklus des Persistenzkontexts fest (siehe Kasten). Da ein PersistenceService gestartet werden muss, wird in diesem Beispiel zusätzlich die Klasse PersistenceServiceInitializer so gebunden, dass Sie beim Start von Guice automatisch instanziiert wird und somit den PersistenceService startet. Ein späterer, expliziter Start des PersistenceService wäre z. B. bei Desktop-Applikationen sinnvoll, die nicht sofort mit der Datenbank verbunden sind.

Nach Installation dieses Moduls stehen dem Anwendungsentwickler die wesentlichen Funktionen von Warp-persist bereits zur Verfügung.

 

Kommentare

Ihr Kommentar zum Thema

Als Gast kommentieren:

Gastkommentare werden nach redaktioneller Prüfung freigegeben (bitte Policy beachten).