Flowable BPMN 用户手册 (v 6.3.0)
idea的Flowable BPMN visualizer插件
@Test
void completeTask1(){
Map map = new HashMap<>();
map.put("flag",false); //设置为true,结束多人会签
taskService.complete("71337501-b22e-11ec-a534-c03c59ad2248",map);
System.out.println("complete ....");
}
第8步:再次通过任务id,去完成任务(查看多人会签任务时,有2个人去完成任务的效果是怎么样的)
map.put("flag",true); //设置为true,结束多人会签
第9步:验证3
应用场景
用户任务4回退到用户任务3,或者从用户任务4回退到用户任务1。
/**
* moveActivityIdTo(),可以从当前的流程跳转到任意的节点
*/
@Test
public void rollbackTask(){
ProcessEngine processEngine = configuration.buildProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
runtimeService.createChangeActivityStateBuilder()
.processInstanceId("67501")
.moveActivityIdTo("usertask4","usertask3")//方法1:可以从当前活动的节点(Id),跳转指定的新的节点(Id)
//.moveActivityIdsToSingleActivityId(currentActivityIds,newActivityId)
.changeState();//改变状态
}
@Test
public void rollbackTask1(){
ProcessEngine processEngine = configuration.buildProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
List newActivityIds = new ArrayList();
newActivityIds.add("usertask1");
runtimeService.createChangeActivityStateBuilder()
.processInstanceId("67501")
//方法1:可以从当前活动的节点(Id),跳转指定的新的节点(Id)
//.moveActivityIdTo("usertask4","usertask3")
//方法2:从当前活动的节点(id),跳转到List ids集合(多个节点)。
.moveSingleActivityIdToActivityIds("usertask4",newActivityIds)
.changeState();//改变状态
}
@Test
public void rollbackTask1(){
ProcessEngine processEngine = configuration.buildProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
List newActivityIds = new ArrayList();
newActivityIds.add("usertask1");
runtimeService.createChangeActivityStateBuilder()
.processInstanceId("67501")
//方法1:可以从当前活动的节点(Id),跳转指定的新的节点(Id)
//.moveActivityIdTo("usertask4","usertask3")
//方法2:从当前活动的节点(id),跳转到List ids集合(多个节点)。
//.moveSingleActivityIdToActivityIds("usertask4",newActivityIds)
//方法3:不管当前节点是哪个了,就是要从当前执行实例跳到哪个节点。参数1:执行id,参数2:目标id。
.moveExecutionToActivityId("77501","usertask3")
.changeState();//改变状态
}
moveActivityIdTo(String currentActivityId,String newActivityId)
这个方法来处理。应用场景
业务副总肯定是不能回退到行政副总。即使你可以强行跳过来,但这种逻辑是不合理的。
从业务副总回退到业务负责人,这是串行的,和上面的操作一样。
关注1:从并行节点回退到串行节点。并行审批流转到业务副总(没处理),同时流转到行政副总(没处理)。编码要实现,业务副总(没处理)回退到用户审批01(起始节点)。自动地,行政副总要自动回退到用户审批01(起始节点)。
关注2:并行审批流转到业务副总(没处理),同时流转到行政副总(已处理,到达并行网关之集合)。因为是并行网关,所以也要等待业务副总(没处理)审批是吧。这时想编码要实现,业务副总(没处理)回退到用户审批01(起始节点)。自动地,行政副总要自动回退到用户审批01(起始节点)。
关注3:从串行节点回退到并行节点。总经理回退到并行网关中的业务副总、行政副总。
关注4:总经理回退到用户审批01(起始节点),其实也是串行的,和上面的操作一样。
/**
* 回退操作
* 业务副总驳回到到用户审批处 那么行政审批的应该自动回到到用户审批处
*/
@Test
public void rollbackTask(){
ProcessEngine processEngine = configuration.buildProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
// 当前的Task对应的用户任务的Id
List currentActivityIds = new ArrayList();
currentActivityIds.add("usertask4"); // 业务副总
currentActivityIds.add("usertask3"); // 行政副总
// 需要回退的目标节点的用户任务Id
String newActivityId = "usertask1"; // 用户审批01
// 回退操作
runtimeService.createChangeActivityStateBuilder()
.processInstanceId("95001")
.moveActivityIdsToSingleActivityId(currentActivityIds,newActivityId)
.changeState();
}
第6步:验证
task表
act_hi_actinst表,查看任务列表
第三步:演示2:并行审批流转到业务副总(没处理),同时流转到行政副总(已处理,到达并行网关之集合)。因为是并行网关,所以也要等待业务副总(没处理)审批是吧。这时想编码要实现,业务副总(没处理)回退到用户审批01(起始节点)。自动地,行政副总要自动回退到用户审批01(起始节点)。
第1步:完成任务:用户审批01,user1。业务负责人,user2。行政副总,user4。
第2步:验证
task表,只有1条任务,流转到(即等待)业务副总user3
act_hi_actinst表,查看任务列表
第3步:业务副总(没处理)回退到用户审批01,重新去录入相关数据。行政副总会自动回退到用户审批01:
/**
* 回退操作
* 业务副总驳回到到用户审批处
*/
@Test
public void rollbackTask(){
ProcessEngine processEngine = configuration.buildProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
// 当前的Task对应的用户任务的Id
List currentActivityIds = new ArrayList();
currentActivityIds.add("usertask4"); // 业务副总
//currentActivityIds.add("usertask3"); //行政副总
// 需要回退的目标节点的用户任务Id
String newActivityId = "usertask1"; // 用户审批01
// 回退操作
runtimeService.createChangeActivityStateBuilder()
.processInstanceId("95001")
.moveActivityIdsToSingleActivityId(currentActivityIds,newActivityId)
.changeState();
}
第四步:演示3:总经理回退到并行网关中的业务副总、行政副总。
@Test
public void rollbackTask(){
ProcessEngine processEngine = configuration.buildProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
// 当前的Task对应的用户任务的Id
List newActivityId = new ArrayList();
newActivityId.add("usertask2"); //业务负责人
newActivityId.add("usertask3"); //行政副总
// 回退操作
runtimeService.createChangeActivityStateBuilder()
.processInstanceId("95001")
.moveSingleActivityIdToActivityIds("usertask5",newActivityId)
.changeState();
}
/**
* 回退操作
* 从子流程回退到主流程操作
*/
@Test
void rollbackMainTask(){
// 回退操作
runtimeService.createChangeActivityStateBuilder()
.processInstanceId("2501")
// 没有多个时,可用此方法
.moveActivityIdTo("usertask2","usertask1")
.changeState();
}
}
/**
* 回退操作
* 从子流程回退到主流程操作:moveExecutionToActivityId不关心当前的节点
*/
@Test
void rollbackMainTask(){
// 回退操作
runtimeService.createChangeActivityStateBuilder()
.processInstanceId("2501")
.moveExecutionToActivityId("5003","usertask1")
.changeState();
}
/**
* 回退操作
*/
@Test
void rollbackSubTask(){
// 回退操作
runtimeService.createChangeActivityStateBuilder()
.processInstanceId("2501")
//当然也可以回退到usertask1
.moveActivityIdTo("usertask3","usertask2")
.changeState();
}
第四步:验证
task表
act_hi_actinst
撤消 = 回退 + 删除历史记录信息
实际开发过程中,要结合历史数据。通过一些sql语句,所这些回退节点都找出来。如果说操作比较复杂,你可能还要去重、编排、处理。
/**
* 查看部署的流程内置的表单信息
*/
@Test
public void getStartFromData(){
ProcessEngine processEngine = configuration.buildProcessEngine();
StartFormData startFormData = processEngine.getFormService().getStartFormData("inner_form:1:4");
List formProperties = startFormData.getFormProperties();
for (FormProperty formProperty : formProperties) {
String id = formProperty.getId();
String name = formProperty.getName();
FormType type = formProperty.getType();
System.out.println("id = " + id);
System.out.println("name = " + name);
System.out.println("type.getClass() = " + type.getClass());
}
}
/**
* 正常的启动流程
*/
@Test
void startFlow() throws Exception{
Map map = new HashMap<>();
map.put("days","5");
map.put("startDate","20220403");
map.put("reason","想休息下");
ProcessInstance processInstance = runtimeService
.startProcessInstanceById("myProcess:5:4dd61987-b313-11ec-882d-c03c59ad2248",map);
}
/**
* 通过FormService来启动一个表单流程
* @throws Exception
*/
@Test
void startFormFlow() throws Exception{
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.deploymentId("4da14de4-b313-11ec-882d-c03c59ad2248")
.singleResult();
// map只能是
Map map = new HashMap<>();
map.put("days","2");
map.put("startDate","20220406");
map.put("reason","出去玩玩");
// 提交启动的表单数据
// ProcessInstance processInstance = processEngine.getFormService().submitStartFormData("inner_form:1:4", map);
ProcessInstance processInstance = processEngine.getFormService().submitStartFormData(processDefinition.getId(), map);
}
/**
* 根据Task编号来查看表单数据
*/
@Test
public void getTaskFormData(){
ProcessEngine processEngine = configuration.buildProcessEngine();
String taskId = "2508";// taskId,即任务编号
TaskFormData taskFormData = processEngine.getFormService().getTaskFormData(taskId);
List formProperties = taskFormData.getFormProperties();
for (FormProperty formProperty : formProperties) {
System.out.println("formProperty.getId() = " + formProperty.getId());
System.out.println("formProperty.getName() = " + formProperty.getName());
System.out.println("formProperty.getValue() = " + formProperty.getValue());
}
}
/**
* 根据Task编号来修改(保存、更新)表单数据
*/
@Test
public void saveOrupdateTaskFormData(){
ProcessEngine processEngine = configuration.buildProcessEngine();
String taskId = "2508";// taskId,即任务编号
Map map = new HashMap();
map.put("reson","巴拉巴拉");
FormService formService = processEngine.getFormService();
formService.saveFormData(taskId,map);
}
/**
* 直接完成任务
*/
@Test
public void submitTaskFormData1(){
// 直接完成
ProcessEngine processEngine = configuration.buildProcessEngine();
processEngine.getTaskService().complete("2508");
}
/**
* 保存表单数据并完成任务
*/
@Test
public void submitTaskFormData2(){
ProcessEngine processEngine = configuration.buildProcessEngine();
String taskId = "2508";
// 完成任务的同时可以修改(保存、更新)表单数据
Map map = new HashMap();
map.put("days","7");
map.put("startDate","20220408");
map.put("reason","9出去玩玩");
processEngine.getFormService().submitTaskFormData(taskId,map);
}
/**
* 查看已经完成的Task的表单数据
*/
@Test
void getHisTaskFormData(){
String taskId = "80efeb32-b313-11ec-a7ff-c03c59ad2248";
List list = processEngine.getHistoryService()
.createHistoricDetailQuery()
.taskId(taskId)
.formProperties()
.list();
for (HistoricDetail historicDetail : list) {
HistoricFormPropertyEntityImpl his = (HistoricFormPropertyEntityImpl) historicDetail;
System.out.println("his.getPropertyId() = " + his.getPropertyId());
System.out.println("his.getPropertyValue() = " + his.getPropertyValue());
}
}
{
"key": "form1",
"name": "请假流程",
"fields": [
{
"id": "startTime",
"name": "开始时间",
"type": "date",
"required": true,
"placeholder": "empty"
},
{
"id": "days",
"name": "请假天数",
"type": "string",
"required": true,
"placeholder": "empty"
},
{
"id": "reason",
"name": "请假原因",
"type": "text",
"required": true,
"placeholder": "empty"
}
]
}
@Autowired
private FormRepositoryService formRepositoryService;
/**
* 部署form表单:在外置Form表单中我们需要在流程部署完毕后,再对表单做部署的操作
*/
@Test
public void deployForm() throws Exception{
FormDeployment formDeployment = formRepositoryService.createDeployment()
.addClasspathResource("holiday.form")
.name("test")
.parentDeploymentId("1") //和我们上面部署的流程关联
.deploy();
System.out.println("formDeployment.getId() = " + formDeployment.getId());
}
/**
* 启动流程实例,并且设置对应的值
*/
@Test
void startTask(){
Map map = new HashMap<>();
map.put("days","4");
map.put("startTime","20220404");
map.put("reason","出去玩玩");
ProcessInstance processInstance = runtimeService.startProcessInstanceWithForm(
"myProcess:1:4"
, null
, map
, "请假流程");
String id = processInstance.getId();
System.out.println("id = " + id);
}
/**
* 查看流程定义表单数据
*/
@Test
public void getTaskFormData1(){
Task task = taskService.createTaskQuery()
.processDefinitionId("myProcess:1:4")
.taskAssignee("zhangsan")
.singleResult();
// FormInfo 表单的元数据信息
FormInfo formInfo = runtimeService.getStartFormModel("myProcess:1:4", "5001");
System.out.println("formInfo.getId() = " + formInfo.getId());
System.out.println("formInfo.getName() = " + formInfo.getName());
System.out.println("formInfo.getKey() = " + formInfo.getKey());
// FormModel 表单中的具体信息 具体实现是 SimpleFormModel
SimpleFormModel formModel = (SimpleFormModel) formInfo.getFormModel();
List fields = formModel.getFields();
for (FormField field : fields) {
System.out.println("field.getId() = " + field.getId());
System.out.println("field.getName() = " + field.getName());
System.out.println("field.getValue() = " + field.getValue());
}
System.out.println("formModel = " + formModel);
}
/**
* 查看具体的Task的表单数据
*/
@Test
void getTaskData(){
FormInfo formInfo = taskService.getTaskFormModel("17505");
System.out.println("formInfo.getId() = " + formInfo.getId());
System.out.println("formInfo.getName() = " + formInfo.getName());
System.out.println("formInfo.getKey() = " + formInfo.getKey());
SimpleFormModel formModel = (SimpleFormModel) formInfo.getFormModel();
List fields = formModel.getFields();
for (FormField field : fields) {
System.out.println("field.getId() = " + field.getId());
System.out.println("field.getName() = " + field.getName());
System.out.println("field.getValue() = " + field.getValue());
}
}
taskService.completeTaskWithForm
来完成表单的任务
/**
* 完成任务
*/
@Test
public void completeTaskForm(){
Map map = new HashMap<>();
map.put("days","4");
map.put("startTime","20220404");
map.put("reason","出去玩玩");
String taskId = "5010";
String formDefinitionId = "2503";
String outcome = "波哥";
taskService.completeTaskWithForm(taskId,formDefinitionId,outcome,map);
}
2022-03-27T23:36:14
2022-03-27T23:36:14
这个时间之前还没有处理,那么就会触发定时边界事件,从而从人工任务3。zhangsan
的位置。public class MyOneDelegate implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) {
System.out.println("完成自动审批任务-----》MyOneDelegate" + LocalDateTime.now().toString());
// 业务执行发现有问题 此处的errorCode需要和定义的error标签中的errorCode保持一致
throw new BpmnError("abcd");
}
}
/**
* 通过信号发送来触发信号启动事件的执行
* 全局的信息
*/
@Test
void signalGolbal() throws Exception {
runtimeService.signalEventReceived("secondSingal");
// 我们得保证容器的运行,所以需要阻塞
TimeUnit.MINUTES.sleep(1);
}
@Test
public void signalGlobal() throws Exception{
String signal = "signal2";
Map variables = new HashMap();
processEngine.getRuntimeService().signalEventReceived(signal,variables);
}
public class MyOneDelegate implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) {
System.out.println("微信支付-----》MyOneDelegate" + LocalDateTime.now().toString());
System.out.println("余额不足....");
throw new BpmnError("payFail");
}
}