fd7498f468a7a56e0e5c8385810d54c2bbbaf7f4
[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         List<ProcessDefinition> processDefinitions = new ArrayList<ProcessDefinition>();
56         processDefinitionKeys = env.getProperty("migration.processDefinitionKeys", List.class, new ArrayList<String>());
57         for (String key : processDefinitionKeys) {
58             processDefinitions.add(repositoryService.createProcessDefinitionQuery().processDefinitionKey(key)
59                     .latestVersion().singleResult());
60         }
61         return processDefinitions;
62     }
63
64     private void migrate(String sourceProcessDefinitionId, String targetProcessDefinitionId) {
65         MigrationPlan migrationPlan =
66                 runtimeService.createMigrationPlan(sourceProcessDefinitionId, targetProcessDefinitionId)
67                         .mapEqualActivities().updateEventTriggers().build();
68         List<String> activityIds = new ArrayList<>();
69
70         for (MigrationInstruction instruction : migrationPlan.getInstructions()) {
71             activityIds.add(instruction.getSourceActivityId());
72         }
73         for (String activityId : activityIds) {
74             ProcessInstanceQuery activeProcessInstancesQuery = runtimeService.createProcessInstanceQuery()
75                     .processDefinitionId(sourceProcessDefinitionId).activityIdIn(activityId).active();
76             if (!activeProcessInstancesQuery.list().isEmpty()) {
77                 logger.info("Migrating {} process instance(s) from {} to {}",
78                         Long.valueOf(activeProcessInstancesQuery.count()), sourceProcessDefinitionId,
79                         targetProcessDefinitionId);
80                 MigrationPlanExecutionBuilder migration =
81                         runtimeService.newMigration(migrationPlan).processInstanceQuery(activeProcessInstancesQuery);
82                 migration.executeAsync();
83             }
84         }
85         suspendEmptyProcessDefinition(sourceProcessDefinitionId);
86     }
87
88     private void suspendEmptyProcessDefinition(String sourceProcessDefinitionId) {
89         List<ProcessInstance> activeProcessInstances = runtimeService.createProcessInstanceQuery()
90                 .processDefinitionId(sourceProcessDefinitionId).active().list();
91         if (activeProcessInstances.isEmpty()) {
92             repositoryService.suspendProcessDefinitionById(sourceProcessDefinitionId);
93         } else {
94             logger.info("Unable to migrate {} process instance(s) from {}",
95                     Integer.valueOf(activeProcessInstances.size()), sourceProcessDefinitionId);
96         }
97     }
98
99     protected List<ProcessDefinition> getOldProcessDefinitions(String key, int version) {
100         List<ProcessDefinition> processDefinitions =
101                 repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).list();
102         List<ProcessDefinition> oldProcessDefinitions = new ArrayList<>();
103         for (ProcessDefinition processDef : processDefinitions) {
104             if (!processDef.isSuspended() && (processDef.getVersion() != version)) {
105                 oldProcessDefinitions.add(processDef);
106             }
107         }
108         return oldProcessDefinitions;
109     }
110 }