Daten vergleichen über die Entitätsgrenzen hinaus
Eine Sache die ich in fast jeder Anwendung an der ich bisher gearbeitet habe früher oder später tun musste, ist es zu vergleichen, ob sich Daten verändert haben. Ein typischer Fall hierbei sind Schnittstellen. Wenn sich ein Datensatz in meiner Anwendung verändert hat, dann möchte ich diese Änderungen über eine Schnittstelle schicken oder ein Event erzeugen, so dass andere Anwendungen über diese Änderungen informiert sind.
Eine einfache Variante dies zu tun ist natürlich dieses Event immer genau dann auszulösen, wenn mein Datensatz gespeichert wird. In kleineren Umgebungen ist dies sicher auch eine praktikabele Lösung. Sie ist leicht und vor allem schnell zu implementieren. Sie birgt allerdings auch die Gefahr, dass jede Menge Events generiert werden die unter umständen nicht generiert werden müssten. Wir würden also gerne entscheiden ob das Event wirklich generiert werden muss. Eine erste, einfach zu verwendende Lösung liefert uns das Community Commons Modul aus dem Mendix Marketplace.
Die folgenden Beispiele orientieren sich alle an diesem Domain Model, in dem es eine Employee Entity gibt welche Assoziationen zu Location, Department sowie Address hat.
Die ObjectHasChanged Action
Im Communit Commons Modul aus dem Mendix Marketplace gibt es eine Java Action mit Namen objectHasChanged. Diese Action ist die einfache Lösung für unser oben beschriebenes Problem. Man übergibt ihr ein Objekt aus dem Cache und die Java Action liefert einen Boolean Wert zurück der uns sagt ob das Objekt sich verändert hat. In einem Microflow sieht das ganze dann folgendermaßen aus.
Diese Lösung funktioniert für den einfachen Fall tadellos und es spricht zunächst nichts dagegen diesen Ansatz zu verwenden. Diese Java Action erkennt nicht nur geänderte Attribute, sie erkennt auch geänderte Assoziationen.
Es gibt dennnoch zwei offensichtliche Nachteile.
- Es wird nicht erkannt wenn die Assoziation gleich bleibt, sich aber auf dem assoziierten Objekt etwas verändert hat. Ein Beispiel hierbei wäre eine Änderung der Adresse des Mitarbeiters.
- Die Java Action vergleicht alles. Man kann einzelne Attribute nicht von dem Vergleich ausnehmen. Möchte man zum Beispiel den LastCheckInTimestamp von dem Vergleich ausnehmen weil dieses Attribut irrelevant für das Event ist, so lässt sich das mit dieser Java Action nicht realisieren.
Wir suchen also nach einer Lösung mit der man Attribute Ignorieren kann und die in der Lage ist ganze Datenstrukturen zu vergleichen.
Vergleich mit Mappings
Eine Mögliche Lösung ist es Mappings für Vergleiche dieser Art zu verwenden. Man kann ein Mapping über mehrere Assoziationen hinweg verwenden und man kann genau definieren welche Attribute vorhanden sein sollen. Da man in der Verwendung von Schnittstellen in der Regel ohnehin mit Mappings arbeitet ist die Verwendung dieser zum Datenvergleich naheliegend. Ein weiterer großer Vorteil ist, dass man Mappings ohne großen Aufwand erweitern oder anpassen kann.
Im Konkreten sieht die Lösung nun wie folgt aus. Zunächst erstellen wir ein Mapping für die gesammte Datenstruktur.
In diesem Mapping finden sich nur diejenigen Attribute wieder, die für den Vergleich relevant sind. Werden durch Änderungen mehr oder weniger Attribute benötigt, so muss lediglich das Mapping angepasst werden.
Der eigentliche Vergleich findet in einem Microflow statt.
Dieser Microflow zieht sich das Employee Objekt aus der Datenbank, so dass die Version aus dem Cache und die Version aus der Datenbank parallel im Microflow existieren. Nun wendet sie das Mapping auf beide Objekte an. Im Endpunkt werden nun lediglich die beiden JSON Strings miteinander verglichen. Sind diese ungleich, so haben sich Änderungen auf den relevanten Attributen oder Objekten ergeben. Sind diese Strings jedoch gleich, so hat sich an den relevanten Daten nichts verändert.
Dieser Microflow kann in einem Save Prozess auf einer Employee_NewEdit Page eingesetzt werden, man kann ihn aber auch im BeforeCommit Event des Employee Objektes einsetzen.
Viel Spaß beim Ausprobieren!