From 20b6a0ec246aa12f2bbc034b3926cb4d72878840 Mon Sep 17 00:00:00 2001 From: Enrique Date: Thu, 7 Sep 2023 08:43:32 +0200 Subject: [PATCH] [kie-issues-509] Handle SLA timers during process instance migration (#2323) * [kie-issues-509] Handle SLA timers during process instance migration * [kie-issues-509] Add tests for process SLA and usertask SLA migration * [kie-issue-509] fix tests and add SLA process migration --------- Co-authored-by: Martin Weiler --- .../instance/node/StateBasedNodeInstance.java | 6 +- .../impl/migration/MigrationManager.java | 198 +++++++++++++----- .../migration/TimerMigrationManagerTest.java | 108 +++++++++- .../migration/v1/BPMN2-ProcessSLA-v1.bpmn2 | 139 ++++++++++++ .../migration/v1/BPMN2-UserTaskSLA-v1.bpmn2 | 137 ++++++++++++ .../migration/v2/BPMN2-ProcessSLA-v2.bpmn2 | 139 ++++++++++++ .../migration/v2/BPMN2-UserTaskSLA-v2.bpmn2 | 137 ++++++++++++ 7 files changed, 803 insertions(+), 61 deletions(-) create mode 100644 jbpm-runtime-manager/src/test/resources/migration/v1/BPMN2-ProcessSLA-v1.bpmn2 create mode 100644 jbpm-runtime-manager/src/test/resources/migration/v1/BPMN2-UserTaskSLA-v1.bpmn2 create mode 100644 jbpm-runtime-manager/src/test/resources/migration/v2/BPMN2-ProcessSLA-v2.bpmn2 create mode 100644 jbpm-runtime-manager/src/test/resources/migration/v2/BPMN2-UserTaskSLA-v2.bpmn2 diff --git a/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/StateBasedNodeInstance.java b/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/StateBasedNodeInstance.java index 5cc3b33614..d7b38b587f 100644 --- a/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/StateBasedNodeInstance.java +++ b/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/StateBasedNodeInstance.java @@ -401,9 +401,9 @@ public void removeEventListeners() { } @Override - protected void triggerCompleted(String type, boolean remove) { - if (this.slaCompliance == org.kie.api.runtime.process.ProcessInstance.SLA_PENDING) { - if (System.currentTimeMillis() > slaDueDate.getTime()) { + protected void triggerCompleted(String type, boolean remove) { + if (this.slaCompliance == org.kie.api.runtime.process.ProcessInstance.SLA_PENDING) { + if (System.currentTimeMillis() > slaDueDate.getTime()) { // completion of the node instance is after expected SLA due date, mark it accordingly this.slaCompliance = org.kie.api.runtime.process.ProcessInstance.SLA_VIOLATED; } else { diff --git a/jbpm-runtime-manager/src/main/java/org/jbpm/runtime/manager/impl/migration/MigrationManager.java b/jbpm-runtime-manager/src/main/java/org/jbpm/runtime/manager/impl/migration/MigrationManager.java index 9e131161b5..e462611e0c 100644 --- a/jbpm-runtime-manager/src/main/java/org/jbpm/runtime/manager/impl/migration/MigrationManager.java +++ b/jbpm-runtime-manager/src/main/java/org/jbpm/runtime/manager/impl/migration/MigrationManager.java @@ -16,8 +16,10 @@ package org.jbpm.runtime.manager.impl.migration; +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; + import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashMap; @@ -25,6 +27,10 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; @@ -142,12 +148,20 @@ public MigrationReport migrate(Map nodeMapping) { boolean migrateExecutorJobs = ((SimpleRuntimeEnvironment)currentManager.getEnvironment()).getEnvironmentTemplate().get("ExecutorService") != null; validate(migrateExecutorJobs); Map> timerMigrated = null; + Map> stateBasedTimer = null; + Map> slaTimerMigrated = null; + Map> humanTaskSuspended = null; + TimerInstance slaProcessInstance = null; try { // collect and cancel any active timers before migration - timerMigrated = cancelActiveTimersBeforeMigration(currentManager); - - // start transaction to secure consistency of the migration + timerMigrated = cancelActiveTimersBeforeMigration(currentManager, TimerNodeInstance.class, active -> asList(active.getTimerId())); + stateBasedTimer = cancelActiveTimersBeforeMigration(currentManager, StateBasedNodeInstance.class, active -> active.getTimerInstances()); + slaTimerMigrated = cancelActiveTimersBeforeMigration(currentManager, org.jbpm.workflow.instance.impl.NodeInstanceImpl.class, active -> asList(active.getSlaTimerId())); + humanTaskSuspended = cancelActiveTimersBeforeMigration(currentManager, HumanTaskNodeInstance.class, active -> asList((active.getSuspendUntilTimerId()))); + slaProcessInstance = cancelSLAActiveTimerProcessInstance(currentManager); + + // start transaction to secure consistency of the migration txm = TransactionManagerFactory.get().newTransactionManager(currentManager.getEnvironment().getEnvironment()); transactionOwner = txm.begin(); @@ -254,9 +268,14 @@ public MigrationReport migrate(Map nodeMapping) { tobe = toBeManager.getEnvironment().getKieBase().newKieSession(); upgradeProcessInstance(current, tobe, migrationSpec.getProcessInstanceId(), migrationSpec.getToProcessId(), nodeMapping, em, toBeManager.getIdentifier()); - if (!timerMigrated.isEmpty()) { - rescheduleTimersAfterMigration(toBeManager, timerMigrated); - } + + // reschedule timers + rescheduleTimersAfterMigration(toBeManager, TimerNodeInstance.class, timerMigrated, (active, timers) -> active.internalSetTimerId(toSingletonTimerId(timers))); + rescheduleTimersAfterMigration(toBeManager, StateBasedNodeInstance.class, stateBasedTimer, (active, timers) -> active.internalSetTimerInstances(timers.stream().map(TimerInstance::getId).collect(Collectors.toList()))); + rescheduleTimersAfterMigration(toBeManager, org.jbpm.workflow.instance.impl.NodeInstanceImpl.class, slaTimerMigrated, (active, timers) -> active.internalSetSlaTimerId(toSingletonTimerId(timers))); + rescheduleTimersAfterMigration(toBeManager, HumanTaskNodeInstance.class, humanTaskSuspended, (active, timers) -> active.setSuspendUntilTimerId(toSingletonTimerId(timers))); + rescheduleTimersAfterMigration(toBeManager, slaProcessInstance); + em.flush(); } finally { em.clear(); @@ -270,10 +289,12 @@ public MigrationReport migrate(Map nodeMapping) { } catch (Throwable e) { txm.rollback(transactionOwner); logger.error("Unexpected error during migration", e); - // put back timers (if there are any) in case of rollback - if (timerMigrated != null && !timerMigrated.isEmpty()) { - rescheduleTimersAfterMigration(currentManager, timerMigrated); - } + + rescheduleTimersAfterMigration(currentManager, TimerNodeInstance.class, timerMigrated, (active, timers) -> active.internalSetTimerId(toSingletonTimerId(timers))); + rescheduleTimersAfterMigration(currentManager, StateBasedNodeInstance.class, stateBasedTimer, (active, timers) -> active.internalSetTimerInstances(timers.stream().map(TimerInstance::getId).collect(Collectors.toList()))); + rescheduleTimersAfterMigration(currentManager, org.jbpm.workflow.instance.impl.NodeInstanceImpl.class, slaTimerMigrated, (active, timers) -> active.internalSetSlaTimerId(toSingletonTimerId(timers))); + rescheduleTimersAfterMigration(currentManager, HumanTaskNodeInstance.class, humanTaskSuspended, (active, timers) -> active.setSuspendUntilTimerId(toSingletonTimerId(timers))); + rescheduleTimersAfterMigration(currentManager, slaProcessInstance); report.addEntry(Type.ERROR, "Migration of process instance (" + migrationSpec.getProcessInstanceId() + ") failed due to " + e.getMessage()); } finally { @@ -297,6 +318,10 @@ public MigrationReport migrate(Map nodeMapping) { return report; } + + private Long toSingletonTimerId(List timerInstances) { + return (timerInstances.isEmpty()) ? -1 : timerInstances.get(0).getId(); + } private void validate(boolean migrateExecutorJobs) { if (migrationSpec == null) { @@ -356,7 +381,7 @@ private void validate(boolean migrateExecutorJobs) { if (migrateExecutorJobs) { List executorJobs = (List) em.createQuery("select id FROM RequestInfo ri WHERE ri.processInstanceId = :processInstanceId and ri.status in (:statuses)") .setParameter("processInstanceId", migrationSpec.getProcessInstanceId()) - .setParameter("statuses", Arrays.asList(STATUS.QUEUED, STATUS.RETRYING, STATUS.RUNNING)) + .setParameter("statuses", asList(STATUS.QUEUED, STATUS.RETRYING, STATUS.RUNNING)) .getResultList(); if (!executorJobs.isEmpty()) { @@ -569,7 +594,68 @@ protected TimerManager getTimerManager(KieSession ksession) { return ((InternalProcessRuntime) ((StatefulKnowledgeSessionImpl) internal).getProcessRuntime()).getTimerManager(); } - protected Map> cancelActiveTimersBeforeMigration(RuntimeManager manager) { + protected TimerInstance cancelSLAActiveTimerProcessInstance(RuntimeManager manager) { + RuntimeEngine engineBefore = manager.getRuntimeEngine(ProcessInstanceIdContext.get(migrationSpec.getProcessInstanceId())); + try { + TimerInstance timerMigrated = engineBefore.getKieSession().execute(new ExecutableCommand() { + + @Override + public TimerInstance execute(Context context) { + KieSession kieSession = ((RegistryContext) context).lookup(KieSession.class); + TimerManager timerManager = getTimerManager(kieSession); + WorkflowProcessInstanceImpl processInstance = (WorkflowProcessInstanceImpl) kieSession.getProcessInstance(migrationSpec.getProcessInstanceId()); + if (processInstance.getSlaTimerId() > 0) { + TimerInstance timerInstance = timerManager.getTimerMap().get(processInstance.getSlaTimerId()); + if (timerInstance != null) { + timerManager.cancelTimer(processInstance.getId(), timerInstance.getId()); + } + + return timerInstance; + } + return null; + } + + }); + return timerMigrated; + } finally { + manager.disposeRuntimeEngine(engineBefore); + } + + } + + protected void rescheduleTimersAfterMigration(RuntimeManager manager, TimerInstance timerMigrated) { + if(timerMigrated == null) { + return; + } + + RuntimeEngine engine = manager.getRuntimeEngine(ProcessInstanceIdContext.get(migrationSpec.getProcessInstanceId())); + try { + engine.getKieSession().execute(new ExecutableCommand() { + + @Override + public Void execute(Context context) { + KieSession kieSession = ((RegistryContext) context).lookup(KieSession.class); + + TimerManager timerManager = getTimerManager(kieSession); + + WorkflowProcessInstanceImpl processInstance = (WorkflowProcessInstanceImpl) kieSession.getProcessInstance(migrationSpec.getProcessInstanceId()); + + long delay = timerMigrated.getDelay() - (System.currentTimeMillis() - timerMigrated.getActivated().getTime()); + timerMigrated.setDelay(delay); + + updateBasedOnTrigger(timerMigrated); + + timerManager.registerTimer(timerMigrated, processInstance); + + processInstance.internalSetSlaTimerId(timerMigrated.getId()); + return null; + }}); + } finally { + manager.disposeRuntimeEngine(engine); + } + } + + protected Map> cancelActiveTimersBeforeMigration(RuntimeManager manager, Class type, Function> getTimerInstances ) { RuntimeEngine engineBefore = manager.getRuntimeEngine(ProcessInstanceIdContext.get(migrationSpec.getProcessInstanceId())); try { Map> timerMigrated = engineBefore.getKieSession().execute(new ExecutableCommand>>() { @@ -589,27 +675,31 @@ public Map> execute(Context context) { Collection activeInstances = processInstance.getNodeInstances(true); for (org.jbpm.workflow.instance.NodeInstance active : activeInstances) { - if (active instanceof TimerNodeInstance) { - TimerInstance timerInstance = timerManager.getTimerMap().get(((TimerNodeInstance) active).getTimerId()); - - timerManager.cancelTimer(processInstance.getId(), timerInstance.getId()); - result.put(active.getId(), Arrays.asList(timerInstance)); - } else if (active instanceof StateBasedNodeInstance) { - List timers = ((StateBasedNodeInstance) active).getTimerInstances(); - - if (timers != null && !timers.isEmpty()) { - List collected = new ArrayList<>(); - for (Long timerId : timers) { - TimerInstance timerInstance = timerManager.getTimerMap().get(timerId); - if (timerInstance==null) { - report.addEntry(Type.WARN, "Could not find timer instance with id "+timerId+" to cancel."); - continue; - } - timerManager.cancelTimer(processInstance.getId(), timerInstance.getId()); - collected.add(timerInstance); - } - result.put(active.getId(), collected); + if (!type.isAssignableFrom(active.getClass())) { + continue; + } + + List timers = getTimerInstances.apply(type.cast(active)); + if (timers == null) { + continue; + } + + List collected = new ArrayList<>(); + for (Long timerId : timers) { + if (timerId == -1) { + continue; } + + TimerInstance timerInstance = timerManager.getTimerMap().get(timerId); + if (timerInstance == null) { + report.addEntry(Type.WARN, "Could not find timer instance with id " + timerId + " to cancel."); + continue; + } + timerManager.cancelTimer(processInstance.getId(), timerInstance.getId()); + collected.add(timerInstance); + } + if (!collected.isEmpty()) { + result.put(active.getId(), collected); } } @@ -623,12 +713,16 @@ public Map> execute(Context context) { } } - protected void rescheduleTimersAfterMigration(RuntimeManager manager, Map> timerMigrated) { + protected void rescheduleTimersAfterMigration(RuntimeManager manager, Class nodeType, Map> timersToMigrate, BiConsumer> timerMigrated) { + if(timersToMigrate.isEmpty()) { + return; + } + RuntimeEngine engine = manager.getRuntimeEngine(ProcessInstanceIdContext.get(migrationSpec.getProcessInstanceId())); try { engine.getKieSession().execute(new ExecutableCommand() { - private static final long serialVersionUID = 7144657913971146080L; + private static final long serialVersionUID = 7144357923971146089L; @Override public Void execute(Context context) { @@ -637,35 +731,25 @@ public Void execute(Context context) { WorkflowProcessInstanceImpl processInstance = (WorkflowProcessInstanceImpl) kieSession.getProcessInstance(migrationSpec.getProcessInstanceId()); - for (Entry> entry : timerMigrated.entrySet()) { + for (Entry> entry : timersToMigrate.entrySet()) { org.jbpm.workflow.instance.NodeInstance active = processInstance.getNodeInstance(entry.getKey(), true); - if (active instanceof TimerNodeInstance) { - TimerInstance timerInstance = entry.getValue().get(0); - + if(!nodeType.isAssignableFrom(active.getClass())) { + continue; + } + + List timerInstances = entry.getValue(); + for (TimerInstance timerInstance : timerInstances) { long delay = timerInstance.getDelay() - (System.currentTimeMillis() - timerInstance.getActivated().getTime()); timerInstance.setDelay(delay); updateBasedOnTrigger(timerInstance); - - timerManager.registerTimer(timerInstance, processInstance); - ((TimerNodeInstance) active).internalSetTimerId(timerInstance.getId()); - } else if (active instanceof StateBasedNodeInstance) { - - List timerInstances = entry.getValue(); - List timers = new ArrayList<>(); - for (TimerInstance timerInstance : timerInstances) { - long delay = timerInstance.getDelay() - (System.currentTimeMillis() - timerInstance.getActivated().getTime()); - timerInstance.setDelay(delay); - - updateBasedOnTrigger(timerInstance); - - timerManager.registerTimer(timerInstance, processInstance); - timers.add(timerInstance.getId()); - } - ((StateBasedNodeInstance) active).internalSetTimerInstances(timers); + timerManager.registerTimer(timerInstance, processInstance); } + + timerMigrated.accept(nodeType.cast(active), timerInstances); + } return null; @@ -697,4 +781,4 @@ protected void updateBasedOnTrigger(TimerInstance timerInstance) { } } -} +} \ No newline at end of file diff --git a/jbpm-runtime-manager/src/test/java/org/jbpm/runtime/manager/impl/migration/TimerMigrationManagerTest.java b/jbpm-runtime-manager/src/test/java/org/jbpm/runtime/manager/impl/migration/TimerMigrationManagerTest.java index 0c7da595c9..e427358794 100644 --- a/jbpm-runtime-manager/src/test/java/org/jbpm/runtime/manager/impl/migration/TimerMigrationManagerTest.java +++ b/jbpm-runtime-manager/src/test/java/org/jbpm/runtime/manager/impl/migration/TimerMigrationManagerTest.java @@ -41,6 +41,7 @@ import org.jbpm.services.task.identity.JBossUserGroupCallbackImpl; import org.jbpm.services.task.impl.TaskDeadlinesServiceImpl; import org.jbpm.test.listener.process.NodeLeftCountDownProcessEventListener; +import org.jbpm.test.listener.process.SLAViolationCountDownProcessEventListener; import org.jbpm.test.util.AbstractBaseTest; import org.junit.After; import org.junit.Before; @@ -114,6 +115,13 @@ public TimerMigrationManagerTest(String strategy) { private static final String USERTASK_BOUNDARY_TIMER_ID_V1 = "UserTaskBoundary-v1"; private static final String USERTASK_BOUNDARY_TIMER_ID_V2 = "UserTaskBoundary-v2"; + + private static final String USERTASK_SLA_ID_V1 = "BPMN2-UserTaskSLA-v1"; + private static final String USERTASK_SLA_ID_V2 = "BPMN2-UserTaskSLA-v2"; + + private static final String PROCESS_SLA_ID_V1 = "BPMN2-ProcessSLA-v1"; + private static final String PROCESS_SLA_ID_V2 = "BPMN2-ProcessSLA-v2"; + private JPAAuditLogService auditService; private RuntimeEngine runtime; private long pid; @@ -298,7 +306,7 @@ public void testMigrateEventSubprocessTimerProcessInstance() throws Exception { } @SuppressWarnings({"unchecked", "rawtypes"}) - @Test(timeout=10000) + @Test//(timeout=10000) public void testMigrateTimerProcessInstanceRollback() throws Exception { NodeLeftCountDownProcessEventListener countdownListener = new NodeLeftCountDownProcessEventListener("Event", 1); createRuntimeManagers("migration/v1/BPMN2-Timer-v1.bpmn2", "migration/v2/BPMN2-Timer-v2.bpmn2", countdownListener); @@ -590,6 +598,104 @@ public void testMigrateUserTaskNotCompletedBoundaryTimerProcessInstance() throws checkProcessCompleted(countdownListener); } + @Test(timeout=10000) + public void testUserTaskSLA() throws Exception { + SLAViolationCountDownProcessEventListener countdownListener = new SLAViolationCountDownProcessEventListener(1); + createRuntimeManagers("migration/v1/BPMN2-UserTaskSLA-v1.bpmn2", "migration/v2/BPMN2-UserTaskSLA-v2.bpmn2", countdownListener); + assertNotNull(managerV1); + assertNotNull(managerV2); + + RuntimeEngine runtime = managerV1.getRuntimeEngine(EmptyContext.get()); + KieSession ksession = runtime.getKieSession(); + assertNotNull(ksession); + + ProcessInstance pi1 = ksession.startProcess(USERTASK_SLA_ID_V1); + assertNotNull(pi1); + assertEquals(ProcessInstance.STATE_ACTIVE, pi1.getState()); + JPAAuditLogService auditService = new JPAAuditLogService(emf); + ProcessInstanceLog log = auditService.findProcessInstance(pi1.getId()); + assertNotNull(log); + assertEquals(USERTASK_SLA_ID_V1, log.getProcessId()); + assertEquals(DEPLOYMENT_ID_V1, log.getExternalId()); + + managerV1.disposeRuntimeEngine(runtime); + + MigrationSpec migrationSpec = new MigrationSpec(DEPLOYMENT_ID_V1, pi1.getId(), DEPLOYMENT_ID_V2, USERTASK_SLA_ID_V2); + + MigrationManager migrationManager = new MigrationManager(migrationSpec); + MigrationReport report = migrationManager.migrate(); + + assertNotNull(report); + assertTrue(report.isSuccessful()); + + log = auditService.findProcessInstance(pi1.getId()); + assertNotNull(log); + assertEquals(USERTASK_SLA_ID_V2, log.getProcessId()); + assertEquals(DEPLOYMENT_ID_V2, log.getExternalId()); + assertEquals(ProcessInstance.STATE_ACTIVE, log.getStatus().intValue()); + + + // wait till timer fires + countdownListener.waitTillCompleted(); + + log = auditService.findProcessInstance(pi1.getId()); + auditService.dispose(); + assertNotNull(log); + assertEquals(USERTASK_SLA_ID_V2, log.getProcessId()); + assertEquals(DEPLOYMENT_ID_V2, log.getExternalId()); + assertEquals(ProcessInstance.STATE_ACTIVE, log.getStatus().intValue()); + + } + + @Test(timeout=10000) + public void testProcessSLA() throws Exception { + SLAViolationCountDownProcessEventListener countdownListener = new SLAViolationCountDownProcessEventListener(1); + createRuntimeManagers("migration/v1/BPMN2-ProcessSLA-v1.bpmn2", "migration/v2/BPMN2-ProcessSLA-v2.bpmn2", countdownListener); + assertNotNull(managerV1); + assertNotNull(managerV2); + + RuntimeEngine runtime = managerV1.getRuntimeEngine(EmptyContext.get()); + KieSession ksession = runtime.getKieSession(); + assertNotNull(ksession); + + ProcessInstance pi1 = ksession.startProcess(PROCESS_SLA_ID_V1); + assertNotNull(pi1); + assertEquals(ProcessInstance.STATE_ACTIVE, pi1.getState()); + JPAAuditLogService auditService = new JPAAuditLogService(emf); + ProcessInstanceLog log = auditService.findProcessInstance(pi1.getId()); + assertNotNull(log); + assertEquals(PROCESS_SLA_ID_V1, log.getProcessId()); + assertEquals(DEPLOYMENT_ID_V1, log.getExternalId()); + + managerV1.disposeRuntimeEngine(runtime); + + MigrationSpec migrationSpec = new MigrationSpec(DEPLOYMENT_ID_V1, pi1.getId(), DEPLOYMENT_ID_V2, PROCESS_SLA_ID_V2); + + MigrationManager migrationManager = new MigrationManager(migrationSpec); + MigrationReport report = migrationManager.migrate(); + + assertNotNull(report); + assertTrue(report.isSuccessful()); + + log = auditService.findProcessInstance(pi1.getId()); + assertNotNull(log); + assertEquals(PROCESS_SLA_ID_V2, log.getProcessId()); + assertEquals(DEPLOYMENT_ID_V2, log.getExternalId()); + assertEquals(ProcessInstance.STATE_ACTIVE, log.getStatus().intValue()); + + + // wait till timer fires + countdownListener.waitTillCompleted(); + + log = auditService.findProcessInstance(pi1.getId()); + auditService.dispose(); + assertNotNull(log); + assertEquals(PROCESS_SLA_ID_V2, log.getProcessId()); + assertEquals(DEPLOYMENT_ID_V2, log.getExternalId()); + assertEquals(ProcessInstance.STATE_ACTIVE, log.getStatus().intValue()); + + } + protected void createRuntimeManagers(String processV1, String processV2, ProcessEventListener...eventListeners) { RuntimeEnvironment environment = RuntimeEnvironmentBuilder.Factory.get() .newDefaultBuilder() diff --git a/jbpm-runtime-manager/src/test/resources/migration/v1/BPMN2-ProcessSLA-v1.bpmn2 b/jbpm-runtime-manager/src/test/resources/migration/v1/BPMN2-ProcessSLA-v1.bpmn2 new file mode 100644 index 0000000000..14c8d0fa4b --- /dev/null +++ b/jbpm-runtime-manager/src/test/resources/migration/v1/BPMN2-ProcessSLA-v1.bpmn2 @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _1-_2 + + + + + + + + _1-_2 + _2-_3 + + + + + _2_TaskNameInputX + _2_SkippableInputX + + + + _2_TaskNameInputX + + + + + + + _2_SkippableInputX + + + + + + + + john + + + + + + + + + + _2-_3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _xI_0QCs8EDy3G-EZm5NgUw + _xI_0QCs8EDy3G-EZm5NgUw + + diff --git a/jbpm-runtime-manager/src/test/resources/migration/v1/BPMN2-UserTaskSLA-v1.bpmn2 b/jbpm-runtime-manager/src/test/resources/migration/v1/BPMN2-UserTaskSLA-v1.bpmn2 new file mode 100644 index 0000000000..3255d53f9f --- /dev/null +++ b/jbpm-runtime-manager/src/test/resources/migration/v1/BPMN2-UserTaskSLA-v1.bpmn2 @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + _1-_2 + + + + + + + + + + + _1-_2 + _2-_3 + + + + + _2_TaskNameInputX + _2_SkippableInputX + + + + _2_TaskNameInputX + + + + + + + _2_SkippableInputX + + + + + + + + john + + + + + + + + + + _2-_3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _bDDtUCs7EDyU3ILCRECaIg + _bDDtUCs7EDyU3ILCRECaIg + + diff --git a/jbpm-runtime-manager/src/test/resources/migration/v2/BPMN2-ProcessSLA-v2.bpmn2 b/jbpm-runtime-manager/src/test/resources/migration/v2/BPMN2-ProcessSLA-v2.bpmn2 new file mode 100644 index 0000000000..fa60461bb2 --- /dev/null +++ b/jbpm-runtime-manager/src/test/resources/migration/v2/BPMN2-ProcessSLA-v2.bpmn2 @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _1-_2 + + + + + + + + _1-_2 + _2-_3 + + + + + _2_TaskNameInputX + _2_SkippableInputX + + + + _2_TaskNameInputX + + + + + + + _2_SkippableInputX + + + + + + + + john + + + + + + + + + + _2-_3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _3levgCs8EDyjMtruot-ztw + _3levgCs8EDyjMtruot-ztw + + diff --git a/jbpm-runtime-manager/src/test/resources/migration/v2/BPMN2-UserTaskSLA-v2.bpmn2 b/jbpm-runtime-manager/src/test/resources/migration/v2/BPMN2-UserTaskSLA-v2.bpmn2 new file mode 100644 index 0000000000..2dbcdce0d8 --- /dev/null +++ b/jbpm-runtime-manager/src/test/resources/migration/v2/BPMN2-UserTaskSLA-v2.bpmn2 @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + _1-_2 + + + + + + + + + + + _1-_2 + _2-_3 + + + + + _2_TaskNameInputX + _2_SkippableInputX + + + + _2_TaskNameInputX + + + + + + + _2_SkippableInputX + + + + + + + + john + + + + + + + + + + _2-_3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _T9P9sCs6EDyfboU5usA46A + _T9P9sCs6EDyfboU5usA46A + +