Skip to main content

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!