58d0c6d37432cdf13b848c22319f40d50a159f6f
[so.git] /
1 package org.onap.so.bpmn.common.workflow.service;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import org.camunda.bpm.engine.ProcessEngine;
6 import org.camunda.bpm.engine.RepositoryService;
7 import org.camunda.bpm.engine.RuntimeService;
8 import org.camunda.bpm.engine.migration.MigrationInstruction;
9 import org.camunda.bpm.engine.migration.MigrationPlan;
10 import org.camunda.bpm.engine.migration.MigrationPlanExecutionBuilder;
11 import org.camunda.bpm.engine.repository.ProcessDefinition;
12 import org.camunda.bpm.engine.runtime.ProcessInstance;
13 import org.camunda.bpm.engine.runtime.ProcessInstanceQuery;
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16 import org.springframework.beans.factory.annotation.Autowired;
17 import org.springframework.beans.factory.annotation.Value;
18 import org.springframework.boot.context.event.ApplicationReadyEvent;
19 import org.springframework.context.event.EventListener;
20 import org.springframework.core.env.Environment;
21 import org.springframework.stereotype.Service;
22
23 @Service
24 public class AutoProcessInstanceMigrationService {
25
26     private static Logger logger = LoggerFactory.getLogger(AutoProcessInstanceMigrationService.class);
27
28     @Autowired
29     private Environment env;
30     @Autowired
31     protected ProcessEngine processEngine;
32
33     @Value("${migration.autoMigrationEnabled:false}")
34     private boolean autoMigrationEnabled;
35
36     private RuntimeService runtimeService;
37     private RepositoryService repositoryService;
38     private List<String> processDefinitionKeys;
39
40     @EventListener(ApplicationReadyEvent.class)
41     protected void executeAutoProcessInstanceMigrations() {
42         if (autoMigrationEnabled) {
43             runtimeService = processEngine.getRuntimeService();
44             repositoryService = processEngine.getRepositoryService();
45             for (ProcessDefinition definition : getProcessDefinitions()) {
46                 for (ProcessDefinition procDefOld : getOldProcessDefinitions(definition.getKey(),
47                         definition.getVersion())) {
48                     migrate(procDefOld.getId(), definition.getId());
49                 }
50             }
51         }
52     }
53
54     protected List<ProcessDefinition> getProcessDefinitions() {
55
56         List<ProcessDefinition> processDefinitions = new ArrayList<ProcessDefinition>();
57         processDefinitionKeys = env.getProperty("migration.processDefinitionKeys", List.class, new ArrayList<String>());
58         for (String key : processDefinitionKeys) {
59             processDefinitions.add(repositoryService.createProcessDefinitionQuery().processDefinitionKey(key)
60                     .latestVersion().singleResult());
61         }
62         return processDefinitions;
63     }
64
65     private void migrate(String sourceProcessDefinitionId, String targetProcessDefinitionId) {
66         MigrationPlan migrationPlan =
67                 runtimeService.createMigrationPlan(sourceProcessDefinitionId, targetProcessDefinitionId)
68                         .mapEqualActivities().updateEventTriggers().build();
69         List<String> activityIds = new ArrayList<>();
70
71         for (MigrationInstruction instruction : migrationPlan.getInstructions()) {
72             activityIds.add(instruction.getSourceActivityId());
73         }
74         for (String activityId : activityIds) {
75             ProcessInstanceQuery activeProcessInstancesQuery = runtimeService.createProcessInstanceQuery()
76                     .processDefinitionId(sourceProcessDefinitionId).activityIdIn(activityId).active();
77             if (!activeProcessInstancesQuery.list().isEmpty()) {
78                 logger.info("Migrating {} process instance(s) from {} to {}",
79                         Long.valueOf(activeProcessInstancesQuery.count()), sourceProcessDefinitionId,
80                         targetProcessDefinitionId);
81                 MigrationPlanExecutionBuilder migration =
82                         runtimeService.newMigration(migrationPlan).processInstanceQuery(activeProcessInstancesQuery);
83                 migration.executeAsync();
84             }
85         }
86         suspendEmptyProcessDefinition(sourceProcessDefinitionId);
87     }
88
89     private void suspendEmptyProcessDefinition(String sourceProcessDefinitionId) {
90         List<ProcessInstance> activeProcessInstances = runtimeService.createProcessInstanceQuery()
91                 .processDefinitionId(sourceProcessDefinitionId).active().list();
92         if (activeProcessInstances.isEmpty()) {
93             repositoryService.suspendProcessDefinitionById(sourceProcessDefinitionId);
94         } else {
95             logger.info("Unable to migrate {} process instance(s) from {}",
96                     Integer.valueOf(activeProcessInstances.size()), sourceProcessDefinitionId);
97         }
98     }
99
100     protected List<ProcessDefinition> getOldProcessDefinitions(String key, int version) {
101         List<ProcessDefinition> processDefinitions =
102                 repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).list();
103         List<ProcessDefinition> oldProcessDefinitions = new ArrayList<>();
104         for (ProcessDefinition processDef : processDefinitions) {
105             if (!processDef.isSuspended() && (processDef.getVersion() != version)) {
106                 oldProcessDefinitions.add(processDef);
107             }
108         }
109         return oldProcessDefinitions;
110     }
111 }