Programmable Events
Information
- Here you will find a description of programmable events, their function, and how they can be created.
General
Information
- The objective of the use of programmable events is to control the system behavior as far and flexibly as possible and.
- Programmable events are to call any function required (in Python, Jython, or Java) by fixed parameters.
- In the long run, programmable events are to replace customizing exits by more powerful and simpler structures.
Details
- There are two types of events: data-driven events and time-controlled events.
- Data-driven events are events which are run when data is written.
- Time-controlled events are executed at a particular point in time, independent of other activities.
- All programmable events are saved in DT312 Events.
- If this table does not exist or if the framework cannot be started for another reason (e.g. because the Jython interface does not work), the server will not be started. In such a case, a log entry will be written which indicates that the event framework could not be loaded, the respective migration packet is to be run and that, should the error still occur, the PLANTA customer service is to be notified.
- Both event types have the same parameters, e.g. UUID, function type, parameter, and type-specific parameters. For a list and description of the individual parameters, see here.
- As far as the selected language in which event functions are written is concerned (function type),
- Java events are only to be defined for system-oriented application.
- Python events dispose of the full range of Python functionality. However, they require a running server (i.e. no plain web application).
- Jython events can be run in web applications and on regular servers.
- As far as the selected language in which event functions are written is concerned (function type),
- For the management of events, PLANTA provides the following modules in the system customizer:
Note
- No programmable events are started while the server runs in special modes (import, export, migration, and during scheduling).
Data-Driven Events
Information
- Data-driven events (or data events) can be defined for every database table.
- Data-driven events receive the event itself as a parameter (for meta information on the event behavior) as well as the object to be saved (which can be manipulated by the event). This object is either a DtpRecord (in Python) or a Pojo object, as it has been defined in the target folder (in Java and Jython).
- DtpRecords and Java-Pojo objects present different views on the same database records.
- Please note that data-driven events can only be defined for a table as a whole and not for a particular event.
- Whether the event is then to be actually executed must be checked by the event function itself (via the name of the property to be changed) or via the Condition parameter.
- Here you can find information on further parameters for data-driven events.
Event Types
Information
- The following event types are available for data-driven events:
- pre-insert/pre-update/pre-delete
- These event types are executed for insertion/update/deletion processes before saving.
- post-insert/post-update/post-delete
- These event types are executed for insertion/update/deletion processes after saving.
- pre-save/post-save
- These event types are executed for insertion/update processes before or after saving.
- A pre-save-event is both a pre-insert and a pre-update event.
- A post-save-event is both a post-insert and a post-update event.
- These event types are executed for insertion/update processes before or after saving.
- On-change
- This event type is run before saving whenever a data field is changed. Particularities are explained here.
- pre-insert/pre-update/pre-delete
- Pre-functions are executed before saving and allow you to change the record to be saved again or to abort saving (via the return value).
- Post-functions are executed after the records have been saved. They serve to adjust a record (or other objects) after saving has been completed successfully.
Note
- Pre-event-methods and on-change-event-methods can return a boolean value. The change is only carried out if this value is not
False
.
Particularities of On-Change-Events
Information
- On-Change-Events are data-driven events which are carried out each time a data field is changed - i.e. before saving.
- They therefore resemble value ranges but are more flexible since they are triggered by both Jython and Python just like any other event.
- Methods which are called by on-change-events (Jython or Python) have the name of the property which is to be changed as a parameter in addition to the usual data-event parameters (the event itself as well as the pojo object to be changed or the DtpRecord to be changed) as well as the old and new value of the property.
Processing of Data-Driven Events
Information
- Data-driven events are run within the client or web session which has caused the event to be saved.
- Data-driven events are each opened with a DtpRecord (for Python events) or with the pojo object (for Java & Jython) which is to be saved. They correspond exactly to the existing DtpRecord class or to the pojo objects as they have been defined in the target directory.
Important
- It is recommended that the pre-function itself do not carry out any save-actions since they are opened after the transaction has already been started and the saving procedure would then be triggered again.
- In case, contrary to the recommendation, pre-functions carry out save-actions, there is a mechanism which aborts infinite loops after ten recursions.
- Pre-functions are designed for two purposes:
- to check whether saving is actually permitted (by return value). If this is
False
, saving will be aborted. This does not lead to a rollback or exception since the changes for possible corrections are to be retained.- When saving from Python,
dtp_record.save()
simply returns 0 orfalse
. The handling lies within the responsibility of event itself or the saving function. - If there are multiple pre-events, no further events will be carried out after an event has returned
false
. (This is the default handling approach of "and” operators, e.g. in Java, Python, or C.)
- When saving from Python,
- Adjust settings once more. Each change made here will later be written automatically.
- to check whether saving is actually permitted (by return value). If this is
- Saving in Post-Events is less critical since the transaction has already been abandoned here. However, infinite loops are generally possible here as well. They will also be aborted after 10 recursions.
Changed properties
- A particular functionality for events is the option to retrieve all changed fields of the DtpRecord or the changed properties of the pojo object including the original value of a field. Original values are saved as soon as an object has been updated (e.g.
DataItem.setvalue()
). - Original values are reset as soon as all post-events have been run (see chart above).
Create Data-Driven Event
Procedure
- Insert an event record in the Data-Driven Events module.
- The Create Event module is opened in which the required event data can be entered.
- Select the event type and the function type for the data table to which the event is to refer.
- Allocate a function name.
- Optionally you can specify a condition and/or make an entry in the Parameter field.
- If the event is to be active directly, mark the Activated checkbox.
- An event is only executed if the Activated checkbox is activated.
- Save.
Time-Controlled Events
Information
- Time-controlled events are executed at a defined point in time regardless of saving.
- Since the events are not linked to records, they receive the event as a parameter but no DtpRecord and no pojo object.
- Here you can find information on further parameters for time-controlled events.
Processing of Time-Controlled Events
Information
- Time-controlled events are also executed when no client sessions are registered on the server.
- Consequentially, time-controlled events are executed directly in the global server session. Realizing them via the
java.util.Timer
standard Java-class assures that each event runs in its own Java thread and thus (e.g. in an infinite loop within the event function or similar) does not block the server. - When starting the server, all already existing time-controlled events are scheduled for start (as far as they are active and their Status permits it).
- Currently, only Jython or Java functions for time-controlled events are accepted.
- Since the events are currently run in the global server session, the variables of the user session, which are deemed a given in customizing, are missing here. Code which would normally calculate the user rights by means of the user variable does not run within events.
- Time-controlled events can have four statuses (specified in the Status parameter):
- 0 Waiting: The event is currently scheduled to run (again) at a later point in time.
- 1 Is executed: The function assigned to the event (Java or Jython) is currently running.
- 2 Terminated: The event has been terminated without errors and will not be run again.
- 3 Failed: An error has occurred in the last run. The event will be run again after server restart.
- When starting the server, all active time-controlled events are scanned.
- Events with Terminated or Is running status are not executed again.
- All events with Waiting and Failed status are now started and enter their life-cycle:
Scheduling of Time-Controlled Events
Information
- Events have a start date and a start time and support different intervals of recurrence.
- Possible interval modes (are specified in the Recurs parameter)
Interval | Description |
---|---|
Once | The event is executed once at the planned point in time and does not recur. |
Hourly | The event recurs every hour. |
Daily | The event recurs every day. |
Weekly | The event recurs every seven days. |
Monthly | The event recurs the next month on the same week day, e.g. on the first Monday or on the last Friday of a month. |
Yearly | The event recurs on the same date in the following year. Events on 02/29 only recur in leap years |
User-defined | A user-defined interval is specified. Allows for detailed configuration |
- In User Defined mode, the user has the following configuration options:
- The number and unit of the interval of recursion in one of the existing units: minutes / hours / days / weeks / months / years
- On which weekdays the event may be executed
- When the event is to be terminated (multiple selection not possible): never / at a defined point in time / after a defined number of executions
Implementation
- The
get_next_scheduled_execution_time
Jython scheduling function is located at<Server-Verzeichnis>/jython/server/events/event.py.
- It is called upon server start in order to schedule all time-controlled events once and every time a time-controlled event has been executed.
- It returns a
java.util.Date
which specifies the point in time at which the event is to be executed again. - If it returns the
None
function, the event switches to the "Terminated" status and will not be executed again.
- It returns a
- The
get_next_event_execution
function ofget_next_scheduled_execution_time
is called from the customizing name space under<Server-Verzeichnis>/jython/customizing/events
. - It carries out the calculation of the next time of execution according to the configuration.
- If the event has never been executed before, the configured start time is used to calculate the time of execution.
- If the event has at least one history entry, the planned time of the last event will be used.
Sequence of event execution
- The sequence of event execution is stored in data table 313 Event history.
- It is used to determine the next time of execution.
Create Time-Controlled Event
Procedure
- Insert a new event record in the Time-Controlled Events module.
- Allocate a function type and function name.
- Currently, only the Jython and Java function types are supported for time-controlled events.
- Optionally you can make an entry in the Parameter field.
- Enter Day and Time of the initial execution of the event.
- In the Recurs field, set how often the event is to be executed by making a selection from the listbox.
- If the recursion of the event is to be defined more precisely:
- Select the User-defined entry.
- Save.
- Opn the Configure User-Defined Interval module by clicking on the Configure button.
- Enter a number below the Recurs every heading and enter a Unit in order to define the interval between the recursions of the event.
- Optionally activate the checkboxes of the weekdays below the Recurs on heading in order to restrict the execution of the event to particular days.
- On the weekdays for which the checkboxes are activated, the event can be executed.
- Define below the Ends heading when the event is to be terminated, i.e. when the recursions of the event are to be suspended.
- The Never ends checkbox is activated by default.
- If the event is to be terminated on a particular date, activate the Ends on checkbox and store the date.
- If the event is to be terminated after a particular number of executions, activate the Ends after checkbox and store the number of desired executions.
- If the recursion of the event is to be defined more precisely:
- If the event is to be immediately active, mark the Activated checkbox.
- An event is only executed if the Activated checkbox is activated.
- Save.
Details
- In order to edit a user-defined interval, click on the configure button and make the changes in the Configure User-Defined Interval module.
Extension of Python Functionalities
- In the course of the implementation of programmable events, the Python API Reference has been extended by the following functions:
- In DtpRecord:
get_changed_dis
: Returns a list of all data items the values of which have been changed.get_dis
: Returns a list of all data items of the record.- Hat nicht wirklich was mit Original-Werten zu tun, aber mir ist aufgefallen, dass diese Funktion fehlt, und die Logik auf C ist fast identisch mit
get_changed_dis
(musste nur eine if-Abfrage weglassen), also… gibt’s sie jetzt
- Hat nicht wirklich was mit Original-Werten zu tun, aber mir ist aufgefallen, dass diese Funktion fehlt, und die Logik auf C ist fast identisch mit
- In DataItem:
has_been_updated
: Returnstrue
if this data item has been updatedget_original_value
: Returns the saved, initial value. If the data item has not been updated, the current value is applicable.get_original_tech_value
: The same goes for the technical value (in analogy toget_tech_value
)
- In DtpRecord: