Activiti 6.0 通过程序脚本动态设置用户任务usertask的超时时长duration解决方案

原文链接: https://my.oschina.net/u/3706162/blog/1785834

项目使用springboot + spring cloud + activiti 6.0.0 实现动态工作流引擎,遇到了节点超时时长可以通过js脚本方式设置的需求。

实现思路方案

1. 沿用activiti的asyncexecutor任务调度,不采用quartz等其他方案。使用Activiti bpmn的timer boundry event。

2. activiti流程定义bpmn中task上定义timer boundry event,此处event的id为${timerBoundryId}

3. 在任务usertask的documentation中设置{"timerBoundryId":"${timerBoundryId}","script":"if(true){return 60;}"}

4. activiti执行到task后,将task上的timer全部删掉,然后再通过程序读取task上documentation设置,执行js脚本获取到duration时长

5. 因为activiti没有开放创建timers的api,所以通过实现org.activiti.engine.impl.interceptor.Command接口类CreateTimerCmd在act_ru_timers表中创建timer记录。

--------------

代码部分

删除task上全部timers的代码

private void clearTimerJobs(String processId, List newTasks) {
		newTasks.forEach(item->{
			List executions = runtimeService.createExecutionQuery()
					.processInstanceId(processId).parentId(item.getExecutionId()).list();
			executions.forEach(exec -> {
				List timeJobs = managementService.createTimerJobQuery().processInstanceId(processId)
						.executionId(exec.getId()).list();
				if(!timeJobs.isEmpty()){
					// delete execution
					timeJobs.forEach(job->{
						managementService.deleteTimerJob(job.getId());
					});
					CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
					commandExecutor.execute(new DeleteExecutionCmd(exec.getId()));
				}
			});
		});
	}

DeleteExecutionCmd.java

import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.task.Comment;

public class DeleteExecutionCmd implements Command {
	protected String executorId;

	public DeleteExecutionCmd(String executorId) {
		this.executorId = executorId;
	}

	@Override
	public Comment execute(CommandContext commandContext) {
		commandContext.getExecutionEntityManager().delete(executorId);
		return null;
	}
}

CreateTimerCmd.java

import org.activiti.bpmn.model.BoundaryEvent;
import org.activiti.bpmn.model.TimerEventDefinition;
import org.activiti.engine.impl.asyncexecutor.JobManager;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.jobexecutor.TimerEventHandler;
import org.activiti.engine.impl.jobexecutor.TriggerTimerEventJobHandler;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.persistence.entity.TimerJobEntity;
import org.activiti.engine.task.Comment;

public class CreateTimerCmd implements Command {
	protected String duration;
	protected String taskId;
	protected BoundaryEvent timerBoundaryEvent;

	public CreateTimerCmd(BoundaryEvent timerBoundaryEvent, String taskId , String duration) {
		this.taskId = taskId;
		this.duration = duration;
		this.timerBoundaryEvent = timerBoundaryEvent;
	}

	/**
	 * 创建timer job
	 * 需要为当前task的execution上创建child execution,并且创建timer job,并且将execution绑定到timerboudryevent上
	 */
	public Comment execute(CommandContext commandContext) {
		TaskEntity task = commandContext.getTaskEntityManager().findById(taskId);
		ExecutionEntity execution = commandContext.getExecutionEntityManager().findById(task.getExecutionId());
		
		ExecutionEntity childExecutionEntity = commandContext.getExecutionEntityManager().createChildExecution((ExecutionEntity) execution);
	    childExecutionEntity.setParentId(execution.getId());
	    childExecutionEntity.setCurrentFlowElement(timerBoundaryEvent);
	    childExecutionEntity.setScope(false);
		
		JobManager jobManager = Context.getCommandContext().getJobManager();
	    TimerEventDefinition timerEventDefinition = new TimerEventDefinition();
	    timerEventDefinition.setTimeDuration(duration);
	    
		TimerJobEntity timerJob = jobManager.createTimerJob(timerEventDefinition, false, childExecutionEntity, TriggerTimerEventJobHandler.TYPE,
	        TimerEventHandler.createConfiguration(childExecutionEntity.getCurrentActivityId(), timerEventDefinition.getEndDate(), timerEventDefinition.getCalendarName()));
	    if (timerJob != null) {
	      jobManager.scheduleTimerJob(timerJob);
	    }
		return null;
	}
}

执行CreateTimerCommand的方法

@Transactional
	public void addTimerToTask(String taskId, String timerBoudryElementId,float duration) {
		TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
		BpmnModel model = repositoryService.getBpmnModel(task.getProcessDefinitionId());
		if (model.getProcesses() != null && model.getProcesses().size() > 0) {
			// 从模型上获取到当前的task节点
			BoundaryEvent timerBoudry = (BoundaryEvent)model.getProcesses().get(0).getFlowElement(timerBoudryElementId, true);
			CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
			commandExecutor.execute(new CreateTimerCmd(timerBoudry, taskId, "PT"+(int)(duration*60)+"M"));
			logger.info("创建timer成功,任务Id:"+taskId +" timerBoudryElementId:"+timerBoudryElementId+" duration:"+"PT"+(int)(duration*60)+"M");
		}
	}

其中taskId是任务id,timerBoundryElementId是task documentation中的${timerBoundryId}, duration则通过js解析获取。

------

网上Activiti 6.0.0的此类实现比较少,故分享出来,如果有更好实现,望各位老师分享。

转载于:https://my.oschina.net/u/3706162/blog/1785834

你可能感兴趣的:(Activiti 6.0 通过程序脚本动态设置用户任务usertask的超时时长duration解决方案)