Eine Laufzeitumgebung für Modelle
Das CDO Model Repository Framework [3], eine optionale Komponente von EMF, wurde entwickelt, um Modeling auch im Enterprise-Umfeld und im großen Maßstab einsetzbar zu machen (Abb. 2). Der in Bezug auf das Business-Modell voll-transparent erbrachte Mehrwert von CDO lässt sich in die folgenden Kategorien einteilen:
- Skalierbarkeit: Jedes einzelne Business Object wird grundsätzlich erst bei Bedarf geladen und zuverlässig dem Garbage Collector zugeführt, sobald die Anwendung es nicht mehr referenziert. Gigabyte-große Modelle sind so leicht möglich, ohne dass bereits das Businessdesign darauf Rücksicht nehmen muss.
- Verteilung: Die lokalen Objekte sind über eine permanente Verbindung zum Model Repository ständig auf dem aktuellen Stand. Es entsteht die Illusion, dass alle Clients auf einem identischen, großen Objektgrafen, einem Distributed Shared Model, operieren. Von diesem (optionalen) Mechanismus stammt übrigens auch der volle Name von CDO: Connected Data Objects.
- Transaktionalität: Modifikationen des Objektgrafen sind auf unterster technischer Ebene (also nicht nur durch Kooperation der Anwendung wie bei EMF Transactions) transaktionssicher und zwar mit Objektgranularität und standardmäßig optimistischem Locking. Explizite Read oder Write Locks, sowie Save Points und Repository-übergreifende, verteilte Transaktionen gehören auch zum Repertoire von CDO.
- Persistenz: Die eigentliche Persistenzebene tief im CDO Repository Server ermöglicht die Integration so unterschiedlicher Datenquellen wie relationaler Datenbanken (zum Beispiel via Hibernate), objektorientierter Datenbanken oder Dateisystemen; sogar Web Services wären denkbar.
- Versionierung: Falls die Implementierung des gewählten Backend Adapters dies unterstützt und das Repository entsprechend konfiguriert ist, sind alle historischen Zustände des Objektgrafen konsistent wiederherstell- und navigierbar. So genannte Audit Views ermöglichen Time Traveling ohne Eingriff in die Businessmodelle oder nennenswerten Mehraufwand in der Anwendung.
All diese Eigenschaften und Funktionen sind entweder transparent oder verbergen sich hinter Programmierschnittstellen, die im Laufe mehrerer Jahre gereift sind. Im Folgenden soll gezeigt werden, wie sich CDO in EMF einfügt, um diese Anforderungen zu erfüllen. Dabei beginnen wir auf der Client-Seite und steigen dann über die Client/Serverkommunikation bis in das Model Repository und die Anbindung externer Datenquellen herab.
Die Anatomie eines CDO-Objekts
Wie inzwischen bekannt, sind die ganz gewöhnlichen Java-Referenzen, die vom EMF-Generator als Instanzfelder in die Subklassen von EObjectImpl generiert werden, letztlich schuld an der Speicherverschwendung. Das einzige Gegenmittel ist ebenso drastisch wie konsequent: Die generierten Klassen dürfen gar keine Fields mehr enthalten. Mittels eines Schalters in der Generatorkonfiguration lässt sich die gesamte Generierung auf so genannte „reflektive Delegation“ umstellen. Danach greifen die generierten Getter und Setter der modellierten Attribute und Referenzen nicht mehr auf Instanzfelder der Klasse zu, sondern delegieren den Zugriff an die Methoden eDynamicGet und eDynamicSet der Superklasse EBasicObjectImpl.
Genau hier setzt die CDO-Integration mit EMF an. Durch eine weitere Generatoroption wird die Basisklasse für alle Modellobjekte von EObjectImpl in dessen Subklasse CDOObjectImpl geändert. Dadurch übernimmt ein CDO-Objekt die volle Kontrolle über den eigenen Objektzustand und besitzt keine modellbezogenen Fields mehr. Stattdessen speichert jedes CDO-Objekt einen technischen Identifier, die CDOID, sowie einen Verweis auf eine interne Datenstruktur, die CDO Revision, die letztendlich die eigentlichen Modelldaten aufnehmen kann. Eine solche CDO Revision enthält keine Strong References auf andere Objekte oder Revisions, sondern nur noch deren CDOIDs. Sie kann leicht über das Netzwerk transportiert, in Datenbanken gespeichert und fast immer aus dem Hauptspeicher entfernt werden.
Die nötige Infrastruktur
Damit nicht bei jedem Zugriff auf eine Objektreferenz die dazugehörende Revision vom Server aus der Datenquelle geladen werden muss, sieht das CDO-Framework Caches auf verschiedenen Ebenen vor. Auf der Clientseite hat jede CDO-Session ihren eigenen Revision Cache, der gemäß Voreinstellung aus einem fixed-size LRU Cache und einem nachgeschalteten memory-sensitive Cache besteht. Die eigentlichen CDO-Objekte, die ja nur leere Wrapper mit einer ID sind, werden von so genannten Views beliebig erzeugt, mit der jeweils richtigen Revision verknüpft und in einem eigenen memory-sensitive Cache abgelegt.
Welches die richtige Revision ist, hängt dabei nicht nur von der CDOID ab, sondern maßgeblich auch davon, welche Version die View auswählt. CDO unterstützt grundsätzlich drei verschiedene Auswahlstrategien für Revisions, und demzufolge gibt es die drei Sichttypen (Abb. 4):
- View: eine read-only-Sicht auf den jeweils aktuellsten Zustand des Repositories
- Audit: eine read-only-Sicht auf historische Zustände, mit änderbarer Zielzeit
- Transaction: eine read-write-Sicht auf den aktuellen Zustand
Die Daten in einer Revision werden nur während und in einer Transaktion verändert. Wenn die Transaktion am Ende der Bearbeitungssequenz committet wird, wird der Zustand der neuen und geänderten Revisions praktisch eingefroren und mit einer für das Objekt eindeutigen Versionsnummer sowie einer Art Transaktionskennung versehen. Beim erneuten Änderungsversuch innerhalb einer Transaktion wird zunächst eine transaktionale Kopie der Ausgangsrevision erzeugt und intern im CDO-Objekt verlinkt.
Das elegante und reibungslose Zusammenspiel der beteiligten Komponenten wird intern von der CDO State Machine gesteuert. Abbildung 5 zeigt sie in leicht vereinfachter Darstellung. Interessant dabei ist das Remote Invalidate Event, das asynchron vom Repository Server übertragen wird, wenn die CDO-Session auf dem Client dies nicht explizit untersagt. Wenn also eine andere Transaktion durch Änderung eine neue Revision eines Objekts erzeugt, dann werden alle Clients darüber benachrichtigt, und die State Machines ihrer Views ändern den Zustand entweder auf PROXY oder CONFLICT, je nachdem, ob das Objekt lokale Änderungen enthält oder nicht.














