1 package org.onap.so.bpmn.common.workflow.service;
 
   3 import java.util.ArrayList;
 
   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;
 
  24 public class AutoProcessInstanceMigrationService {
 
  26     private static Logger logger = LoggerFactory.getLogger(AutoProcessInstanceMigrationService.class);
 
  29     private Environment env;
 
  31     protected ProcessEngine processEngine;
 
  33     @Value("${migration.autoMigrationEnabled:false}")
 
  34     private boolean autoMigrationEnabled;
 
  36     private RuntimeService runtimeService;
 
  37     private RepositoryService repositoryService;
 
  38     private List<String> processDefinitionKeys;
 
  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());
 
  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());
 
  61         return processDefinitions;
 
  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<>();
 
  70         for (MigrationInstruction instruction : migrationPlan.getInstructions()) {
 
  71             activityIds.add(instruction.getSourceActivityId());
 
  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();
 
  85         suspendEmptyProcessDefinition(sourceProcessDefinitionId);
 
  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);
 
  94             logger.info("Unable to migrate {} process instance(s) from {}",
 
  95                     Integer.valueOf(activeProcessInstances.size()), sourceProcessDefinitionId);
 
  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);
 
 108         return oldProcessDefinitions;