Activiti ワークフロー エンジンを Spring Boot アプリケーションに統合するには、通常、次の手順が必要です。
次の依存関係を pom.xml ファイルに追加します。
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
データソースを設定します。例えば:
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useSSL=false&autoReconnect=true&serverTimezone=Asia/Shanghai
username: root
password: 123456
Activiti を構成します。例:
activiti:
database-schema-update: true
database-reduce-time-to-live: true
async-executor-activate: true
history-level: full
check-process-definitions: true
process-definitions:
deploy-resources: classpath*:/processes/*.bpmn20.xml
allow-multiple: true
id-generator: org.activiti.engine.impl.persistence.StrongUuidGenerator
jdbc-batch-processing: true
job-execution:
activate: true
max-jobs-per-acquisition: 5
wait-time-in-millis: 5000
mail:
enabled: false
BPMN ファイルをロードし、プロセス定義をデプロイします。例:
@PostConstruct
private void initProcessDefinitions() {
final Set<String> deploymentResourceNames = resourceResolver.getResourcesAsStream("/processes/*.bpmn20.xml")
.map(resource -> resource.getFilename())
.collect(Collectors.toSet());
deploymentResourceNames.forEach(resourceName -> {
final String processDefinitionId = repositoryService.createDeployment()
.addClasspathResource("processes/" + resourceName)
.name(resourceName)
.deploy()
.getId();
log.info("ProcessDefinition <{}> deployed with id: <{}>", resourceName, processDefinitionId);
});
}
Activiti 関連のサービス コードを作成します。例:
@Service
public class MyWorkflowService {
private final ProcessEngine processEngine;
@Autowired
public MyWorkflowService(final ProcessEngine processEngine) {
this.processEngine = processEngine;
}
public Execution startWorkflow() {
return processEngine.getRuntimeService().startProcessInstanceByKey("myProcessKey");
}
public List<Task> getTasksByUser(final String user) {
return processEngine.getTaskService().createTaskQuery()
.taskAssignee(user)
.list();
}
public void completeTask(final String taskId) {
processEngine.getTaskService().complete(taskId);
}
}
Activiti は、大規模で複雑なビジネス プロセスにより適しています。
Activiti ワークフロー エンジンでは、タスクを拒否する具体的な実装は異なる場合がありますが、通常は次の 2 つのソリューションを使用できます。
履歴タスクの再起動: 現在のタスクの実行履歴をプロセス インスタンスに再インポートし、プロセスを再起動します。これは次のコードで実現できます。
TaskEntity currentTask = (TaskEntity) taskService.createTaskQuery()
.taskId(taskId)
.singleResult();
String processInstanceId = currentTask.getProcessInstanceId();
HistoricTaskInstanceEntity historicTask = (HistoricTaskInstanceEntity) historyService.createHistoricTaskInstanceQuery()
.processInstanceId(processInstanceId)
.taskId(taskId)
.singleResult();
List<HistoricTaskInstanceEntity> toRollbackTasks = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(processInstanceId)
.taskDefinitionKey(historicTask.getTaskDefinitionKey())
.orderByTaskCreateTime()
.asc()
.list();
String activityId = toRollbackTasks.get(0).getTaskDefinitionKey();
runtimeService.createProcessInstanceModification(processInstanceId)
.cancelAllForActivity(activityId)
.startBeforeActivity(activityId)
.processInstanceVariable("taskRejectReason", rejectReason)
.execute(true, true);
前のタスク ノードに転送: 現在のタスクを前のタスク ノードに転送し、現在のタスクの承認ステータスを拒否に設定します。これは次のコードで実現できます。
Task currentTask = taskService.createTaskQuery()
.taskId(taskId)
.singleResult();
String currentActivityId = currentTask.getTaskDefinitionKey();
List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(currentTask.getProcessInstanceId())
.activityType("userTask")
.finished()
.orderByHistoricActivityInstanceEndTime()
.desc()
.list();
if (historicActivityInstances.size() > 1) {
String previousActivityId = historicActivityInstances.get(0).getActivityId();
taskService.addComment(taskId, processInsId, comment);
taskService.complete(taskId, Map.of("status", "rejected", "destination", previousActivityId));
}
ここで提供するコードは単なるサンプルコードであり、具体的な実装プロセスや詳細は異なる場合があることに注意してください。開発者は、実際の状況に応じて対応する修正や調整を行う必要があります。同時に、拒否操作は通常のワークフローの流れに影響を与える可能性があるため、実際の運用では注意が必要です。