enhancement
major
minor
defect
critical
major
minor
minor
#30218
ModificationListener: Es gibt keine unterstützte Möglichkeit, dem Benutzer mitzuteilen, was durch eine Modifikation geändert wurde, sobald der Commit erfolgreich war.
Problem
Ein `tl:ModificationListener` kann weitere Daten innerhalb eines Commits ändern (seine `tl:Modification` wird vor den Commit-Prüfungen ausgeführt), unabhängig davon, welcher Code die auslösende Änderung vorgenommen hat (ein Formular in der Ansicht, eine Tabellenbearbeitung, ein Import in Java). Solche impliziten Änderungen sollten dem Benutzer, der die Daten gespeichert hat, gemeldet werden – jedoch erst nach erfolgreichem Commit und in der React-View-Ebene.
Dafür gibt es keinen unterstützten Hook:
- Eine Modifikation wird vor den Commit-Prüfungen ausgeführt, sodass eine dort angezeigte Meldung auch bei einem Commit erscheinen würde, der anschließend abgelehnt wird.
- Der einzige Callback, der „nach einem erfolgreichen Commit im Commit-Thread“ aufruft, ist tl:Committable, der durch Umwandlung der Knowledge Base in tl:CommitHandler erreicht wird (addCommittable, dann complete(CommitContext)).
- Von dort aus ist der einzige Weg, den Benutzer zu erreichen, InfoService.showInfo/showWarning. Die View-Ebene-eigene Funktion `ViewMessages` benötigt einen React-Kontext, der beim Commit nicht verfügbar ist, und in der Dokumentation wird darauf hingewiesen, dass InfoService in React-Fenstern fehlschlägt. Ein reines Textfragment (Fragments.text) gelangt jedoch in die Snackbar des Fensters.
Beispiel
E-Home (haumacher/ehome #111): Das Umbenennen der ID eines Regelparameters führt dazu, dass jeder Ausdruck, der diese ID im selben Commit nennt, neu geschrieben wird (ein ModificationListener). Anschließend sollte der Benutzer die Meldung „3 Ausdrücke an die neue ID angepasst.“ sehen sowie – für einen Parameter – eine Warnung, dass ein auf dem Controller festgelegter Wert verloren geht. Implementiert mit „Committable“ plus „InfoService“ wie oben beschrieben (de.haumacher.ehome.runtime.IdRenames).
Wunsch
Eine unterstützte Möglichkeit für Code auf Modellebene (ein ModificationListener oder eine Modification), eine Nachricht für den Benutzer der aktuellen Interaktion in die Warteschlange zu stellen, die nur angezeigt wird, wenn der Commit erfolgreich war – sowohl in der React-Ansichtsebene als auch in klassischen Layouts.
Lösung
- After-Commit-Aktion: Eine AfterCommitAction wird im Commit-Thread ausgeführt, nachdem die oberste Transaktion erfolgreich festgeschrieben wurde und die Transaktion vollständig abgeschlossen ist (sie kann eine eigene Transaktion starten). Sie wird verworfen, wenn die Transaktion zurückgesetzt wird oder ihr Commit fehlschlägt, z. B. durch ein Veto eines CommitCheckers (Modellbeschränkungen). Eine fehlgeschlagene Aktion wird protokolliert und hat keinen Einfluss auf den Commit oder die anderen Aktionen.
- Informationen zum Commit: `AfterCommitAction.execute(UpdateEvent changes) ` erhält das `UpdateEvent` der festgeschriebenen Revision – dasselbe Ereignis, das auch die `UpdateListener` erhalten: die Revisionsnummer (`getCommitNumber()`), die erstellten, aktualisierten und gelöschten Objekte sowie das ChangeSet (getChanges()), einschließlich der Änderungen , die die Modification während des Commits vorgenommen hat. Eine in einer verschachtelten Transaktion registrierte Aktion erhält das Ereignis des äußersten Commits. Ein Commit ohne Änderungen erzeugt keine Revision; seine Aktionen werden mit `null` ausgeführt.
- Sie wird über ein explizites CommitActions -Handle registriert, das nichts anderes als diese Registrierung bietet – keine Abfrage einer thread-aktuellen Transaktion:
- „Transaction“ ist ein solches Handle; für Code, der die Transaktion hält,
- erhält ein `ModificationListener` das Handle der Transaktion, die gerade committet wird, als zusätzlichen Parameter von `createModification` und `notifyUpcomingDeletion`, sodass seine `Modification` eine Aktion registrieren kann.
- „Committable“ wird aufgeteilt: Es behält nur die Rolle eines Teilnehmers am Commit eines weiteren Speichers bei (prepare, prepareDelete, commit, rollback). „complete(CommitContext)“ wird zusammen mit seinen leeren Implementierungen entfernt; Aktionen nach einem erfolgreichen Commit verwenden „AfterCommitAction“.
- Benachrichtigung des Benutzers: Eine Aktion nach dem Commit wird über `InfoService.showInfo/showWarning/showError(ResKey summary, ResKey detail)` gemeldet, wodurch sie im Meldungsbereich eines klassischen Fensters und in der Snackbar eines React-Fensters angezeigt wird. Ein Test, bei dem ein Befehl über das ReactServlet gesendet wird, bestätigt den React-Pfad; die veraltete Warnung in ViewMessages, dass InfoService in React-Fenstern fehlschlägt, wird entfernt.
- Der Entwicklerartikel „view-layer/commands“ beschreibt im Abschnitt „Meldung impliziter Änderungen nach dem Commit“, wie Code auf Modellebene implizite Änderungen nach dem Commit meldet.
Der deklarative Änderungshandler für einen Typ oder ein Attribut (anstelle eines global registrierten ModificationListener) ist #30225.
Migration
- ModificationListener.createModification(KnowledgeBase, CommitActions, ...) und ModificationListener.notifyUpcomingDeletion(KnowledgeBase, CommitActions, KnowledgeItem) erhalten das Handle der festgeschriebenen Transaktion als zusätzlichen zweiten Parameter. Implementierungen fügen den Parameter hinzu.
- Committable.complete(CommitContext) wird entfernt. Eine Implementierung, die diese Methode überschreibt, verschiebt diesen Code in eine AfterCommitAction (registriert auf der Transaktion oder in einem ModificationListener für den empfangenen CommitActions-Handle; die Aktion empfängt das UpdateEvent des Commits) und entfernt die @Override-Methode.