Custom Triggers
Workflow transitions ship with a few standard triggers but your application may have a need for more than that. ProcessAutomation allows you to define and implement your own triggers and provides several APIs to make this easier.
Direct triggers
The first class of triggers are direct triggers. These will schedule transitions directly using the
{Workflow}Scheduler
(EJB) service. This interface provides two methods, scheduleTransition
and performTransition
.
Schedule transition
Using scheduleTransition
is the preferred method of implementing triggers. It will offer the provided transition to
the queue such that it can be lazily executed whenever the application has room.
Perform transition
Using performTransition
is discouraged but can be required in some cases. This will circumvent the queue and directly
try to perform the transition. Note that it still needs to acquire room on the performer, but it generally has
precedence over the queue.
An example for this type of trigger is the FlowEngine
because it synchronously needs to execute a list of tasks.
Because this avoids using the queue it is recommended to use a Schedule
trigger instead, which will put tasks on the
queue.
Providing context
The TransitionContext
is used to supply the required information for a transition. The Context
, the transition to
execute and the target element DataRef
. Additionally, it is possible to provide a Serializable
value. This is useful
for tasks defined with the target.class.custom
option.
Event based triggers
Some triggers such as OnCreate
are executed based on some event. This event can originate from multiple places in the
application. Events make it possible to decouple the trigger from those places. All provided events are exposed through
the {DataElement}Events
interface. The {Workflow}EventHandler
provides the trigger implementations based on these
events. Note that the event handler also uses the {Workflow}Scheduler
to schedule its transitions.
The implementation makes use of Jakarta EE Observers from the Context and Dependency Injection (CDI) api.
Transactions
It is important to note that the event handlers run BEFORE_COMPLETE
of the transaction. This is to enable a two-phased
commit in the queue. While the scheduleTransition
call is within the transaction, the job will only be released once
the transaction is committed. This means if anything in the transaction (or even scheduling the transaction) fails, the
transaction is rolled back and no jobs are put on the queue.
In some scenarios you cannot directly rely on the transaction for your trigger to complete. If you need this
functionality, the TransactionPostCommitHook
is provided to run actions after the transaction was committed.
Triggers in custom code
Some triggers are just a one-off and not worth expanding. For these cases there is the CustomTrigger
which allows
you to at least document which custom triggers are present. It is recommended to do this to not lose track of the
custom triggers defined in the application.
Triggers in expanders
Once you discover an expandable pattern, it is easiest to start with a flag option on CustomTrigger
. This avoids
you having to create a metamodel for your trigger but usually gets you a long way for the expanders.
Explicitly modelling a trigger
If you need more complex information, or want to explicitly name your trigger, you can extend the workflows metamodel
to include your own trigger. You simply need to define a new ElementClass with workflows::Trigger
as its supertype.
You can now add expanders based on your own trigger type!