I need to create a workflow that lets the user retrieve an entity from the database, review it, and finally approve or discard it. If the user approves the entity, the application just updates its status to APPROVED
, otherwise if the user discards the entity, the application updates its status to DISCARDED
.
When a new entity gets stored into the database, its status is default to DRAFT
. When the user starts reviewing the entity, the status is then set to IN_REVIEW
– a review might last several days.
To implement the workflow I defined the following JavaDelegate
classes:
public class ReviewEntityTask implements JavaDelegate {
public void execute(DelegateExecution execution) {
// set entity status to IN_REVIEW and update DB
}
}
public class ApproveEntityTask implements JavaDelegate {
public void execute(DelegateExecution execution) {
// set entity status to APPROVED and update DB
}
}
public class DiscardEntityTask implements JavaDelegate {
public void execute(DelegateExecution execution) {
// set entity status to DISCARDED and update DB
}
}
Then, looking at the official documentation, the workflow should be setup like this:
@Service
public class MyWorkflowService {
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
public void startProcess(Article article) {
Map<String, Object> variables = new HashMap<>();
...
runtimeService.startProcessInstanceByKey("entityReview", variables);
}
public void updateOnReview(final MyEntity myEntity) {
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("review", myEntity.getStauts == "IN_REVIEW");
taskService.complete(myEntity.getId(), variables);
}
public void updateOnApprove(final MyEntity myEntity) {
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("approved", myEntity.getStauts == "APPROVED");
taskService.complete(myEntity.getId(), variables);
}
public void updateOnDiscard(final MyEntity myEntity) {
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("discarded", myEntity.getStauts == "DISCARDED");
taskService.complete(myEntity.getId(), variables);
}
}
Before running any task, I need to call runtimeService.startProcessInstanceByKey
to start the process. So my question is: how do I restart the workflow from a given [previous] status? For instance, let's suppose today I start the review by invoking updateOnReview
(status goes to IN_REVIW
) ... and in two days I'm going to approve it by invoking updateOnApprove
(status goes to APPROVED
), how should I invoke runtimeService.startProcessInstanceByKey
to start the workflow from the task I left previously (i.e. the one associated with status IN_REVIEW
)? Thanks.
The way I understand your scenario, the process instance you previously started is now waiting in a user task for an update. You use the taskService to complete the user task and submit the data update. Your question is how to match the update operation to the correct already running instance.
When you start the process instances, you need to include a unique identifier which can be used for this matching later. The natural choice would be the entity id. You can include it in process data, but setting it as businssKey would be even better. https://www.flowable.com/open-source/docs/javadocs/org/flowable/engine/RuntimeService.html#startProcessInstanceById(java.lang.String)
Later, when you need to update the process instance you can use the TaskService to run a query with the businessKey (or process data) as search criteria. https://www.flowable.com/open-source/docs/javadocs/org/flowable/engine/TaskService.html#createTaskQuery()
The query will return you the user task belonging to teh right process instance. Now you can complete this user task using the TaskService and the returned task's id (not the id of your entity).