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.
  • 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 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.
    • On-Change
      • Dieser Eventtyp wird vor dem Speichern ausgeführt, immer wenn sich ein Datenfeld ändert. Besonderheiten werden hier erläutert.
  • 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 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.)
    • Nochmals Eigenschaften anpassen. Jede Änderung hier wird später automatisch geschrieben.
  • 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).

Ein datengesteuertes Event anlegen

Vorgehensweise

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.
    • Es gibt jedoch die Möglichkeit, ein Python-Modul auszuführen, das dann in einer Clientless Session ausgeführt wird.
    • Dazu in dem Modul für Zeitgesteuerte Events den Funktionstyp Jython auswählen, den Funktionsnamen customizing.events.module.run_module und als Parameter den Benutzer, der das Modul startet (standardmäßig PLSYSTEM), gefolgt von ; und dem Funktionsnamen, also z.B. PLSYSTEM;987654
  • 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):
IntervallBeschreibung
EinmaligDas Event wird einmalig zum geplanten Zeitpunkt ausgeführt und nicht wiederholt.
StündlichDas Event wird jede Stunde wiederholt.
TäglichDas Event wird jeden Tag wiederholt.
WöchentlichDas Event wird alle sieben Tagen wiederholt.
MonatlichDas 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.

BenutzerdefiniertEin 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.
  • Es wird die Funktion get_next_event_execution aus dem Customizing-Namespace unter <Server-Verzeichnis>/jython/customizing/events von get_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

Ein zeitgesteuertes Event anlegen

Vorgehensweise

  • Im Modul Zeitgesteuerte Events einen neuen Event-Datensatz einfügen.
  • Funktionstyp und Funktionsnamen vergeben.
    • Aktuell werden für zeitgesteuerte Events nur die Funktionstypen Jython und Java unterstützt.
  • Optional einen Eintrag im Feld Parameter vornehmen.
  • Tag und Uhrzeit der erstmaligen Ausführung des Events eingeben.
  • Im Feld Wiederholt sich  aus der Listbox auswählen, wie häufig das Event ausgeführt werden soll.
    • Wenn die Wiederholung des Events genauer konfiguriert werden soll:
      • Den Eintrag Benutzerdefiniert auswählen.
      • Speichern.
      • Mit Klick auf die Schaltfläche konfigurieren das Modul Benutzerdefiniertes Intervall konfigurieren aufrufen.
        • Unter der Überschrift Wiederholt sich alle eine Zahl und eine Einheit eingeben, um den Abstand zwischen den Wiederholungen des Events festzulegen.
        • Unter der Überschrift Wiederholt sich am optional die Checkboxen der Wochentage aktivieren, um die Ausführung des Events auf bestimmte Tage zu beschränken.
          • An den Wochentagen der aktivierten Checkboxen darf das Event durchgeführt werden.
        • Unter der Überschrift Endet festlegen, wann das Event beendet werden soll, d. h. wann die Wiederholungen des Events eingestellt werden.
          • Standardmäßig ist die Checkbox Endet nie aktiviert.
          • Wenn das Event an einem bestimmten Datum beendet werden soll, die Checkbox Endet am aktivieren und das Datum hinterlegen.
          • Wenn das Event nach einer bestimmten Anzahl an Ausführungen beendet werden soll, die Checkbox Endet nach aktivieren und die Anzahl der gewünschten Ausführungen hinterlegen.
  • Wenn das Event direkt aktiv sein soll, das Häkchen in der Checkbox Aktiviert setzen.
    • Ein Event wird nur ausgeführt, wenn in der Checkbox Aktiviert das Häkchen gesetzt ist.
  • Speichern.

Details

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.

Erweiterung der Python-Funktionalitäten

  • Im Zuge der Einführung programmierbarer Events wurde die Python API um folgende Funktionen erweitert:
    • In  DtpRecord:
      • get_changed_dis : Gibt eine Liste aller DataItems zurück, deren Wert geändert wurde
      • get_dis : Gibt eine Liste aller DataItems des Records zurück.
    • In  DataItem:
      • has_been_updated : Gibt  true  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 zu  get_tech_value).