Programmierbare Events
Information
- Hier wird beschrieben, was programmierbare Events sind, wie sie funktionieren und wie man sie anlegt.
Allgemeines
Information
- Das Ziel des Einsatzes von programmierbaren Events ist, das Verhalten des Systems so weit wie möglich und so flexibel wie möglich zu steuern.
- Programmierbare Events sollen beliebige Funktionen (in Python, Jython oder Java) mit feststehenden Parametern aufrufen.
- Langfristig sollen die programmierbaren Events Customizing-Exits durch mächtigere und einfachere Strukturen ersetzen.
Details
- Es gibt zwei Event-Arten: datengesteuerte Events und zeitgesteuerte Events.
- Datengesteuerte Events sind Events, die beim Schreiben von Daten ausgeführt werden.
- Zeitgesteuerte Events werden zu einem bestimmten Zeitpunkt, unabhängig von sonstiger Aktivität, ausgeführt.
- Alle programmierbaren Events werden in der DT312 Events gespeichert.
- Falls diese Tabelle nicht existiert oder das Event-Framework aus einem anderen Grund nicht gestartet werden kann (etwa, weil die Jython-Schnittstelle nicht funktioniert), wird der Server nicht gestartet. In diesem Fall wird ein Log-Eintrag geschrieben, dem zu entnehmen ist, dass das Event-Framework nicht geladen werden konnte, dass das entsprechende Migrationspaket ausgeführt werden soll und dass, falls der Fehler danach immer noch auftritt, der PLANTA-Customer-Service benachrichtigt werden soll.
- Events beider Arten haben sowohl gleiche Parameter, wie z.B. UUID, Funktionstyp, Parameter, als auch artspezifische Parameter. Die Auflistung und Beschreibung der einzelnen Parameter siehe hier.
- Was die gewählte Sprache angeht, in der Event-Funktionen geschrieben werden (Funktionstyp),
- so sollen Java-Events nur für systemnahe Anwendungsfälle definiert werden.
- Python-Events stehen die volle Python-Funktionalität zur Verfügung, sie benötigen aber einen laufenden Server (d. h., keine reine Web-Anwendung).
- Jython-Events sind in Web-Anwendungen und normalen Servern lauffähig.
- Was die gewählte Sprache angeht, in der Event-Funktionen geschrieben werden (Funktionstyp),
- Für die Verwaltung von Events stellt PLANTA im System-Customizer folgende Module zur Verfügung:
Hinweis
- Während der Server in speziellen Modi läuft (Import, Export, Migration und während der Terminierung), werden keine programmierbaren Events gestartet.
Datengesteuerte Events
Information
- Datengesteuerte Events (oder Daten-Events) können für jede Datenbank-Tabelle definiert werden.
- Datengesteuerte Events erhalten als Parameter das Event selbst (für Meta-Informationen über das Verhalten des Events), sowie das zu speichernde Objekt, das durch das Event manipuliert werden kann. Dieses Objekt ist entweder ein Programmierbare Events#DtpRecord (in Python) oder ein Pojo-Objekt, wie es im Target-Ordner definiert wurde (in Java und Jython).
- DtpRecords und Java-Pojo-Objekte sind verschiedene Sichten auf die gleichen Datenbank-Records.
- Es ist zu beachten, dass alle datengesteuerten Events nur für eine ganze Tabelle definiert werden können, nicht für ein bestimmtes Dataitem.
- Ob das Event dann wirklich ausgeführt werden soll, muss die Event-Funktion entweder selbst überprüfen (über den Namen der zu ändernden Eigenschaft) oder über den Parameter Bedingung .
- Informationen zu weiteren Parametern für datengesteuerte Events sind hier zu finden.
Eventtypen
Information
- Es gibt folgende Eventtypen für datengesteuerte Events:
- Pre-Insert/Pre-Update/Pre-Delete
- Diese Eventtypen werden vor dem Speichern für Einfüge-/Update-/Lösch-Vorgänge ausgeführt.
- Post-Insert/Post-Update/Post-Delete
- Diese Eventtypen werden nach dem Speichern für Einfüge-/Update-/Lösch-Vorgänge ausgeführt.
- Pre-Save/Post-Save
- Diese Eventtypen werden vor bzw. nach dem Speichern für Einfüge- und Update-Vorgänge ausgeführt:
- Ein Pre-Save-Event ist sowohl ein Pre-Insert- als auch Pre-Update-Event.
- Ein Post-Save-Event ist sowohl ein Post-Insert- als auch Post-Update-Event.
- Diese Eventtypen werden vor bzw. nach dem Speichern für Einfüge- und Update-Vorgänge ausgeführt:
- On-Change
- Dieser Eventtyp wird vor dem Speichern ausgeführt, immer wenn sich ein Datenfeld ändert. Besonderheiten werden hier erläutert.
- Pre-Insert/Pre-Update/Pre-Delete
- Pre-Funktionen werden vor dem Speichern ausgeführt und erlauben es, den Datensatz, der gespeichert werden soll, noch einmal zu ändern oder das Speichern abzubrechen (über den Rückgabewert).
- Post-Funktionen werden ausgeführt, nachdem die Datensätze gespeichert wurden. Sie dienen zum Anpassen eines Datensatzes (oder anderer Objekte), nachdem das Speichern erfolgreich abgeschlossen wurde.
Hinweise
- Pre-Event-Methoden und On-Change-Event-Methoden können einen Boolean-Wert zurückliefern. Die Änderung wird nur durchgeführt, wenn dieser Wert nicht
False
ist. - Post-Delete-Events funktionieren derzeit in Python nicht (Mehr Informationen).
Besonderheiten von On-Change-Events
Information
- On-Change-Events sind datengesteuerte Events, die jedes Mal ausgeführt werden, wenn sich ein Datenfeld ändert - also noch vor dem Speichern.
- Sie gleichen daher Wertebereichen, sind aber flexibler, da sie wie alle Events sowohl von Jython als auch von Python getriggert werden.
- Methoden, die von On-Change-Events aufgerufen werden (Jython oder Python) haben zusätzlich zu den üblichen Daten-Event-Parametern (das Event selbst sowie das zu ändernde Pojo-Objekt oder den zu ändernden DtpRecord) als Parameter den Namen der Eigenschaft, die geändert werden soll, und den alten und neuen Wert dieser Eigenschaft.
Ablauf datengesteuerter Events
Information
- Datengesteuerte Events werden innerhalb der Client- bzw. Web-Session ausgeführt, die das Speichern des Objekts veranlasst hat.
- Datengesteuerte Events werden jeweils mit einem DtpRecord (für Python-Events) bzw. mit dem Pojo-Objekt (für Java & Jython) aufgerufen, welches gespeichert werden soll. Sie entsprechen exakt der vorhandenen Klasse Programmierbare Events#DtpRecord bzw. den Pojo-Objekten, wie sie im Target-Ordner definiert wurden.
Wichtig
- Es wird empfohlen, dass Pre-Funktionen selbst keine Speichern-Aktionen durchführen, da sie aufgerufen werden, nachdem die Transaktion bereits gestartet wurde, und das Speichern dann u. U. den Ablauf erneut starten würde.
- Für den Fall, dass Pre-Funktionen entgegen der Empfehlung Speicher-Aktionen durchführen, gibt es einen Mechanismus, der eine Endlosschleife nach zehn Rekursionen abbricht.
- Pre-Funktionen sind für zweierlei Zwecke gedacht:
- Prüfen, ob Speichern wirklich erlaubt ist (durch Rückgabewert). Ist dies
False
, wird das Speichern abgebrochen. Dies führt nicht zu einem Rollback und auch nicht zu einer Exception, da die Änderungen für etwaige Korrekturen erhalten bleiben sollen.- Beim Speichern aus Python heraus liefert
dtp_record.save()
einfach 0 bzw.false
zurück. Das Handling davon ist die Verantwortung des Events selbst bzw. der speichernden Funktion. - Gibt es mehrere Pre-Events, werden nach dem ersten, das
false
zurückliefert, keine weiteren mehr ausgeführt. (Dies entspricht dem Standard-Handling von "and"-Operatoren z. B. in Java, Python oder C.)
- Beim Speichern aus Python heraus liefert
- Nochmals Eigenschaften anpassen. Jede Änderung hier wird später automatisch geschrieben.
- Prüfen, ob Speichern wirklich erlaubt ist (durch Rückgabewert). Ist dies
- Speichern in Post-Events ist weniger kritisch, weil hier die Transaktion bereits verlassen wurde. Prinzipiell sind jedoch auch hier Endlosschleifen möglich, die ebenfalls nach 10 Rekursionen unterbunden werden.
Geänderte Eigenschaften
- Eine besondere Funktionalität für Events ist die Möglichkeit, sämtliche Felder des DtpRecords bzw. der Eigenschaften des Pojo-Objekts abzurufen, die geändert wurden, und dazu auch den Original-Wert, den ein Feld ursprünglich hatte. Original-Werte werden gespeichert, sobald ein Update an einem Objekt aufgerufen wurde (z.B.
DataItem.setvalue()
). - Original-Werte werden zurückgesetzt, sobald alle Post-Events ausgeführt wurden (s. Diagramm oben).
Wie man datengesteuerte Events anlegt, findet man in der Beschreibung des Moduls Datengesteuerte Events.
Zeitgesteuerte Events
Information
- Zeitgesteuerte Events werden unabhängig vom Speichern zu bestimmten Zeiten ausgeführt werden.
- Da diese Events nicht an Datensätze gebunden sind, erhalten sie als Parameter das Event, aber keinen DtpRecord und kein Pojo-Objekt.
- Informationen zu weiteren Parametern für zeitgesteuerte Events sind hier zu finden.
Ablauf zeitgesteuerter Events
Information
- Zeitgesteuerte Events werden auch ausgeführt, wenn keinerlei Client-Sessions am Server angemeldet sind.
- Daraus folgt, dass zeitgesteuerte Events direkt in der globalen Server-Session ausgeführt werden. Da sie durch die Standard-Java-Klasse
java.util.Timer
realisiert werden, wird sichergestellt, dass jeder Event in einem eigenen Java-Thread läuft und daher (etwa bei einer Endlosschleife innerhalb der Event-Funktion o. ä.) nicht den Server blockiert. - Beim Starten des Servers werden zunächst alle vorhandenen zeitgesteuerten Events (sofern sie aktiv sind und ihr Status dies zulässt) zum Starten terminiert.
- Es werden derzeit nur Jython- oder Java-Funktionen für zeitgesteuerte Events akzeptiert.
- Da die Events derzeit in der globalen Server-Session ausgeführt werden, fehlen die im Customizing als selbstverständlich angesehenen Variablen der Benutzer-Session. Code, der beispielsweise über die Benutzervariable die Benutzerrechte berechnen würde, läuft innerhalb von Events nicht.
- Zeitgesteuerte Events können vier Zustände haben (hinterlegt im Parameter Status ):
- 0 Wartend: Das Event ist derzeit terminiert, zu einem späteren Zeitpunkt (erneut) zu laufen.
- 1 Wird ausgeführt: Die dem Event zugeordnete Funktion (Java oder Jython) läuft derzeit.
- 2 Beendet: Das Event wurde ohne Fehler beendet und wird nicht erneut ausgeführt werden.
- 3 Fehlgeschlagen: Bei der letzten Ausführung trat ein Fehler auf. Das Event wird nach Server-Neustart erneut ausgeführt.
- Beim Start des Servers werden alle aktiven zeitgesteuerten Events durchgesehen.
- Events mit dem Status Beendet oder Wird ausgeführt werden nicht mehr ausgeführt.
- Alle Events mit dem Status Wartend und Fehlgeschlagen werden nun gestartet und treten in ihren Lebenszyklus ein:
Terminierung von zeitgesteuerten Events
Information
- Events haben ein Startdatum und eine Startuhrzeit und unterstützen verschiedene Wiederholintervalle.
- Mögliche Intervall-Modi (werden hinterlegt im Parameter Wiederholt sich):
Intervall | Beschreibung |
---|---|
Einmalig | Das Event wird einmalig zum geplanten Zeitpunkt ausgeführt und nicht wiederholt. |
Stündlich | Das Event wird jede Stunde wiederholt. |
Täglich | Das Event wird jeden Tag wiederholt. |
Wöchentlich | Das Event wird alle sieben Tagen wiederholt. |
Monatlich | Das Event wiederholt sich am gleichen Wochentag im nächsten Monat z. B. am ersten Montag oder am letzten Freitag eines Monats. |
Jährlich | Das Event wiederholt sich am gleichen Datum im nächsten Jahr. Events am 29.02. werden nur in Schaltjahren wiederholt. |
Benutzerdefiniert | Ein benutzerdefiniertes Intervall wird hinterlegt. Erlaubt eine detailliertere Konfiguration. |
- Der Anwender hat im Modus Benutzerdefiniert die folgenden Konfigurationsmöglichkeiten:
- Die Anzahl und Einheit des Wiederholintervalls in einer der vorhanden Einheiten: Minuten / Stunden / Tage / Wochen / Monate / Jahre
- An welchen Wochentagen das Event laufen darf
- Wann das Event enden soll (Mehrfachauswahl nicht möglich): nie / an einem bestimmten Zeitpunkt / nach einer bestimmten Anzahl Ausführungen
Die Implementierung
- Die Jython-Terminierungsfunktion
get_next_scheduled_execution_time
befindet sich unter<Server-Verzeichnis>/jython/server/events/event.py.
- Sie wird beim Server-Start aufgerufen, um alle zeitgesteuerten Events einmal zu terminieren, sowie jedes Mal, nachdem ein zeitgesteuertes Event ausgeführt wurde.
- Sie liefert ein
java.util.Date
zurück, welches den Zeitpunkt angibt, zu dem das Event das nächste Mal ausgeführt werden soll. - Liefert sie die Funktion
None
zurück, wechselt das Event in den Status "Beendet" und wird nicht erneut ausgeführt werden.
- Sie liefert ein
- Es wird die Funktion
get_next_event_execution
aus dem Customizing-Namespace unter<Server-Verzeichnis>/jython/customizing/events
vonget_next_scheduled_execution_time
aufgerufen. - Diese führt die Berechnung des nächsten Ausführungszeitpunkts anhand der Konfiguration durch.
- Ist das Event noch nie gelaufen wird die konfigurierte Startzeit genommen, um den Ausführungszeitpunkt zu berechnen.
- Hat das Event mindestens einen Historie-Eintrag wird die geplante Zeit des letztens Events herangezogen.
Verlauf der Eventdurchführungen
- Der Verlauf der Eventdurchführungen wird in der Datentabelle 313 Event-Historie verwahrt.
- Sie wird verwendet, um den nächsten Ausführzeitpunkt zu ermitteln.
Wie man zeitgesteuerte Events anlegt, findet man in der Beschreibung des Moduls Zeitgesteuerte Events.
Startup-Events
Information
- Startup-Events werden unabhängig vom Speichern genau einmal beim Server-Startup ausgeführt.
- Da diese Events nicht an Datensätze gebunden sind, erhalten sie als Parameter das Event, aber keinen DtpRecord und kein Pojo-Objekt.
- Sie können als abgespeckte Zeitgesteuerte Events verstanden werden (also zeitgesteuerte Events ohne Informationen zu ihrer Terminierung, wann sie laufen sollen).
Ablauf von Startup-Events
Information
- Startup-Events werden automatisch ausgeführt, sobald der PLANTA-Server gestartet wurde und sich initialisiert hat.
- Wie Zeitgesteuerte Events auch werden Startup-Events in der globalen Server-Session ausgeführt.
- Sie werden gemäß der Spalte Position der Tabelle Events nacheinander ausgeführt.
- Etwaige Fehler beim Ausführen von Startup-Events werden im Log-File vermerkt.
- Wie für zeitgesteuerten Events werden auch für Startup-Events derzeit nur Jython- oder Java-Funktionen akzeptiert. Startup-Events vom Typ "Python" werden nicht ausgeführt.
- Es gibt aber (wie bei Zeitgesteuerten Events auch) die Möglichkeit, über die Jython-Funktion
customizing.events.module.run_module
ein Python-Modul auszuführen, das dann in einer Clientless-Session ausgeführt wird.
- Es gibt aber (wie bei Zeitgesteuerten Events auch) die Möglichkeit, über die Jython-Funktion
Wie man Startup-Events anlegt, findet man in der Beschreibung des Moduls Startup-Events.
Erweiterung der Python-Funktionalitäten
- Im Zuge der Einführung programmierbarer Events wurde die Python API um folgende Funktionen erweitert:
- In Programmierbare Events#DtpRecord:
get_changed_dis
: Gibt eine Liste aller DataItems zurück, deren Wert geändert wurdeget_dis
: Gibt eine Liste aller DataItems des Records zurück.
- In Programmierbare Events#DataItem:
has_been_updated
: Gibttrue
zurück, falls dieses DataItem upgedated wurde.get_original_value
: Gibt den gespeicherten, ursprünglichen Wert zurück. Falls das DataItem nicht upgedated wurde, ist dies der aktuelle Wert.get_original_tech_value
: Gibt den gespeicherten, ursprünglichen technischen Wert zurück (analog zuget_tech_value
).
- In Programmierbare Events#DtpRecord: