我们之前已经看了流程定义列表页面process-list.jsp和运行流程列表页面running-manage.jsp,这两个页面都有激活和挂起,那么有什么不同呢?
首先是流程定义挂起的url
http://localhost:8080/kft-activiti-demo-no-maven/workflow/processdefinition/update/suspend/leave:1:20
其次是流程实例挂起的url
http://localhost:8080/kft-activiti-demo-no-maven/workflow/processinstance/update/suspend/14
从现象上看,当流程定义激活或者挂起时,对应的流程运行实例的suspended状态会跟着改变;
当流程运行实例激活或者挂起时,对应的流程定义的suspended状态不会跟着改变。
一、流程定义的激活、挂起
ActivitiController中:
/**
* 挂起、激活流程定义
*/
@RequestMapping(value = "processdefinition/update/{state}/{processDefinitionId}")
public String updateState(@PathVariable("state") String state, @PathVariable("processDefinitionId") String processDefinitionId,
RedirectAttributes redirectAttributes) {
if (state.equals("active")) {
redirectAttributes.addFlashAttribute("message", "已激活ID为[" + processDefinitionId + "]的流程定义。");
repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
} else if (state.equals("suspend")) {
repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null);
redirectAttributes.addFlashAttribute("message", "已挂起ID为[" + processDefinitionId + "]的流程定义。");
}
return "redirect:/workflow/process-list";
}
请注意suspendProcessDefinitionById和activateProcessDefinitionById方法的第二个参数,我们来看一下RepositoryServiceImpl中这个方法的定义:
public void suspendProcessDefinitionById(String processDefinitionId, boolean suspendProcessInstances, Date suspensionDate) {
this.commandExecutor.execute(new SuspendProcessDefinitionCmd(processDefinitionId, null, suspendProcessInstances, suspensionDate, null));
}
原来它就是用来控制在挂起流程定义时,是否同时挂起对应的流程实例。
public class SuspendProcessDefinitionCmd extends AbstractSetProcessDefinitionStateCmd
{
public SuspendProcessDefinitionCmd(String processDefinitionId, String processDefinitionKey, boolean suspendProcessInstances, Date suspensionDate, String tenantId)
{
super(processDefinitionId, processDefinitionKey, suspendProcessInstances, suspensionDate, tenantId);
}
}
public abstract class AbstractSetProcessDefinitionStateCmd
implements Command<Void>
{
public AbstractSetProcessDefinitionStateCmd(String processDefinitionId, String processDefinitionKey, boolean includeProcessInstances, Date executionDate, String tenantId)
{
this.processDefinitionId = processDefinitionId;
this.processDefinitionKey = processDefinitionKey;
this.includeProcessInstances = includeProcessInstances;
this.executionDate = executionDate;
this.tenantId = tenantId;
}
public Void execute(CommandContext commandContext)
{
List processDefinitions = findProcessDefinition(commandContext);
if (this.executionDate != null)
createTimerForDelayedExecution(commandContext, processDefinitions);
else {
changeProcessDefinitionState(commandContext, processDefinitions);
}
return null;
}
protected void changeProcessDefinitionState(CommandContext commandContext, List<ProcessDefinitionEntity> processDefinitions) {
for (ProcessDefinitionEntity processDefinition : processDefinitions)
{
SuspensionState.SuspensionStateUtil.setSuspensionState(processDefinition, getProcessDefinitionSuspensionState());
commandContext.getProcessEngineConfiguration().getDeploymentManager().getProcessDefinitionCache().remove(processDefinition.getId());
if (this.includeProcessInstances)
{
int currentStartIndex = 0;
List processInstances = fetchProcessInstancesPage(commandContext, processDefinition, currentStartIndex);
while (processInstances.size() > 0)
{
for (ProcessInstance processInstance : processInstances) {
AbstractSetProcessInstanceStateCmd processInstanceCmd = getProcessInstanceChangeStateCmd(processInstance);
processInstanceCmd.execute(commandContext);
}
currentStartIndex += processInstances.size();
processInstances = fetchProcessInstancesPage(commandContext, processDefinition, currentStartIndex);
}
}
}
}
}
activateProcessDefinitionById调用层次类似,不重复。
二、流程实例的激活、挂起
ProcessInstanceController中:
/**
* 挂起、激活流程实例
*/
@RequestMapping(value = "update/{state}/{processInstanceId}")
public String updateState(@PathVariable("state") String state, @PathVariable("processInstanceId") String processInstanceId,
RedirectAttributes redirectAttributes) {
if (state.equals("active")) {
redirectAttributes.addFlashAttribute("message", "已激活ID为[" + processInstanceId + "]的流程实例。");
runtimeService.activateProcessInstanceById(processInstanceId);
} else if (state.equals("suspend")) {
runtimeService.suspendProcessInstanceById(processInstanceId);
redirectAttributes.addFlashAttribute("message", "已挂起ID为[" + processInstanceId + "]的流程实例。");
}
return "redirect:/workflow/processinstance/running";
}
这个就暂时没有过多介绍了,就看一下RuntimeServiceImpl中的实现
public void suspendProcessInstanceById(String processInstanceId) {
this.commandExecutor.execute(new SuspendProcessInstanceCmd(processInstanceId));
}
public void activateProcessInstanceById(String processInstanceId) {
this.commandExecutor.execute(new ActivateProcessInstanceCmd(processInstanceId));
}
public class SuspendProcessInstanceCmd extends AbstractSetProcessInstanceStateCmd
{
public SuspendProcessInstanceCmd(String executionId)
{
super(executionId);
}
}
public abstract class AbstractSetProcessInstanceStateCmd
implements Command<Void>
{
protected final String executionId;
public AbstractSetProcessInstanceStateCmd(String executionId)
{
this.executionId = executionId;
}
public Void execute(CommandContext commandContext)
{
if (this.executionId == null) {
throw new ActivitiIllegalArgumentException("ProcessInstanceId cannot be null.");
}
ExecutionEntity executionEntity = commandContext.getExecutionEntityManager().findExecutionById(this.executionId);
if (executionEntity == null) {
throw new ActivitiObjectNotFoundException("Cannot find processInstance for id '" + this.executionId + "'.", Execution.class);
}
if (!executionEntity.isProcessInstanceType()) {
throw new ActivitiException("Cannot set suspension state for execution '" + this.executionId + "': not a process instance.");
}
SuspensionState.SuspensionStateUtil.setSuspensionState(executionEntity, getNewState());
List childExecutions = commandContext.getExecutionEntityManager().findChildExecutionsByProcessInstanceId(this.executionId);
for (ExecutionEntity childExecution : childExecutions) {
if (!childExecution.getId().equals(this.executionId)) {
SuspensionState.SuspensionStateUtil.setSuspensionState(childExecution, getNewState());
}
}
List tasks = commandContext.getTaskEntityManager().findTasksByProcessInstanceId(this.executionId);
for (TaskEntity taskEntity : tasks) {
SuspensionState.SuspensionStateUtil.setSuspensionState(taskEntity, getNewState());
}
return null;
}
protected abstract SuspensionState getNewState();
}