13. Timer Events
Timer events enable deadline-based workflow automation. Flowable evaluates timers using its async executor.
Timer Event Types
| Type | BPMN Element | Purpose |
|---|---|---|
| Boundary (Interrupting) | <boundaryEvent cancelActivity="true"> |
Cancels the task and takes alternate path |
| Boundary (Non-Interrupting) | <boundaryEvent cancelActivity="false"> |
Triggers action but keeps task active |
| Intermediate Catch | <intermediateCatchEvent> |
Pauses process for a duration |
Timer Duration Formats (ISO 8601)
| Format | Example | Meaning |
|---|---|---|
| Minutes | PT30M |
30 minutes |
| Hours | PT2H |
2 hours |
| Days | P1D |
1 day |
| Combined | P3DT4H |
3 days and 4 hours |
| Repeating | R/PT1H |
Repeat every hour indefinitely |
| Limited Repeats | R3/PT1H |
Repeat 3 times, every hour |
Pattern 1: Auto-Skip After Timeout
Task automatically skips after a duration. The process continues to the next step.
<userTask id="optionalApproval" name="Optional Approval" flowable:candidateGroups="ROLE_APPROVER"/>
<!-- Interrupting timer: cancels task after 48 hours -->
<boundaryEvent id="timeout" attachedToRef="optionalApproval" cancelActivity="true">
<timerEventDefinition>
<timeDuration>PT48H</timeDuration>
</timerEventDefinition>
</boundaryEvent>
<!-- Both paths lead to the same next step -->
<sequenceFlow sourceRef="optionalApproval" targetRef="nextStep"/>
<sequenceFlow sourceRef="timeout" targetRef="nextStep"/>
Pattern 2: Escalation (Reassign After Timeout)
Task is reassigned to a different user or role after a timeout. Uses reassignTask delegate.
<userTask id="employeeTask" name="Employee Review" flowable:assignee="${initiator}"/>
<!-- Non-interrupting timer: triggers escalation but keeps task -->
<boundaryEvent id="escalateTimer" attachedToRef="employeeTask" cancelActivity="false">
<timerEventDefinition>
<timeDuration>P2D</timeDuration>
</timerEventDefinition>
</boundaryEvent>
<sequenceFlow sourceRef="escalateTimer" targetRef="doEscalation"/>
<!-- Reassign to manager role -->
<serviceTask id="doEscalation" flowable:delegateExpression="${reassignTask}">
<extensionElements>
<flowable:field name="targetCandidateGroups" stringValue="ROLE_MANAGER"/>
<flowable:field name="clearExisting" stringValue="true"/>
</extensionElements>
</serviceTask>
ReassignTaskDelegate Fields
| Field | Description |
|---|---|
targetAssignee |
Email of specific user to assign to |
targetCandidateUsers |
Comma-separated list of user emails |
targetCandidateGroups |
Comma-separated list of roles (e.g., ROLE_MANAGER,ROLE_ADMIN) |
clearExisting |
If "true", clears existing assignee before adding new ones |
Pattern 3: Delayed Actions (e.g., Follow-up Email)
Execute an action after a specified delay.
<userTask id="submitRequest" name="Submit Request" flowable:assignee="${initiator}"/>
<sequenceFlow sourceRef="submitRequest" targetRef="waitTimer"/>
<!-- Wait for 24 hours -->
<intermediateCatchEvent id="waitTimer" name="Wait 24 Hours">
<timerEventDefinition>
<timeDuration>PT24H</timeDuration>
</timerEventDefinition>
</intermediateCatchEvent>
<sequenceFlow sourceRef="waitTimer" targetRef="sendFollowUp"/>
<serviceTask id="sendFollowUp" flowable:delegateExpression="${sendReminder}">
<extensionElements>
<flowable:field name="to" expression="${initiator}"/>
<flowable:field name="subject" stringValue="Follow-up"/>
<flowable:field name="body" stringValue="24 hours have passed since submission."/>
</extensionElements>
</serviceTask>
Pattern 4: Repeating Email Reminders
Send reminder emails on a schedule while task is pending. Uses sendReminder delegate.