Modulare Enterprise-OSGi-Anwendungen: Let’s transact!

Was bündeln wir als Transaktion?

Bevor wir Alternativen anschauen, begeben wir uns kurz in die Vogelperspektive und überlegen uns, was in einer Transaktion zusammengefasst werden soll. Prinzipiell können Transaktionen bei Zugriffen auf Dateien, Datenbanken oder auch dem Versand von JMS-Nachrichten verwendet werden. Je mehr aber in eine einzelne Transaktion reingepackt wird, umso teurer wird es. Das gilt insbesondere dann, wenn eine Transaktion Zugriffe auf verschiedene Arten von Ressourcen (wie Datenbanken oder Dateien) kapselt. Wie uns die NoSQL-Datenbanken zeigen (die keine Transaktionen kennen), können viele Probleme auch ohne Transaktionen gelöst werden. Beherzigen Sie das und versuchen Sie, möglichst ohne oder mit einfachen Transaktionen auszukommen.

Was bündeln unsere Do-it-yourself-Transaktionen? Sie nutzen den EntityManager. Somit können auch nur Operationen auf dem JPA EntityManager in einer Transaktion gebündelt werden. Das sind Operationen auf JPA-Entitäten und SQL Statements, sofern sie über JPA ausgeführt werden. Das reicht uns aber nicht immer. Eventuell wollen wir Operationen auf verschiedenen Datenbanken in einer Transaktion bündeln oder den Versand einer JMS-Nachricht koppeln. Das können unsere Do-it-yourself-Transaktionen nicht. Dafür brauchen wir schwerere Geschütze. Diese bietet uns der OSGi-Enterprise-Standard, den wir nun kennen lernen.

Transaktionen im OSGi-Enterprise-Standard

Was sagt der OSGi-Enterprise-Standard [5] über Transaktionen? Sie basieren auf dem Java Transaction API (JTA) [6]. Die Spezifikation besteht aus den drei Interfaces UserTransaction, TransactionManager und TransactionSynchronizationRegistry, die aus der JTA-Spezifikation übernommen wurden. Um Transaktionen programmatisch zu steuern, wird das Interface UserTransaction verwendet. Setzen wir zunächst voraus, dass wir eine Implementierung der UserTransaction haben, die als OSGi Service veröffentlicht ist. Dann können wir mit dem Code aus Listing 2 eine Transaktion verwalten.

Listing 2
UserTransaction transaction = getUserTransaction();
transaction.begin();
try {
  // Perform transactional work
} catch (RuntimeException ex) {
  if (transaction != null) transaction.rollback();
  throw ex;
}

Auch diese Variante beinhaltet einiges an Boilerplate-Code. Außerdem haben wir noch nicht geklärt, wie wir an eine Implementierung der UserTransaction kommen.

Den Boilerplate-Code gehen wir später an. Schauen wir zunächst, ob Eclipse Gemini eine Implementierung der OSGi-Spezifikation bietet. Das Projekt implementiert die OSGi-Enterprise-Spezifikationen für JPA, JDBC und noch einige mehr. Für Transaktionen gibt es jedoch leider keine Implementierung. Hier sind wir also auf uns alleine gestellt. Verschaffen wir uns nun einen Überblick darüber, welche Implementierungen des OSGi-Enterprise-Standards für Transaktionen es gibt.

Implementierungen

Apache Aries [7] implementiert den OSGi-Enterprise-Standard und insbesondere auch die Transaktionen. Leider lässt sich diese Implementierung nicht in unserer Enterprise-Anwendung verwenden. Grund dafür sind Abhängigkeiten zu anderen Teilprojekten von Apache Aries, die nicht mit Eclipse Gemini kompatibel sind, wie beispielsweise Apache Aries Blueprint. Schauen wir also weiter.

Eine weitere Implementierung von JTA für OSGi ist Atomikos TransactionsEssentials [8]. Die Konfiguration von Atomikos für Blueprint erfolgt analog zu einer normalen Spring-Konfiguration. Hierbei ist zu beachten, dass Atomikos eine spezielle JDBC DataSource benötigt. Sie wird mit der Blueprint-Konfiguration aus Listing 3 erzeugt. Außerdem benötigen wir die UserTransaction, die wir mit der Blueprint-Konfiguration aus Listing 4 erzeugen und als OSGi Service veröffentlichen.

Listing 3
NONXADBMSjdbc:derby:db;create=trueorg.apache.derby.jdbc.EmbeddedDriver160
Listing 4
true

Nun haben wir alles zusammen. Aber diese Konfiguration passt nicht recht zu unserer Enterprise-Anwendung. Damit wir Atomikos nutzen können, müssen wir die JDBC DataSource selbst erzeugen und können das nicht mehr über Gemini DBAccess tun. Wie Listing 3 zeigt, handeln wir uns damit wieder Abhängigkeiten zu konkreten JDBC-Treibern ein. Um genau das zu vermeiden, haben wir doch aber Gemini DBAccess erst eingeführt!

Kommentare

Schreibe einen Kommentar

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