This is an automated email from the ASF dual-hosted git repository.
tiagobento pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git
The following commit(s) were added to refs/heads/main by this push:
new 93ba2a6e4c0 incubator-kie-issues#2307: adjust root process references
after migration (#6839)
93ba2a6e4c0 is described below
commit 93ba2a6e4c07a82cb4953e38b418e60e83314470
Author: Jan Stastny <[email protected]>
AuthorDate: Fri Jul 31 14:08:36 2026 +0200
incubator-kie-issues#2307: adjust root process references after migration
(#6839)
---
.../kogito/persistence/jdbc/GenericRepository.java | 53 +++-
.../persistence/jdbc/JDBCProcessInstances.java | 21 +-
.../kie/kogito/persistence/jdbc/Repository.java | 47 ++--
.../ansi/V10.2.0__add_root_process_instance_id.sql | 22 ++
.../V10.2.0__add_root_process_instance_id.sql | 22 ++
.../jdbc/AbstractProcessInstancesIT.java | 312 ++++++++++++++++++++-
.../src/test/resources/BPMN2-CallActivity-v1.bpmn2 | 82 ++++++
.../src/test/resources/BPMN2-CallActivity-v2.bpmn2 | 82 ++++++
8 files changed, 604 insertions(+), 37 deletions(-)
diff --git
a/kogito-addons/common/persistence/jdbc/src/main/java/org/kie/kogito/persistence/jdbc/GenericRepository.java
b/kogito-addons/common/persistence/jdbc/src/main/java/org/kie/kogito/persistence/jdbc/GenericRepository.java
index f7ee9e1ddd8..eb0cc4f95ce 100644
---
a/kogito-addons/common/persistence/jdbc/src/main/java/org/kie/kogito/persistence/jdbc/GenericRepository.java
+++
b/kogito-addons/common/persistence/jdbc/src/main/java/org/kie/kogito/persistence/jdbc/GenericRepository.java
@@ -38,6 +38,11 @@ import static java.util.Arrays.stream;
public class GenericRepository extends Repository {
private static final Logger LOGGER =
LoggerFactory.getLogger(GenericRepository.class);
+ private static final String ID = "id";
+ private static final String PROCESS_ID = "process_id";
+ private static final String PROCESS_VERSION = "process_version";
+ private static final String ROOT_PROCESS_ID = "root_process_id";
+ private static final String ROOT_PROCESS_VERSION = "root_process_version";
private static final String PAYLOAD = "payload";
private static final String VERSION = "version";
@@ -142,7 +147,8 @@ public class GenericRepository extends Repository {
}
@Override
- void insertInternal(String processId, String processVersion, String
rootProcessId, String rootProcessVersion, UUID id, byte[] payload, String
businessKey, String[] eventTypes) {
+ void insertInternal(String processId, String processVersion, String
rootProcessId, String rootProcessVersion,
+ String rootProcessInstanceId, UUID id, byte[] payload, String
businessKey, String[] eventTypes) {
try (Connection connection = dataSource.getConnection();
PreparedStatement statement =
connection.prepareStatement(INSERT);
PreparedStatement eventStatement =
connection.prepareStatement(DELETE_ALL_WAITING_FOR_EVENT_TYPE);
@@ -164,7 +170,8 @@ public class GenericRepository extends Repository {
statement.setString(4, processVersion);
statement.setString(5, rootProcessId);
statement.setString(6, rootProcessVersion);
- statement.setLong(7, 0L);
+ statement.setString(7, rootProcessInstanceId);
+ statement.setLong(8, 0L);
statement.executeUpdate();
if (businessKey != null) {
try (PreparedStatement businessKeyStmt =
connection.prepareStatement(INSERT_BUSINESS_KEY)) {
@@ -259,7 +266,8 @@ public class GenericRepository extends Repository {
}
private Record from(ResultSet rs) throws SQLException {
- return new Record(rs.getBytes(PAYLOAD), rs.getLong(VERSION));
+ return new Record(rs.getString(ID), rs.getString(PROCESS_ID),
rs.getString(PROCESS_VERSION),
+ rs.getString(ROOT_PROCESS_ID),
rs.getString(ROOT_PROCESS_VERSION), rs.getLong(VERSION), rs.getBytes(PAYLOAD));
}
@Override
@@ -422,6 +430,40 @@ public class GenericRepository extends Repository {
return statement + " " + (processVersion == null ?
PROCESS_VERSION_IS_NULL : PROCESS_VERSION_EQUALS_TO);
}
+ private static String sqlIncludingRootVersion(String statement, String
rootProcessVersion) {
+ return statement + (rootProcessVersion == null ?
ROOT_PROCESS_VERSION_IS_NULL : ROOT_PROCESS_VERSION_EQUALS_TO);
+ }
+
+ private void migrateRootCascade(Connection connection,
+ String processId, String processVersion,
+ String targetProcessId, String targetProcessVersion,
+ String[] processInstanceIds) throws SQLException {
+ final String cascadeSql;
+ if (processInstanceIds == null) {
+ cascadeSql = sqlIncludingRootVersion(MIGRATE_ROOT_BULK,
processVersion);
+ } else {
+ String placeholders = stream(processInstanceIds).map(x ->
"?").collect(Collectors.joining(", "));
+ cascadeSql =
MIGRATE_ROOT_INSTANCES_SQL_TEMPLATE.formatted(placeholders);
+ }
+
+ try (PreparedStatement cascadeStmt =
connection.prepareStatement(cascadeSql)) {
+ cascadeStmt.setString(1, targetProcessId);
+ cascadeStmt.setString(2, targetProcessVersion);
+ if (processInstanceIds == null) {
+ cascadeStmt.setString(3, processId);
+ if (processVersion != null) {
+ cascadeStmt.setString(4, processVersion);
+ }
+ } else {
+ int i = 3;
+ for (String id : processInstanceIds) {
+ cascadeStmt.setString(i++, id);
+ }
+ }
+ cascadeStmt.executeUpdate();
+ }
+ }
+
@Override
long migrate(String processId, String processVersion, String
targetProcessId, String targetProcessVersion) {
try (Connection connection = dataSource.getConnection();
@@ -432,7 +474,9 @@ public class GenericRepository extends Repository {
if (processVersion != null) {
statement.setString(4, processVersion);
}
- return statement.executeUpdate();
+ long count = statement.executeUpdate();
+ migrateRootCascade(connection, processId, processVersion,
targetProcessId, targetProcessVersion, null);
+ return count;
} catch (Exception e) {
throw uncheckedException(e, "Error updating process instance
%s-%s", processId, processVersion);
}
@@ -461,6 +505,7 @@ public class GenericRepository extends Repository {
statement.setString(i, processVersion);
}
statement.executeUpdate();
+ migrateRootCascade(connection, processId, processVersion,
targetProcessId, targetProcessVersion, processInstanceIds);
} catch (Exception e) {
throw uncheckedException(e, "Error updating process instance
%s-%s", processId, processVersion);
}
diff --git
a/kogito-addons/common/persistence/jdbc/src/main/java/org/kie/kogito/persistence/jdbc/JDBCProcessInstances.java
b/kogito-addons/common/persistence/jdbc/src/main/java/org/kie/kogito/persistence/jdbc/JDBCProcessInstances.java
index 11746d5d8d9..414ac08c2a2 100644
---
a/kogito-addons/common/persistence/jdbc/src/main/java/org/kie/kogito/persistence/jdbc/JDBCProcessInstances.java
+++
b/kogito-addons/common/persistence/jdbc/src/main/java/org/kie/kogito/persistence/jdbc/JDBCProcessInstances.java
@@ -81,8 +81,9 @@ public class JDBCProcessInstances<T extends Model> implements
MutableProcessInst
String[] eventTypes = getUniqueEvents(instance);
String rootProcessId = ((AbstractProcessInstance<T>)
instance).internalGetProcessInstance().getRootProcessId();
String rootProcessVersion = ((AbstractProcessInstance<T>)
instance).internalGetProcessInstance().getRootProcessVersion();
- repository.insertInternal(process.id(), process.version(),
rootProcessId, rootProcessVersion, UUID.fromString(id),
marshaller.marshallProcessInstance(instance), instance.businessKey(),
- eventTypes);
+ String rootProcessInstanceId = ((AbstractProcessInstance<T>)
instance).internalGetProcessInstance().getRootProcessInstanceId();
+ repository.insertInternal(process.id(), process.version(),
rootProcessId, rootProcessVersion, rootProcessInstanceId,
+ UUID.fromString(id),
marshaller.marshallProcessInstance(instance), instance.businessKey(),
eventTypes);
connectInstance(instance);
} else {
LOGGER.warn("Skipping create of process instance id: {}, state:
{}", id, instance.status());
@@ -155,8 +156,8 @@ public class JDBCProcessInstances<T extends Model>
implements MutableProcessInst
}
private ProcessInstance<T> unmarshall(Repository.Record record,
ProcessInstanceReadMode mode) {
- AbstractProcessInstance<T> instance = (AbstractProcessInstance<T>)
marshaller.unmarshallProcessInstance(record.getPayload(), process, mode);
- instance.setVersion(record.getVersion());
+ AbstractProcessInstance<T> instance = (AbstractProcessInstance<T>)
marshaller.unmarshallProcessInstance(record.payload(), process, mode);
+ instance.setVersion(record.version());
connectInstance(instance);
return instance;
}
@@ -167,10 +168,12 @@ public class JDBCProcessInstances<T extends Model>
implements MutableProcessInst
}
private void connectInstance(ProcessInstance<?> instance) {
- ((AbstractProcessInstance<?>)
instance).internalSetReloadSupplier(marshaller.createdReloadFunction(() -> {
- Repository.Record r = repository.findByIdInternal(process.id(),
process.version(), UUID.fromString(instance.id())).orElseThrow();
- ((AbstractProcessInstance<?>) instance).setVersion(r.getVersion());
- return r.getPayload();
- }));
+ ((AbstractProcessInstance<?>) instance).internalSetReloadSupplier(pi
-> {
+ Repository.Record r = repository.findByIdInternal(process.id(),
process.version(), UUID.fromString(pi.id())).orElseThrow();
+ pi.setVersion(r.version());
+ marshaller.createdReloadFunction(r::payload).accept(pi);
+
pi.internalGetProcessInstance().setRootProcessId(r.rootProcessId());
+
pi.internalGetProcessInstance().setRootProcessVersion(r.rootProcessVersion());
+ });
}
}
diff --git
a/kogito-addons/common/persistence/jdbc/src/main/java/org/kie/kogito/persistence/jdbc/Repository.java
b/kogito-addons/common/persistence/jdbc/src/main/java/org/kie/kogito/persistence/jdbc/Repository.java
index 946f5910031..6cdf8e9888c 100644
---
a/kogito-addons/common/persistence/jdbc/src/main/java/org/kie/kogito/persistence/jdbc/Repository.java
+++
b/kogito-addons/common/persistence/jdbc/src/main/java/org/kie/kogito/persistence/jdbc/Repository.java
@@ -24,11 +24,13 @@ import java.util.stream.Stream;
abstract class Repository {
- static final String INSERT = "INSERT INTO process_instances (id, payload,
process_id, process_version, root_process_id, root_process_version, version)
VALUES (?, ?, ?, ?, ?, ?, ?)";
+ static final String INSERT =
+ "INSERT INTO process_instances (id, payload, process_id,
process_version, root_process_id, root_process_version,
root_process_instance_id, version) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
static final String INSERT_BUSINESS_KEY = "INSERT INTO
business_key_mapping (business_key,process_instance_id) VALUES (?,?)";
- static final String FIND_ALL = "SELECT payload, version FROM
process_instances WHERE process_id = ?";
- static final String FIND_BY_ID = "SELECT payload, version FROM
process_instances WHERE process_id = ? and id = ?";
- static final String FIND_BY_BUSINESS_KEY = "SELECT payload, version FROM
process_instances INNER JOIN business_key_mapping ON id = process_instance_id
WHERE business_key = ? and process_id = ?";
+ static final String FIND_ALL = "SELECT id, payload, process_id,
process_version, root_process_id, root_process_version, version FROM
process_instances WHERE process_id = ?";
+ static final String FIND_BY_ID = "SELECT id, payload, process_id,
process_version, root_process_id, root_process_version, version FROM
process_instances WHERE process_id = ? and id = ?";
+ static final String FIND_BY_BUSINESS_KEY =
+ "SELECT id, payload, process_id, process_version, root_process_id,
root_process_version, version FROM process_instances INNER JOIN
business_key_mapping ON id = process_instance_id WHERE business_key = ? and
process_id = ?";
static final String UPDATE = "UPDATE process_instances SET payload = ?
WHERE process_id = ? and id = ?";
static final String UPDATE_WITH_LOCK = "UPDATE process_instances SET
payload = ?, version = ? WHERE process_id = ? and id = ? and version = ?";
static final String DELETE = "DELETE FROM process_instances WHERE
process_id = ? and id = ?";
@@ -36,30 +38,31 @@ abstract class Repository {
static final String PROCESS_VERSION_IS_NULL = "and process_version is
null";
static final String MIGRATE_BULK = "UPDATE process_instances SET
process_id = ?, process_version = ? WHERE process_id = ? ";
static final String MIGRATE_INSTANCES_SQL_TEMPLATE = "UPDATE
process_instances SET process_id = ?, process_version = ? WHERE process_id = ?
and id IN ( %s ) ";
+ // Cascade UPDATE root columns for child subprocess instances — bulk
overload (completed by sqlIncludingRootVersion)
+ static final String MIGRATE_ROOT_BULK =
+ "UPDATE process_instances SET root_process_id = ?,
root_process_version = ? WHERE root_process_id = ? ";
+ // Cascade UPDATE root columns for child subprocess instances — selective
overload
+ static final String MIGRATE_ROOT_INSTANCES_SQL_TEMPLATE =
+ "UPDATE process_instances SET root_process_id = ?,
root_process_version = ? WHERE root_process_instance_id IN ( %s )";
+ static final String ROOT_PROCESS_VERSION_EQUALS_TO = "and
root_process_version = ?";
+ static final String ROOT_PROCESS_VERSION_IS_NULL = "and
root_process_version is null";
static final String FIND_ALL_WAITING_FOR_EVENT_TYPE =
- "SELECT payload, version FROM event_types, process_instances WHERE
process_instances.id = event_types.process_instance_id AND process_id = ? AND
event_type = ?";
+ "SELECT process_instances.id, payload, process_id,
process_version, root_process_id, root_process_version, version FROM
event_types, process_instances WHERE process_instances.id =
event_types.process_instance_id AND process_id = ? AND event_type = ?";
static final String DELETE_ALL_WAITING_FOR_EVENT_TYPE = "DELETE FROM
event_types WHERE process_instance_id = ?";
static final String INSERT_WAITING_FOR_EVENT_TYPE = "INSERT INTO
event_types (process_instance_id, event_type) VALUES(?,?)";
- static class Record {
- private final byte[] payload;
- private final long version;
-
- public byte[] getPayload() {
- return payload;
- }
-
- public long getVersion() {
- return version;
- }
-
- public Record(byte[] payload, long version) {
- this.payload = payload;
- this.version = version;
- }
+ record Record(
+ String id,
+ String processId,
+ String processVersion,
+ String rootProcessId,
+ String rootProcessVersion,
+ long version,
+ byte[] payload) {
}
- abstract void insertInternal(String processId, String processVersion,
String rootProcessId, String rootProcessVersion, UUID id, byte[] payload,
String businessKey, String[] eventTypes);
+ abstract void insertInternal(String processId, String processVersion,
String rootProcessId, String rootProcessVersion,
+ String rootProcessInstanceId, UUID id, byte[] payload, String
businessKey, String[] eventTypes);
abstract void updateInternal(String processId, String processVersion, UUID
id, byte[] payload, String[] eventTypes);
diff --git
a/kogito-addons/common/persistence/jdbc/src/main/resources/kie-flyway/db/persistence-jdbc/ansi/V10.2.0__add_root_process_instance_id.sql
b/kogito-addons/common/persistence/jdbc/src/main/resources/kie-flyway/db/persistence-jdbc/ansi/V10.2.0__add_root_process_instance_id.sql
new file mode 100644
index 00000000000..0efe251a002
--- /dev/null
+++
b/kogito-addons/common/persistence/jdbc/src/main/resources/kie-flyway/db/persistence-jdbc/ansi/V10.2.0__add_root_process_instance_id.sql
@@ -0,0 +1,22 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+--
+
+ALTER TABLE process_instances ADD COLUMN IF NOT EXISTS
root_process_instance_id character varying(36);
+
+CREATE INDEX IF NOT EXISTS idx_process_instances_root_process_instance_id ON
process_instances (root_process_instance_id);
diff --git
a/kogito-addons/common/persistence/jdbc/src/main/resources/kie-flyway/db/persistence-jdbc/postgresql/V10.2.0__add_root_process_instance_id.sql
b/kogito-addons/common/persistence/jdbc/src/main/resources/kie-flyway/db/persistence-jdbc/postgresql/V10.2.0__add_root_process_instance_id.sql
new file mode 100644
index 00000000000..0efe251a002
--- /dev/null
+++
b/kogito-addons/common/persistence/jdbc/src/main/resources/kie-flyway/db/persistence-jdbc/postgresql/V10.2.0__add_root_process_instance_id.sql
@@ -0,0 +1,22 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+--
+
+ALTER TABLE process_instances ADD COLUMN IF NOT EXISTS
root_process_instance_id character varying(36);
+
+CREATE INDEX IF NOT EXISTS idx_process_instances_root_process_instance_id ON
process_instances (root_process_instance_id);
diff --git
a/kogito-addons/common/persistence/jdbc/src/test/java/org/kie/kogito/persistence/jdbc/AbstractProcessInstancesIT.java
b/kogito-addons/common/persistence/jdbc/src/test/java/org/kie/kogito/persistence/jdbc/AbstractProcessInstancesIT.java
index 9d47fbf96aa..0daf72d1911 100644
---
a/kogito-addons/common/persistence/jdbc/src/test/java/org/kie/kogito/persistence/jdbc/AbstractProcessInstancesIT.java
+++
b/kogito-addons/common/persistence/jdbc/src/test/java/org/kie/kogito/persistence/jdbc/AbstractProcessInstancesIT.java
@@ -20,7 +20,10 @@ package org.kie.kogito.persistence.jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
+import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Optional;
import javax.sql.DataSource;
@@ -32,13 +35,16 @@ import org.kie.kogito.Model;
import org.kie.kogito.auth.IdentityProviders;
import org.kie.kogito.auth.SecurityPolicy;
import org.kie.kogito.internal.process.workitem.Policy;
+import org.kie.kogito.process.Process;
import org.kie.kogito.process.ProcessInstance;
+import org.kie.kogito.process.Processes;
import org.kie.kogito.process.SignalFactory;
import org.kie.kogito.process.WorkItem;
import org.kie.kogito.process.bpmn2.BpmnProcess;
import org.kie.kogito.process.bpmn2.BpmnProcessInstance;
import org.kie.kogito.process.bpmn2.BpmnVariables;
import org.kie.kogito.process.bpmn2.StaticApplicationAssembler;
+import org.kie.kogito.process.impl.AbstractProcessInstance;
import org.kie.kogito.process.impl.StaticProcessConfig;
import org.kie.kogito.process.workitems.impl.DefaultKogitoWorkItemHandler;
@@ -67,6 +73,42 @@ abstract class AbstractProcessInstancesIT {
.migrate();
}
+ /** Loads multiple BPMN files into a single application context so that
call-activity/subprocess wiring works. */
+ private Map<String, BpmnProcess> createProcesses(DataSource dataSource,
Boolean lock, String... fileNames) {
+ Map<String, BpmnProcess> processMap = new HashMap<>();
+ Processes processesSelfRef = new Processes() {
+ @Override
+ public Collection<String> processIds() {
+ return processMap.keySet();
+ }
+
+ @Override
+ public Collection<Process<? extends Model>> processes() {
+ return Collections.unmodifiableCollection(processMap.values());
+ }
+
+ @Override
+ public Process<? extends Model> processById(String processId) {
+ return processMap.get(processId);
+ }
+ };
+
+ StaticProcessConfig processConfig =
StaticProcessConfig.newStaticProcessConfigBuilder()
+ .withWorkItemHandler("Human Task", new
DefaultKogitoWorkItemHandler())
+ .build();
+
+ Application application =
StaticApplicationAssembler.instance().newStaticApplication(
+ new TestProcessInstancesFactory(dataSource, lock,
processesSelfRef), processConfig, fileNames);
+
+ Processes container = application.get(Processes.class);
+ for (String processId : container.processIds()) {
+ BpmnProcess p = (BpmnProcess) container.processById(processId);
+ processMap.put(processId, p);
+ abort(p.instances());
+ }
+ return processMap;
+ }
+
private BpmnProcess createProcess(DataSource dataSource, Boolean lock,
String fileName) {
StaticProcessConfig processConfig =
StaticProcessConfig.newStaticProcessConfigBuilder()
.withWorkItemHandler("Human Task", new
DefaultKogitoWorkItemHandler())
@@ -74,9 +116,9 @@ abstract class AbstractProcessInstancesIT {
Application application =
StaticApplicationAssembler.instance().newStaticApplication(new
TestProcessInstancesFactory(dataSource, lock), processConfig, fileName);
- org.kie.kogito.process.Processes container =
application.get(org.kie.kogito.process.Processes.class);
+ Processes container = application.get(Processes.class);
String processId = container.processIds().stream().findFirst().get();
- org.kie.kogito.process.Process<? extends Model> process =
container.processById(processId);
+ Process<? extends Model> process = container.processById(processId);
abort(process.instances());
BpmnProcess compiledProcess = (BpmnProcess) process;
@@ -333,6 +375,272 @@ abstract class AbstractProcessInstancesIT {
assertEmpty(processInstancesV2);
}
+ @Test
+ public void testMigrateRootCascade() throws Exception {
+ // Load the call-activity (no version) and its subprocess so that
child rows are written with
+ // root_process_id = "BPMN2_CallActivity" and root_process_version =
null.
+ Map<String, BpmnProcess> processes = createProcesses(getDataSource(),
lock(),
+ "BPMN2-CallActivity.bpmn2", "BPMN2-CallActivity-v2.bpmn2",
"BPMN2-UserTask.bpmn2");
+ BpmnProcess callActivityProcess = processes.get("BPMN2_CallActivity");
+ BpmnProcess userTaskProcess = processes.get("BPMN2_UserTask");
+
+ // Start the call-activity instance — this spawns a BPMN2_UserTask
subprocess
+ ProcessInstance<BpmnVariables> parentInstance =
callActivityProcess.createInstance(
+ BpmnVariables.create(singletonMap("test", "cascade")));
+ parentInstance.start();
+
+ // Sanity: subprocess must be present in the BPMN2_UserTask instances
table
+ assertThat(userTaskProcess.instances().stream().count())
+ .as("subprocess should have been
created").isGreaterThanOrEqualTo(1);
+
+ // Capture the subprocess instance id from the DB before migration
+ String childId;
+ try (Connection connection = getDataSource().getConnection();
+ ResultSet rs = connection.createStatement().executeQuery(
+ "SELECT id FROM process_instances WHERE process_id =
'BPMN2_UserTask' AND root_process_id = 'BPMN2_CallActivity'")) {
+ assertThat(rs.next()).as("child row should exist").isTrue();
+ childId = rs.getString(1);
+ }
+
+ // Migrate the call-activity process to a new id/version
+ callActivityProcess.instances().migrateAll("BPMN2_CallActivity_v2",
"2.0");
+
+ // The child subprocess row must have its
root_process_id/root_process_version updated
+ try (Connection connection = getDataSource().getConnection();
+ ResultSet rs = connection.createStatement().executeQuery(
+ "SELECT root_process_id, root_process_version FROM
process_instances WHERE id = '" + childId + "'")) {
+ assertThat(rs.next()).isTrue();
+ assertThat(rs.getString(1)).as("child root_process_id must be
updated").isEqualTo("BPMN2_CallActivity_v2");
+ assertThat(rs.getString(2)).as("child root_process_version must be
updated").isEqualTo("2.0");
+ }
+
+ // The in-memory unmarshalled instance must reflect the migrated root
columns,
+ // not the stale values baked into the payload before migration.
+ AbstractProcessInstance<?> childInstance =
(AbstractProcessInstance<?>) userTaskProcess.instances()
+ .findById(childId).get();
+ childInstance.executeInWorkflowProcessInstanceRead(pi -> {
+ assertThat(pi.getRootProcessId())
+ .as("unmarshalled child rootProcessId must be overridden
from DB column")
+ .isEqualTo("BPMN2_CallActivity_v2");
+ assertThat(pi.getRootProcessVersion())
+ .as("unmarshalled child rootProcessVersion must be
overridden from DB column")
+ .isEqualTo("2.0");
+ return null;
+ });
+ }
+
+ @Test
+ public void testMigrateRootCascadeVersioned() throws Exception {
+ // Same as testMigrateRootCascade but uses the versioned call-activity
(drools:version="1.0")
+ // so that root_process_version is stored as "1.0" rather than null.
+ Map<String, BpmnProcess> processes = createProcesses(getDataSource(),
lock(),
+ "BPMN2-CallActivity.bpmn2", "BPMN2-CallActivity-v2.bpmn2",
"BPMN2-UserTask.bpmn2");
+ BpmnProcess callActivityProcess = processes.get("BPMN2_CallActivity");
+ BpmnProcess userTaskProcess = processes.get("BPMN2_UserTask");
+
+ ProcessInstance<BpmnVariables> parentInstance =
callActivityProcess.createInstance(
+ BpmnVariables.create(singletonMap("test",
"cascade-versioned")));
+ parentInstance.start();
+
+ assertThat(userTaskProcess.instances().stream().count())
+ .as("subprocess should have been
created").isGreaterThanOrEqualTo(1);
+
+ String childId;
+ try (Connection connection = getDataSource().getConnection();
+ ResultSet rs = connection.createStatement().executeQuery(
+ "SELECT id FROM process_instances WHERE process_id =
'BPMN2_UserTask' AND root_process_id = 'BPMN2_CallActivity'")) {
+ assertThat(rs.next()).as("child row should exist").isTrue();
+ childId = rs.getString(1);
+ }
+
+ callActivityProcess.instances().migrateAll("BPMN2_CallActivity_v2",
"2.0");
+
+ try (Connection connection = getDataSource().getConnection();
+ ResultSet rs = connection.createStatement().executeQuery(
+ "SELECT root_process_id, root_process_version FROM
process_instances WHERE id = '" + childId + "'")) {
+ assertThat(rs.next()).isTrue();
+ assertThat(rs.getString(1)).as("child root_process_id must be
updated").isEqualTo("BPMN2_CallActivity_v2");
+ assertThat(rs.getString(2)).as("child root_process_version must be
updated").isEqualTo("2.0");
+ }
+
+ // The in-memory unmarshalled instance must reflect the migrated root
columns,
+ // not the stale values baked into the payload before migration.
+ AbstractProcessInstance<?> childInstance =
(AbstractProcessInstance<?>) userTaskProcess.instances()
+ .findById(childId).get();
+ childInstance.executeInWorkflowProcessInstanceRead(pi -> {
+ assertThat(pi.getRootProcessId())
+ .as("unmarshalled child rootProcessId must be overridden
from DB column")
+ .isEqualTo("BPMN2_CallActivity_v2");
+ assertThat(pi.getRootProcessVersion())
+ .as("unmarshalled child rootProcessVersion must be
overridden from DB column")
+ .isEqualTo("2.0");
+ return null;
+ });
+ }
+
+ @Test
+ public void testMigrateRootCascadeWithExplicitList() throws Exception {
+ // Uses the unversioned call-activity (root_process_version = null).
+ Map<String, BpmnProcess> processes = createProcesses(getDataSource(),
lock(),
+ "BPMN2-CallActivity.bpmn2", "BPMN2-CallActivity-v2.bpmn2",
"BPMN2-UserTask.bpmn2");
+ BpmnProcess callActivityProcess = processes.get("BPMN2_CallActivity");
+ BpmnProcess userTaskProcess = processes.get("BPMN2_UserTask");
+
+ // Start TWO call-activity instances – each spawns a BPMN2_UserTask
child.
+ ProcessInstance<BpmnVariables> parentInstance1 =
callActivityProcess.createInstance(
+ BpmnVariables.create(singletonMap("test",
"cascade-explicit-1")));
+ parentInstance1.start();
+
+ ProcessInstance<BpmnVariables> parentInstance2 =
callActivityProcess.createInstance(
+ BpmnVariables.create(singletonMap("test",
"cascade-explicit-2")));
+ parentInstance2.start();
+
+ // Sanity: both children must exist.
+ assertThat(userTaskProcess.instances().stream().count())
+ .as("two subprocesses should have been
created").isGreaterThanOrEqualTo(2);
+
+ // Resolve the child ids by their parent root_process_instance_id.
+ String childId1;
+ String childId2;
+ try (Connection connection = getDataSource().getConnection();
+ ResultSet rs = connection.createStatement().executeQuery(
+ "SELECT id, root_process_instance_id FROM
process_instances"
+ + " WHERE process_id = 'BPMN2_UserTask' AND
root_process_id = 'BPMN2_CallActivity'")) {
+ assertThat(rs.next()).as("first child row should exist").isTrue();
+ String firstChildId = rs.getString(1);
+ String firstRootInstanceId = rs.getString(2);
+
+ assertThat(rs.next()).as("second child row should exist").isTrue();
+ String secondChildId = rs.getString(1);
+ String secondRootInstanceId = rs.getString(2);
+
+ // Map child IDs back to parentInstance1 / parentInstance2.
+ if (firstRootInstanceId.equals(parentInstance1.id())) {
+ childId1 = firstChildId;
+ childId2 = secondChildId;
+ } else {
+ childId1 = secondChildId;
+ childId2 = firstChildId;
+ }
+ }
+
+ // Migrate ONLY parentInstance1 using the explicit-list overload.
+
callActivityProcess.instances().migrateProcessInstances("BPMN2_CallActivity_v2",
"2.0", parentInstance1.id());
+
+ // The child of the migrated parent must have its root columns updated.
+ try (Connection connection = getDataSource().getConnection();
+ ResultSet rs = connection.createStatement().executeQuery(
+ "SELECT root_process_id, root_process_version FROM
process_instances WHERE id = '" + childId1 + "'")) {
+ assertThat(rs.next()).isTrue();
+ assertThat(rs.getString(1)).as("migrated child root_process_id
must be updated").isEqualTo("BPMN2_CallActivity_v2");
+ assertThat(rs.getString(2)).as("migrated child
root_process_version must be updated").isEqualTo("2.0");
+ }
+
+ // The migrated child's in-memory instance must reflect the updated
root columns.
+ AbstractProcessInstance<?> migratedChild =
(AbstractProcessInstance<?>) userTaskProcess.instances()
+ .findById(childId1).get();
+ migratedChild.executeInWorkflowProcessInstanceRead(pi -> {
+ assertThat(pi.getRootProcessId())
+ .as("unmarshalled migrated child rootProcessId must be
overridden from DB column")
+ .isEqualTo("BPMN2_CallActivity_v2");
+ assertThat(pi.getRootProcessVersion())
+ .as("unmarshalled migrated child rootProcessVersion must
be overridden from DB column")
+ .isEqualTo("2.0");
+ return null;
+ });
+
+ // The child of the NOT-migrated parent must be left intact
(root_process_version = null — process has no version).
+ try (Connection connection = getDataSource().getConnection();
+ ResultSet rs = connection.createStatement().executeQuery(
+ "SELECT root_process_id, root_process_version FROM
process_instances WHERE id = '" + childId2 + "'")) {
+ assertThat(rs.next()).isTrue();
+ assertThat(rs.getString(1)).as("untouched child root_process_id
must remain unchanged").isEqualTo("BPMN2_CallActivity");
+ assertThat(rs.getString(2)).as("untouched child
root_process_version must remain unchanged").isNull();
+ }
+ }
+
+ @Test
+ public void testMigrateRootCascadeWithExplicitListVersioned() throws
Exception {
+ // Same as testMigrateRootCascadeWithExplicitList but uses the
versioned call-activity
+ // (drools:version="1.0") so that root_process_version is "1.0" rather
than null.
+ Map<String, BpmnProcess> processes = createProcesses(getDataSource(),
lock(),
+ "BPMN2-CallActivity-v1.bpmn2", "BPMN2-CallActivity-v2.bpmn2",
"BPMN2-UserTask.bpmn2");
+ BpmnProcess callActivityProcess = processes.get("BPMN2_CallActivity");
+ BpmnProcess userTaskProcess = processes.get("BPMN2_UserTask");
+
+ // Start TWO call-activity instances – each spawns a BPMN2_UserTask
child.
+ ProcessInstance<BpmnVariables> parentInstance1 =
callActivityProcess.createInstance(
+ BpmnVariables.create(singletonMap("test",
"cascade-explicit-versioned-1")));
+ parentInstance1.start();
+
+ ProcessInstance<BpmnVariables> parentInstance2 =
callActivityProcess.createInstance(
+ BpmnVariables.create(singletonMap("test",
"cascade-explicit-versioned-2")));
+ parentInstance2.start();
+
+ // Sanity: both children must exist.
+ assertThat(userTaskProcess.instances().stream().count())
+ .as("two subprocesses should have been
created").isGreaterThanOrEqualTo(2);
+
+ // Resolve the child ids by their parent root_process_instance_id.
+ String childId1;
+ String childId2;
+ try (Connection connection = getDataSource().getConnection();
+ ResultSet rs = connection.createStatement().executeQuery(
+ "SELECT id, root_process_instance_id FROM
process_instances"
+ + " WHERE process_id = 'BPMN2_UserTask' AND
root_process_id = 'BPMN2_CallActivity'")) {
+ assertThat(rs.next()).as("first child row should exist").isTrue();
+ String firstChildId = rs.getString(1);
+ String firstRootInstanceId = rs.getString(2);
+
+ assertThat(rs.next()).as("second child row should exist").isTrue();
+ String secondChildId = rs.getString(1);
+ String secondRootInstanceId = rs.getString(2);
+
+ // Map child IDs back to parentInstance1 / parentInstance2.
+ if (firstRootInstanceId.equals(parentInstance1.id())) {
+ childId1 = firstChildId;
+ childId2 = secondChildId;
+ } else {
+ childId1 = secondChildId;
+ childId2 = firstChildId;
+ }
+ }
+
+ // Migrate ONLY parentInstance1 using the explicit-list overload.
+
callActivityProcess.instances().migrateProcessInstances("BPMN2_CallActivity_v2",
"2.0", parentInstance1.id());
+
+ // The child of the migrated parent must have its root columns updated.
+ try (Connection connection = getDataSource().getConnection();
+ ResultSet rs = connection.createStatement().executeQuery(
+ "SELECT root_process_id, root_process_version FROM
process_instances WHERE id = '" + childId1 + "'")) {
+ assertThat(rs.next()).isTrue();
+ assertThat(rs.getString(1)).as("migrated child root_process_id
must be updated").isEqualTo("BPMN2_CallActivity_v2");
+ assertThat(rs.getString(2)).as("migrated child
root_process_version must be updated").isEqualTo("2.0");
+ }
+
+ // The migrated child's in-memory instance must reflect the updated
root columns.
+ AbstractProcessInstance<?> migratedChild =
(AbstractProcessInstance<?>) userTaskProcess.instances()
+ .findById(childId1).get();
+ migratedChild.executeInWorkflowProcessInstanceRead(pi -> {
+ assertThat(pi.getRootProcessId())
+ .as("unmarshalled migrated child rootProcessId must be
overridden from DB column")
+ .isEqualTo("BPMN2_CallActivity_v2");
+ assertThat(pi.getRootProcessVersion())
+ .as("unmarshalled migrated child rootProcessVersion must
be overridden from DB column")
+ .isEqualTo("2.0");
+ return null;
+ });
+
+ // The child of the NOT-migrated parent must be left intact
(root_process_version = "1.0").
+ try (Connection connection = getDataSource().getConnection();
+ ResultSet rs = connection.createStatement().executeQuery(
+ "SELECT root_process_id, root_process_version FROM
process_instances WHERE id = '" + childId2 + "'")) {
+ assertThat(rs.next()).isTrue();
+ assertThat(rs.getString(1)).as("untouched child root_process_id
must remain unchanged").isEqualTo("BPMN2_CallActivity");
+ assertThat(rs.getString(2)).as("untouched child
root_process_version must remain unchanged").isEqualTo("1.0");
+ }
+ }
+
@Test
public void testSignalStorage() {
BpmnProcess process = createProcess(getDataSource(), lock(),
"BPMN2-IntermediateCatchEventSignal.bpmn2");
diff --git
a/kogito-addons/common/persistence/jdbc/src/test/resources/BPMN2-CallActivity-v1.bpmn2
b/kogito-addons/common/persistence/jdbc/src/test/resources/BPMN2-CallActivity-v1.bpmn2
new file mode 100644
index 00000000000..c3eb97b0095
--- /dev/null
+++
b/kogito-addons/common/persistence/jdbc/src/test/resources/BPMN2-CallActivity-v1.bpmn2
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
+ xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
+ xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
+ xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
+ xmlns:drools="http://www.jboss.org/drools"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ id="_A7B32A2F-9AE6-474F-8AB5-6F7F40D45BCA"
+ targetNamespace="https://kie.apache.org/bpmn">
+ <process id="BPMN2_CallActivity" name="BPMN2-CallActivity"
isExecutable="true" drools:version="1.0">
+ <startEvent id="_E72D0298-CF01-4188-9958-EFDE076502F5" name="StartProcess">
+ <outgoing>_1A7B501C-A669-4205-9FFE-A83D5EE05859</outgoing>
+ </startEvent>
+ <callActivity id="_72853AC5-4DFC-456D-AE20-BC7B4AC2A7CD" name="Call
UserTask" calledElement="BPMN2_UserTask">
+ <extensionElements>
+ <drools:metaData name="customAbortParent">
+ <drools:metaValue>false</drools:metaValue>
+ </drools:metaData>
+ </extensionElements>
+ <incoming>_1A7B501C-A669-4205-9FFE-A83D5EE05859</incoming>
+ <outgoing>_C01C1053-95A8-42A1-ADD7-952A6D44CBC8</outgoing>
+ </callActivity>
+ <scriptTask id="_6F4E8823-0B6D-4441-9A21-FFBDB5AE78BC" name="Completed">
+ <incoming>_C01C1053-95A8-42A1-ADD7-952A6D44CBC8</incoming>
+ <outgoing>_C21AF008-7C03-489F-8DE2-7C36B2DBEB9C</outgoing>
+ <script>System.out.println("BPMN2_CallActivity completed");</script>
+ </scriptTask>
+ <endEvent id="_536D8501-15FE-4917-8B01-F74CC1E97BC1" name="EndProcess">
+ <incoming>_C21AF008-7C03-489F-8DE2-7C36B2DBEB9C</incoming>
+ </endEvent>
+ <sequenceFlow id="_1A7B501C-A669-4205-9FFE-A83D5EE05859"
sourceRef="_E72D0298-CF01-4188-9958-EFDE076502F5"
targetRef="_72853AC5-4DFC-456D-AE20-BC7B4AC2A7CD"/>
+ <sequenceFlow id="_C01C1053-95A8-42A1-ADD7-952A6D44CBC8"
sourceRef="_72853AC5-4DFC-456D-AE20-BC7B4AC2A7CD"
targetRef="_6F4E8823-0B6D-4441-9A21-FFBDB5AE78BC"/>
+ <sequenceFlow id="_C21AF008-7C03-489F-8DE2-7C36B2DBEB9C"
sourceRef="_6F4E8823-0B6D-4441-9A21-FFBDB5AE78BC"
targetRef="_536D8501-15FE-4917-8B01-F74CC1E97BC1"/>
+ </process>
+ <bpmndi:BPMNDiagram id="_A5312E1E-7503-4923-9318-CF7543292967">
+ <bpmndi:BPMNPlane id="_46670079-0E5B-4A48-B54A-8D068651E739"
bpmnElement="BPMN2_CallActivity">
+ <bpmndi:BPMNShape id="_A6AB348D-D6A7-48A9-BF03-E26D407B1EB8"
bpmnElement="_E72D0298-CF01-4188-9958-EFDE076502F5">
+ <dc:Bounds x="240" y="280" width="60" height="60"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="_F0992EF3-2BC7-4709-9BCB-2F90FEFC5BB4"
bpmnElement="_72853AC5-4DFC-456D-AE20-BC7B4AC2A7CD">
+ <dc:Bounds x="380" y="260" width="180" height="100"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="_FDF52CCC-FD9F-4BB7-A1FC-0AD2E62BA462"
bpmnElement="_6F4E8823-0B6D-4441-9A21-FFBDB5AE78BC">
+ <dc:Bounds x="620" y="260" width="180" height="100"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="_76DA0107-DEAE-49AA-A440-DE02D130B6DD"
bpmnElement="_536D8501-15FE-4917-8B01-F74CC1E97BC1">
+ <dc:Bounds x="880" y="280" width="60" height="60"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNEdge id="_8CC5BEB8-305A-4E6C-81C3-AEFAD990AA2F"
bpmnElement="_1A7B501C-A669-4205-9FFE-A83D5EE05859">
+ <di:waypoint x="270" y="310"/>
+ <di:waypoint x="470" y="310"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="_666A4480-F355-4A01-A35B-7EE4E2C7C2BB"
bpmnElement="_C01C1053-95A8-42A1-ADD7-952A6D44CBC8">
+ <di:waypoint x="470" y="310"/>
+ <di:waypoint x="710" y="310"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="_C08B9475-0A90-440B-AD22-0D7A9697D2D9"
bpmnElement="_C21AF008-7C03-489F-8DE2-7C36B2DBEB9C">
+ <di:waypoint x="710" y="310"/>
+ <di:waypoint x="910" y="310"/>
+ </bpmndi:BPMNEdge>
+ </bpmndi:BPMNPlane>
+ </bpmndi:BPMNDiagram>
+</definitions>
diff --git
a/kogito-addons/common/persistence/jdbc/src/test/resources/BPMN2-CallActivity-v2.bpmn2
b/kogito-addons/common/persistence/jdbc/src/test/resources/BPMN2-CallActivity-v2.bpmn2
new file mode 100644
index 00000000000..40279901f80
--- /dev/null
+++
b/kogito-addons/common/persistence/jdbc/src/test/resources/BPMN2-CallActivity-v2.bpmn2
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
+ xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
+ xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
+ xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
+ xmlns:drools="http://www.jboss.org/drools"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ id="_A7B32A2F-9AE6-474F-8AB5-6F7F40D45BCB"
+ targetNamespace="https://kie.apache.org/bpmn">
+ <process id="BPMN2_CallActivity_v2" name="BPMN2-CallActivity-v2"
isExecutable="true" drools:version="2.0">
+ <startEvent id="_E72D0298-CF01-4188-9958-EFDE076502F5" name="StartProcess">
+ <outgoing>_1A7B501C-A669-4205-9FFE-A83D5EE05859</outgoing>
+ </startEvent>
+ <callActivity id="_72853AC5-4DFC-456D-AE20-BC7B4AC2A7CD" name="Call
UserTask" calledElement="BPMN2_UserTask">
+ <extensionElements>
+ <drools:metaData name="customAbortParent">
+ <drools:metaValue>false</drools:metaValue>
+ </drools:metaData>
+ </extensionElements>
+ <incoming>_1A7B501C-A669-4205-9FFE-A83D5EE05859</incoming>
+ <outgoing>_C01C1053-95A8-42A1-ADD7-952A6D44CBC8</outgoing>
+ </callActivity>
+ <scriptTask id="_6F4E8823-0B6D-4441-9A21-FFBDB5AE78BC" name="Completed">
+ <incoming>_C01C1053-95A8-42A1-ADD7-952A6D44CBC8</incoming>
+ <outgoing>_C21AF008-7C03-489F-8DE2-7C36B2DBEB9C</outgoing>
+ <script>System.out.println("BPMN2_CallActivity_v2 completed");</script>
+ </scriptTask>
+ <endEvent id="_536D8501-15FE-4917-8B01-F74CC1E97BC1" name="EndProcess">
+ <incoming>_C21AF008-7C03-489F-8DE2-7C36B2DBEB9C</incoming>
+ </endEvent>
+ <sequenceFlow id="_1A7B501C-A669-4205-9FFE-A83D5EE05859"
sourceRef="_E72D0298-CF01-4188-9958-EFDE076502F5"
targetRef="_72853AC5-4DFC-456D-AE20-BC7B4AC2A7CD"/>
+ <sequenceFlow id="_C01C1053-95A8-42A1-ADD7-952A6D44CBC8"
sourceRef="_72853AC5-4DFC-456D-AE20-BC7B4AC2A7CD"
targetRef="_6F4E8823-0B6D-4441-9A21-FFBDB5AE78BC"/>
+ <sequenceFlow id="_C21AF008-7C03-489F-8DE2-7C36B2DBEB9C"
sourceRef="_6F4E8823-0B6D-4441-9A21-FFBDB5AE78BC"
targetRef="_536D8501-15FE-4917-8B01-F74CC1E97BC1"/>
+ </process>
+ <bpmndi:BPMNDiagram id="_A5312E1E-7503-4923-9318-CF7543292968">
+ <bpmndi:BPMNPlane id="_46670079-0E5B-4A48-B54A-8D068651E740"
bpmnElement="BPMN2_CallActivity_v2">
+ <bpmndi:BPMNShape id="_A6AB348D-D6A7-48A9-BF03-E26D407B1EB8"
bpmnElement="_E72D0298-CF01-4188-9958-EFDE076502F5">
+ <dc:Bounds x="240" y="280" width="60" height="60"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="_F0992EF3-2BC7-4709-9BCB-2F90FEFC5BB4"
bpmnElement="_72853AC5-4DFC-456D-AE20-BC7B4AC2A7CD">
+ <dc:Bounds x="380" y="260" width="180" height="100"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="_FDF52CCC-FD9F-4BB7-A1FC-0AD2E62BA462"
bpmnElement="_6F4E8823-0B6D-4441-9A21-FFBDB5AE78BC">
+ <dc:Bounds x="620" y="260" width="180" height="100"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="_76DA0107-DEAE-49AA-A440-DE02D130B6DD"
bpmnElement="_536D8501-15FE-4917-8B01-F74CC1E97BC1">
+ <dc:Bounds x="880" y="280" width="60" height="60"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNEdge id="_8CC5BEB8-305A-4E6C-81C3-AEFAD990AA2F"
bpmnElement="_1A7B501C-A669-4205-9FFE-A83D5EE05859">
+ <di:waypoint x="270" y="310"/>
+ <di:waypoint x="470" y="310"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="_666A4480-F355-4A01-A35B-7EE4E2C7C2BB"
bpmnElement="_C01C1053-95A8-42A1-ADD7-952A6D44CBC8">
+ <di:waypoint x="470" y="310"/>
+ <di:waypoint x="710" y="310"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="_C08B9475-0A90-440B-AD22-0D7A9697D2D9"
bpmnElement="_C21AF008-7C03-489F-8DE2-7C36B2DBEB9C">
+ <di:waypoint x="710" y="310"/>
+ <di:waypoint x="910" y="310"/>
+ </bpmndi:BPMNEdge>
+ </bpmndi:BPMNPlane>
+ </bpmndi:BPMNDiagram>
+</definitions>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]