use of org.flowable.common.engine.api.FlowableObjectNotFoundException in project petals-se-flowable by petalslink.
the class SuspendProcessInstancesOperation method doExecute.
@Override
public SuspendProcessInstancesResponse doExecute(final SuspendProcessInstances incomingObject) throws Exception {
final SuspendProcessInstancesResponse response = new SuspendProcessInstancesResponse();
final List<ProcessInstanceIdentifier> results = response.getProcessInstanceIdentifier();
for (final String processInstanceId : incomingObject.getProcessInstanceIdentifier()) {
this.log.fine(String.format("Suspends process instance #%s.", processInstanceId));
final ProcessInstanceIdentifier result = new ProcessInstanceIdentifier();
result.setValue(processInstanceId);
results.add(result);
try {
this.runtimeService.suspendProcessInstanceById(processInstanceId);
result.setResult(AdjournmentResult.SUSPENDED);
} catch (@SuppressWarnings("squid:S1166") final FlowableObjectNotFoundException e) {
result.setResult(AdjournmentResult.NOT_FOUND);
} catch (@SuppressWarnings("squid:S1166") final FlowableException e) {
result.setResult(AdjournmentResult.ALREADY_SUSPENDED);
}
}
return response;
}
use of org.flowable.common.engine.api.FlowableObjectNotFoundException in project RuoYi-Flowable-Plus by KonBAI-Q.
the class WfTaskServiceImpl method taskReject.
/**
* 驳回任务
*
* @param bo
*/
@Override
public void taskReject(WfTaskBo bo) {
if (taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult().isSuspended()) {
throw new RuntimeException("任务处于挂起状态");
}
// 当前任务 task
Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult();
// 获取流程定义信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
// 获取所有节点信息
Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
// 获取全部节点列表,包含子节点
Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
// 获取当前任务节点元素
FlowElement source = null;
if (allElements != null) {
for (FlowElement flowElement : allElements) {
// 类型为用户节点
if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
// 获取节点信息
source = flowElement;
}
}
}
// 目的获取所有跳转到的节点 targetIds
// 获取当前节点的所有父级用户任务节点
// 深度优先算法思想:延边迭代深入
List<UserTask> parentUserTaskList = FlowableUtils.iteratorFindParentUserTasks(source, null, null);
if (parentUserTaskList == null || parentUserTaskList.size() == 0) {
throw new RuntimeException("当前节点为初始任务节点,不能驳回");
}
// 获取活动 ID 即节点 Key
List<String> parentUserTaskKeyList = new ArrayList<>();
parentUserTaskList.forEach(item -> parentUserTaskKeyList.add(item.getId()));
// 获取全部历史节点活动实例,即已经走过的节点历史,数据采用开始时间升序
List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceStartTime().asc().list();
// 数据清洗,将回滚导致的脏数据清洗掉
List<String> lastHistoricTaskInstanceList = FlowableUtils.historicTaskInstanceClean(allElements, historicTaskInstanceList);
// 此时历史任务实例为倒序,获取最后走的节点
List<String> targetIds = new ArrayList<>();
// 循环结束标识,遇到当前目标节点的次数
int number = 0;
StringBuilder parentHistoricTaskKey = new StringBuilder();
for (String historicTaskInstanceKey : lastHistoricTaskInstanceList) {
// 当会签时候会出现特殊的,连续都是同一个节点历史数据的情况,这种时候跳过
if (parentHistoricTaskKey.toString().equals(historicTaskInstanceKey)) {
continue;
}
parentHistoricTaskKey = new StringBuilder(historicTaskInstanceKey);
if (historicTaskInstanceKey.equals(task.getTaskDefinitionKey())) {
number++;
}
// number == 2,第二次遇到,代表最后一次的循环范围
if (number == 2) {
break;
}
// 如果当前历史节点,属于父级的节点,说明最后一次经过了这个点,需要退回这个点
if (parentUserTaskKeyList.contains(historicTaskInstanceKey)) {
targetIds.add(historicTaskInstanceKey);
}
}
// 目的获取所有需要被跳转的节点 currentIds
// 取其中一个父级任务,因为后续要么存在公共网关,要么就是串行公共线路
UserTask oneUserTask = parentUserTaskList.get(0);
// 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务
List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
List<String> runTaskKeyList = new ArrayList<>();
runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
// 需驳回任务列表
List<String> currentIds = new ArrayList<>();
// 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务
List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(oneUserTask, runTaskKeyList, null, null);
currentUserTaskList.forEach(item -> currentIds.add(item.getId()));
// 规定:并行网关之前节点必须需存在唯一用户任务节点,如果出现多个任务节点,则并行网关节点默认为结束节点,原因为不考虑多对多情况
if (targetIds.size() > 1 && currentIds.size() > 1) {
throw new RuntimeException("任务出现多对多情况,无法撤回");
}
// 循环获取那些需要被撤回的节点的ID,用来设置驳回原因
List<String> currentTaskIds = new ArrayList<>();
currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
if (currentId.equals(runTask.getTaskDefinitionKey())) {
currentTaskIds.add(runTask.getId());
}
}));
// 设置驳回意见
currentTaskIds.forEach(item -> taskService.addComment(item, task.getProcessInstanceId(), FlowComment.REJECT.getType(), bo.getComment()));
try {
// 如果父级任务多于 1 个,说明当前节点不是并行节点,原因为不考虑多对多情况
if (targetIds.size() > 1) {
// 1 对 多任务跳转,currentIds 当前节点(1),targetIds 跳转到的节点(多)
runtimeService.createChangeActivityStateBuilder().processInstanceId(task.getProcessInstanceId()).moveSingleActivityIdToActivityIds(currentIds.get(0), targetIds).changeState();
}
// 如果父级任务只有一个,因此当前任务可能为网关中的任务
if (targetIds.size() == 1) {
// 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetIds.get(0) 跳转到的节点(1)
runtimeService.createChangeActivityStateBuilder().processInstanceId(task.getProcessInstanceId()).moveActivityIdsToSingleActivityId(currentIds, targetIds.get(0)).changeState();
}
} catch (FlowableObjectNotFoundException e) {
throw new RuntimeException("未找到流程实例,流程可能已发生变化");
} catch (FlowableException e) {
throw new RuntimeException("无法取消或开始活动");
}
}
use of org.flowable.common.engine.api.FlowableObjectNotFoundException in project RuoYi-Flowable-Plus by KonBAI-Q.
the class WfTaskServiceImpl method taskReturn.
/**
* 退回任务
*
* @param bo 请求实体参数
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void taskReturn(WfTaskBo bo) {
if (taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult().isSuspended()) {
throw new RuntimeException("任务处于挂起状态");
}
// 当前任务 task
Task task = taskService.createTaskQuery().taskId(bo.getTaskId()).singleResult();
// 获取流程定义信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
// 获取所有节点信息
Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
// 获取全部节点列表,包含子节点
Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
// 获取当前任务节点元素
FlowElement source = null;
// 获取跳转的节点元素
FlowElement target = null;
if (allElements != null) {
for (FlowElement flowElement : allElements) {
// 当前任务节点元素
if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
source = flowElement;
}
// 跳转的节点元素
if (flowElement.getId().equals(bo.getTargetKey())) {
target = flowElement;
}
}
}
// 从当前节点向前扫描
// 如果存在路线上不存在目标节点,说明目标节点是在网关上或非同一路线上,不可跳转
// 否则目标节点相对于当前节点,属于串行
Boolean isSequential = FlowableUtils.iteratorCheckSequentialReferTarget(source, bo.getTargetKey(), null, null);
if (!isSequential) {
throw new RuntimeException("当前节点相对于目标节点,不属于串行关系,无法回退");
}
// 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务
List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
List<String> runTaskKeyList = new ArrayList<>();
runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
// 需退回任务列表
List<String> currentIds = new ArrayList<>();
// 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务
List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(target, runTaskKeyList, null, null);
currentUserTaskList.forEach(item -> currentIds.add(item.getId()));
// 循环获取那些需要被撤回的节点的ID,用来设置驳回原因
List<String> currentTaskIds = new ArrayList<>();
currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
if (currentId.equals(runTask.getTaskDefinitionKey())) {
currentTaskIds.add(runTask.getId());
}
}));
// 设置回退意见
for (String currentTaskId : currentTaskIds) {
taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getType(), bo.getComment());
}
try {
// 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetKey 跳转到的节点(1)
runtimeService.createChangeActivityStateBuilder().processInstanceId(task.getProcessInstanceId()).moveActivityIdsToSingleActivityId(currentIds, bo.getTargetKey()).changeState();
} catch (FlowableObjectNotFoundException e) {
throw new RuntimeException("未找到流程实例,流程可能已发生变化");
} catch (FlowableException e) {
throw new RuntimeException("无法取消或开始活动");
}
}
use of org.flowable.common.engine.api.FlowableObjectNotFoundException in project ox-data-cloud by ox-data.
the class BackUserTaskCmd method execute.
@Override
public String execute(CommandContext commandContext) {
if (targetActivityId == null || targetActivityId.length() == 0) {
throw new FlowableException("TargetActivityId cannot be empty");
}
// / TaskEntity task = CommandContextUtil.getTaskService().getTask(taskId);
// / v6.5.1.28
TaskEntity task = CommandContextUtil.getProcessEngineConfiguration().getTaskServiceConfiguration().getTaskService().getTask(taskId);
if (task == null) {
throw new FlowableObjectNotFoundException("task " + taskId + " doesn't exist", Task.class);
}
String sourceActivityId = task.getTaskDefinitionKey();
String processInstanceId = task.getProcessInstanceId();
String processDefinitionId = task.getProcessDefinitionId();
Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);
FlowNode sourceFlowElement = (FlowNode) process.getFlowElement(sourceActivityId, true);
// 只支持从用户任务退回
if (!(sourceFlowElement instanceof UserTask)) {
throw new FlowableException("Task with id:" + taskId + " is not a UserTask");
}
FlowNode targetFlowElement = (FlowNode) process.getFlowElement(targetActivityId, true);
// 退回节点到当前节点不可达到,不允许退回
if (!FlowableUtils.isReachable(process, targetFlowElement, sourceFlowElement)) {
throw new FlowableException("Cannot back to [" + targetActivityId + "]");
}
// ps:目标节点如果相对当前节点是在子流程内部,则无法直接退回,目前处理是只能退回到子流程开始节点
String[] sourceAndTargetRealActivityId = FlowableUtils.getSourceAndTargetRealActivityId(sourceFlowElement, targetFlowElement);
// 实际应操作的当前节点ID
String sourceRealActivityId = sourceAndTargetRealActivityId[0];
// 实际应操作的目标节点ID
String targetRealActivityId = sourceAndTargetRealActivityId[1];
Map<String, Set<String>> specialGatewayNodes = FlowableUtils.getSpecialGatewayElements(process);
// 当前节点处在的并行网关list
List<String> sourceInSpecialGatewayList = new ArrayList<>();
// 目标节点处在的并行网关list
List<String> targetInSpecialGatewayList = new ArrayList<>();
setSpecialGatewayList(sourceRealActivityId, targetRealActivityId, specialGatewayNodes, sourceInSpecialGatewayList, targetInSpecialGatewayList);
// 实际应筛选的节点ID
Set<String> sourceRealAcitivtyIds = null;
// 若退回目标节点相对当前节点在并行网关中,则要找到相对当前节点最近的这个并行网关,后续做特殊处理
String targetRealSpecialGateway = null;
// 1.目标节点和当前节点都不在并行网关中
if (targetInSpecialGatewayList.isEmpty() && sourceInSpecialGatewayList.isEmpty()) {
sourceRealAcitivtyIds = Sets.newHashSet(sourceRealActivityId);
} else // 2.目标节点不在并行网关中、当前节点在并行网关中
if (targetInSpecialGatewayList.isEmpty() && !sourceInSpecialGatewayList.isEmpty()) {
sourceRealAcitivtyIds = specialGatewayNodes.get(sourceInSpecialGatewayList.get(0));
} else // 3.目标节点在并行网关中、当前节点不在并行网关中
if (!targetInSpecialGatewayList.isEmpty() && sourceInSpecialGatewayList.isEmpty()) {
sourceRealAcitivtyIds = Sets.newHashSet(sourceRealActivityId);
targetRealSpecialGateway = targetInSpecialGatewayList.get(0);
} else // 4.目标节点和当前节点都在并行网关中
{
int diffSpecialGatewayLevel = FlowableUtils.getDiffLevel(sourceInSpecialGatewayList, targetInSpecialGatewayList);
// 在并行网关同一层且在同一分支
if (diffSpecialGatewayLevel == -1) {
sourceRealAcitivtyIds = Sets.newHashSet(sourceRealActivityId);
} else {
// 只筛选当前节点的execution
if (sourceInSpecialGatewayList.size() == diffSpecialGatewayLevel) {
sourceRealAcitivtyIds = Sets.newHashSet(sourceRealActivityId);
} else // 当前节点相对目标节点在并行网关内,应筛选相对目标节点最近的并行网关的所有节点的execution
{
sourceRealAcitivtyIds = specialGatewayNodes.get(sourceInSpecialGatewayList.get(diffSpecialGatewayLevel));
}
// 不做处理
if (targetInSpecialGatewayList.size() == diffSpecialGatewayLevel) {
} else // 目标节点相对当前节点在并行网关内
{
targetRealSpecialGateway = targetInSpecialGatewayList.get(diffSpecialGatewayLevel);
}
}
}
// 筛选需要处理的execution
List<ExecutionEntity> realExecutions = this.getRealExecutions(commandContext, processInstanceId, task.getExecutionId(), sourceRealActivityId, sourceRealAcitivtyIds);
// 执行退回,直接跳转到实际的 targetRealActivityId
List<String> realExecutionIds = realExecutions.stream().map(ExecutionEntity::getId).collect(Collectors.toList());
runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).moveExecutionsToSingleActivityId(realExecutionIds, targetRealActivityId).changeState();
// 目标节点相对当前节点处于并行网关内,需要特殊处理,需要手动生成并行网关汇聚节点(_end)的execution数据
if (targetRealSpecialGateway != null) {
createTargetInSpecialGatewayEndExecutions(commandContext, realExecutions, process, targetInSpecialGatewayList, targetRealSpecialGateway);
}
return targetRealActivityId;
}
use of org.flowable.common.engine.api.FlowableObjectNotFoundException in project ox-data-cloud by ox-data.
the class DeployModelCmd method execute.
@Override
public Deployment execute(CommandContext commandContext) {
RepositoryService repositoryService = CommandContextUtil.getProcessEngineConfiguration(commandContext).getRepositoryService();
Model model = repositoryService.getModel(modelId);
if (model == null) {
throw new FlowableObjectNotFoundException("Could not find a model with id '" + modelId + "'.", Model.class);
}
if (model.getDeploymentId() != null && model.getDeploymentId().length() > 0) {
throw new FlowableException("The model is already deployed");
}
if (!model.hasEditorSource()) {
throw new FlowableObjectNotFoundException("Model with id '" + modelId + "' does not have source " + "available" + ".", String.class);
}
byte[] bpmnBytes = CommandContextUtil.getProcessEngineConfiguration(commandContext).getModelEntityManager().findEditorSourceByModelId(modelId);
if (bpmnBytes == null) {
throw new FlowableObjectNotFoundException("Model with id '" + modelId + "' does not have source " + "available" + ".", String.class);
}
try {
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
String fileName = model.getId() + ".bpmn20.xml";
ByteArrayInputStream bis = new ByteArrayInputStream(bpmnBytes);
deploymentBuilder.addInputStream(fileName, bis);
deploymentBuilder.name(fileName);
deploymentBuilder.category(model.getCategory());
XMLInputFactory xif = XMLInputFactory.newInstance();
InputStreamReader xmlIn = new InputStreamReader(new ByteArrayInputStream(bpmnBytes), "UTF-8");
XMLStreamReader xtr = xif.createXMLStreamReader(xmlIn);
BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);
org.flowable.bpmn.model.Process process = bpmnModel.getMainProcess();
Collection<FlowElement> flowElements = process.getFlowElements();
Map<String, String> formKeyMap = new HashMap<String, String>(16);
for (FlowElement flowElement : flowElements) {
String formKey = null;
if (flowElement instanceof StartEvent) {
StartEvent startEvent = (StartEvent) flowElement;
if (startEvent.getFormKey() != null && startEvent.getFormKey().length() > 0) {
formKey = startEvent.getFormKey();
}
} else if (flowElement instanceof UserTask) {
UserTask userTask = (UserTask) flowElement;
if (userTask.getFormKey() != null && userTask.getFormKey().length() > 0) {
formKey = userTask.getFormKey();
}
}
if (formKey != null && formKey.length() > 0) {
if (formKeyMap.containsKey(formKey)) {
continue;
} else {
String formKeyDefinition = formKey.replace(".form", "");
FlowableFormService flowableFormService = SpringContextUtils.getBean(FlowableFormService.class);
FlowableForm form = flowableFormService.getById(formKeyDefinition);
if (form != null && form.getFormJson() != null && form.getFormJson().length() > 0) {
byte[] formJson = form.getFormJson().getBytes("UTF-8");
ByteArrayInputStream bi = new ByteArrayInputStream(formJson);
deploymentBuilder.addInputStream(formKey, bi);
formKeyMap.put(formKey, formKey);
} else {
throw new FlowableObjectNotFoundException("Cannot find formJson with formKey " + formKeyDefinition);
}
}
}
}
if (model.getTenantId() != null) {
deploymentBuilder.tenantId(model.getTenantId());
}
Deployment deployment = deploymentBuilder.deploy();
if (deployment != null) {
model.setDeploymentId(deployment.getId());
}
return deployment;
} catch (Exception e) {
if (e instanceof FlowableException) {
throw (FlowableException) e;
}
throw new FlowableException(e.getMessage(), e);
}
}
Aggregations