Alterar manualmente a tarefa ao executar a instância do processo
-
21-12-2019 - |
Pergunta
para desenvolver um aplicativo BPM personalizado, há um recurso que usamos com outro fornecedor de mecanismo de BPM e também gostamos de usá-lo com camunda.A funcionalidade direcionada trata de configurar/redefinir instâncias de processo em execução para uma tarefa especificada diferente da ativa no momento.Da nossa perspectiva, é necessário quando, por exemplo:
- criação de instâncias de processo devido à migração de versão de processo
- resolver incidentes
- resolver o uso acidentalmente errado por um usuário
Por fim, não encontrei uma função simples para fazer isso, mas desenvolvi um código personalizado que funcionava com algumas limitações.Existem algumas fraquezas e incertezas neste código, de modo que Eu tenho a seguinte pergunta:
Perdi uma maneira alternativa de conseguir isso ou a abordagem a seguir está correta ou é totalmente sem suporte no momento?
Os pontos fracos atuais:
- primeiro e mais importante: nenhuma instância de tarefa histórica é armazenada.Isso faz com que não seja rastreável quem ou mesmo quando a tarefa foi acionada/ativada/iniciada.Encontrei a seguinte postagem no grupo camunda google (publicar) que diz que está correto neste momento, porque é uma tarefa fora do escopo da definição de processo, mas usando uma definição de tarefa da definição de processo subjacente, eu deveria estar "no escopo"?!
- o código é baseado na implementação interna e não na interface oficial
- Nesse ponto
- Algumas peças como a análise de expressões da definição de tarefas falharam (consulte o código comentado), mas isso pode ser causado por uso errado
Aqui está o código (trecho experimental da nossa fachada de serviço camunda):
@Inject
protected HistoryService histService;
@Inject
protected TaskService taskService;
@Inject
protected ManagementService managementService;
@Inject
protected RuntimeService runtimeService;
@Inject
protected IdentityService identityService;
@Inject
protected RepositoryService repositoryService;
@Inject
protected FormService formService;
@Inject
protected ProcessEngine processEngine;
public void startTask(String processInstanceId, String taskKey) {
Collection<TaskDefinition> taskDefs = getAvailableTasks(
processInstanceId);
TaskEntity newTask = null;
TaskDefinition taskDef = null;
for (TaskDefinition taskDefinition : taskDefs) {
if (taskDefinition.getKey().equals(taskKey)) {
taskDef = taskDefinition;
break;
}
}
boolean taskDefExists = taskDef != null;
List<Task> runningTasksByKey = getTasksByKey(taskKey, processInstanceId);
boolean taskIsAlreadyRunning = runningTasksByKey != null
&& runningTasksByKey.size() > 0;
if (taskDefExists && !taskIsAlreadyRunning) {
newTask = (TaskEntity) taskService.newTask();
ProcessInstance procInst = getProcessInstance(processInstanceId);
ExecutionEntity procInstEntity = (ExecutionEntity) procInst;
String taskName = (String) taskDef.getNameExpression().
getExpressionText();
// String taskAssigne = (String) taskDef.getAssigneeExpression().
// getValue(
// procInstEntity);
// newTask.setAssignee(taskAssigne);
newTask.setTaskDefinitionKey(taskDef.getKey());
newTask.setProcessInstance(procInstEntity);
newTask.setTaskDefinition(taskDef);
newTask.setName(taskName);
newTask.setProcessInstanceId(processInstanceId);
newTask.setProcessDefinitionId(procInstEntity.
getProcessDefinitionId());
taskService.saveTask(newTask);
TaskServiceImpl taskServiceImpl = (TaskServiceImpl) BpmPlatform.
getProcessEngineService().getDefaultProcessEngine().
getTaskService();
CommandExecutor commandExecutor = taskServiceImpl.
getCommandExecutor();
ExecutionEntity executionEntity = commandExecutor.execute(
new SaveTaskActivityInstanceCmd(newTask,
procInstEntity));
// commandExecutor.execute(new `SaveTaskHistoricActivityInstanceCmd(executionEntity, newTask));`
}
}
public Collection<TaskDefinition> getAvailableTasks(String processInstanceId) {
Map<String, TaskDefinition> taskDefs = null;
Collection<TaskDefinition> taskDefObjects = null;
if (processInstanceId != null) {
ProcessInstanceQuery procInstQuery = runtimeService.
createProcessInstanceQuery().processInstanceId(
processInstanceId);
ProcessDefinitionEntity procDefEntity = getProcessDefinitionEager(
processInstanceId);
taskDefs = procDefEntity.getTaskDefinitions();
}
taskDefObjects = (Collection<TaskDefinition>) (taskDefs != null ? taskDefs.
values() : new ArrayList<TaskDefinition>());
return taskDefObjects;
}
public ProcessDefinitionEntity getProcessDefinitionEager(
String processInstanceId) {
ProcessInstanceQuery procInstQuery = runtimeService.
createProcessInstanceQuery().processInstanceId(
processInstanceId);
ProcessInstance procInst = procInstQuery.singleResult();
String procDefId = procInst.getProcessDefinitionId();
return (ProcessDefinitionEntity) repositoryService.getProcessDefinition(
procDefId);
}
public List<Task> getTasksByKey(String taskKey, String processInstanceId) {
List<Task> tasks = taskService.createTaskQuery().processInstanceId(
processInstanceId).taskDefinitionKey(taskKey).list();
return tasks;
}
public class SaveTaskActivityInstanceCmd implements Command<ExecutionEntity>,
Serializable {
private TaskEntity newTask;
private ExecutionEntity procInstEntity;
public SaveTaskActivityInstanceCmd(TaskEntity newTaskInit,
ExecutionEntity procInstEntityInit) {
this.newTask = newTaskInit;
this.procInstEntity = procInstEntityInit;
}
public ExecutionEntity execute(CommandContext commandContext) {
ActivityImpl actImpl = new ActivityImpl(newTask.
getTaskDefinitionKey(),
procInstEntity.getProcessDefinition());
actImpl.setActivityBehavior(new UserTaskActivityBehavior(
new CdiExpressionManager(), newTask.getTaskDefinition()));
ExecutionEntity execEntity = new ExecutionEntity();
execEntity.setActivity(actImpl);
execEntity.setActivityInstanceId(newTask.getTaskDefinitionKey()
+ ":" + newTask.getId());
execEntity.setEventName(newTask.getEventName());
execEntity.setProcessDefinitionId(newTask.getProcessDefinitionId());
execEntity.setActive(true);
execEntity.setProcessInstance(procInstEntity);
commandContext.getExecutionManager().insert(execEntity);
return execEntity;
}
}
Agradeço qualquer dica ou conselho :-)
Solução
Eu não mexeria na instância do processo nesse nível, como você já percebeu, você está contornando os serviços camundas.Quando nos deparamos com um problema semelhante, optamos pelo seguinte:
- cancelar a instância do processo da versão antiga do processo
- inicie uma nova instância do processo estendido e encaminhe-o programaticamente para o estado desejado...
Outra opção:modelar um ponto de entrada (evento de início de mensagem) dentro da nova versão do processo.Então, ao invés de encaminhar programaticamente a instância para o estado desejado, basta iniciar a nova instância através do evento e passar todas as variáveis de processo da instância antiga...
Outras dicas
A partir do Camunda 7.3, você pode usar a modificação de instância de processo para iniciar qualquer atividade em um processo e cancelar qualquer instância de atividade ativa.
Exemplo:
runtimeService.createProcessInstanceModification(processInstanceId)
.startBeforeActivity("someActivityId")
.cancelActivityInstance("someActivityInstanceId")
.execute();
Ver http://docs.camunda.org/7.3/guides/user-guide/#process-engine-process-instance-modification para documentação.