Add yWorkflow dependencies
val yworkflowVersion = "..."
dependencies {
implementation(platform("com.yworkflow:yworkflow-bom:$yworkflowVersion")) (1)
implementation("com.yworkflow:yworkflow-engine") (2)
implementation("com.yworkflow:definition-factory-yaml") (3)
}
| 1 | Import the yWorkflow Bill of Materials (BOM) to manage all module versions centrally. |
| 2 | Include the core workflowDefinition engine. |
| 3 | Add support for defining workflowEngine using YAML files. |
Initialize the workflowDefinition engine
QuickstartWorkflowTest.java
var extensions = new InMemoryExtensionProvider(); (1)
extensions.register(new JoinStatesStatusCondition());
extensions.register(new IsUserOwnerCondition());
extensions.register(new TransitionInputValidator());
extensions.register(new PersistInputAttributeFunction());
var instanceStore = new InMemoryWorkflowInstanceStore(); (2)
var workflowEngine = WorkflowEngine.builder()
.withInstanceStore(instanceStore)
.withExtensions(extensions)
.build(); (3)
| 1 | create a InMemoryExtensionProvider and register all extensions (conditions, functions, etc.) the workflowDefinition uses (i.e. every alias found in the workflowDefinition will be looked up using this object). |
| 2 | create a store that holds workflowDefinition instances in memory |
| 3 | Use builder to create a WorkflowEngine instance |
Define the workflowDefinition using YAML
Expand to see the workflowDefinition state diagram.
leave_request.yml
workflow:
id: "leave_request"
initial-transitions:
- id: "create"
name: "Create Leave Request Draft"
validators:
- alias: "validate.input"
args:
- name: "from"
- format: "^\\d{4}-\\d{2}-\\d{2}$"
- alias: "validate.input"
args:
- name: "to"
- format: "^\\d{4}-\\d{2}-\\d{2}$"
- required: true
post-functions:
- alias: "persist.input"
args:
- name: "from"
- alias: "persist.input"
args:
- name: "to"
default-result:
state: "draft_leave_request"
states:
- id: "draft_leave_request"
name: "Draft Leave Request"
transitions:
- id: "submit"
name: "Submit Leave Request"
default-result:
fork: "forward_to_approvers"
- id: "manager_approval"
name: "Manager Approval"
transitions:
- id: "manager_deny"
name: "Manager Deny Request"
guards:
- alias: "check.state.owner"
default-result:
state: "draft_leave_request"
exit-status: "rejected"
- id: "manager_approve"
name: "Manager Approve Request"
guards:
- alias: "check.state.owner"
default-result:
join: "check_everybody_approved"
- id: "hr_approval"
name: "HR approval"
transitions:
- id: "hr_deny"
name: "HR deny request"
guards:
- alias: "check.state.owner"
default-result:
state: "draft_leave_request"
exit-status: "rejected"
- id: "hr_approve"
name: "HR approve request"
guards:
- alias: "check.state.owner"
default-result:
join: "check_everybody_approved"
- id: "approved"
name: "Leave request approved"
forks:
- id: "forward_to_approvers"
default-results:
- state: "manager_approval"
owners:
- "manager"
- state: "hr_approval"
owners:
- "hr"
joins:
- id: "check_everybody_approved"
condition:
- alias: "check.join.states.status"
default-result:
state: "approved"
Load the YAML workflowDefinition file
QuickstartWorkflowTest.java
var workflowYamlString = loadFileAsString("leave_request.yml"); (1)
var definitionSource = WorkflowYaml.fromYamlString(workflowYamlString);
var workflowDefinition = definitionSource.toWorkflowDefinition(); (2)
workflowEngine.definitions().save(workflowDefinition); (3)
| 1 | load YAML file content |
| 2 | convert YAML to WorkflowDefinition definition |
| 3 | save Workflow definition |
Create instance of the workflowDefinition
QuickstartWorkflowTest.java
var inputs = mutableAttributes()
.withString("from", "2024-01-01")
.withString("to", "2024-01-07")
.toImmutable();
var workflowDefinitionId = workflowDefinitionId("leave_request");
var transitionId = transitionId("create");
var leaveRequest = workflowEngine.instances().init(workflowDefinitionId, transitionId, inputs);
assertThat(leaveRequest).hasAvailableTransitions("submit");
assertThat(leaveRequest).hasStatus(WorkflowInstanceStatus.STARTED);
Submit Leave Request
QuickstartWorkflowTest.java
leaveRequest.transition(transitionId("submit"));
assertThat(leaveRequest).hasNoAvailableTransitions();
Approve as manager
QuickstartWorkflowTest.java
var leaveRequestAsManager = leaveRequest.actAs(caller("manager"));
assertThat(leaveRequestAsManager).hasAvailableTransitions("manager_deny", "manager_approve");
leaveRequestAsManager.transition(transitionId("manager_approve"));
Approve as HR
QuickstartWorkflowTest.java
var leaveRequestAsHr = leaveRequest.actAs(caller("hr"));
assertThat(leaveRequestAsHr).hasAvailableTransitions("hr_deny", "hr_approve");
leaveRequestAsHr.transition(transitionId("hr_approve"));
Assert workflowDefinition state
assertThat(leaveRequest).hasStatus(WorkflowInstanceStatus.COMPLETED); (1)
assertThat(leaveRequest).hasNoAvailableTransitions(); (2)
assertThat(leaveRequest).hasAttribute("from", "2024-01-01"); (3)
assertThat(leaveRequest).hasAttribute("to", "2024-01-07");
| 1 | once both HR and Manager approved the leave request, the workflowDefinition is in completed state |
| 2 | no more transitions are available at this point |
| 3 | inputs were persisted as workflowDefinition attributes |