Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync main branch with Apache main branch #34

Merged
merged 6 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .ci/jenkins/tests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

<groovy.core.version>2.4.11</groovy.core.version>
<groovy.gmaven.pluginVersion>1.6.1</groovy.gmaven.pluginVersion>
<google.guava.version>29.0-jre</google.guava.version>
<google.guava.version>32.0.0-jre</google.guava.version>

<jenkins-spock.version>2.0.0</jenkins-spock.version>
<jenkins.version>2.334</jenkins.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.Map;
import java.util.stream.Stream;

import org.drools.codegen.common.AppPaths;
import org.drools.io.FileSystemResource;
import org.drools.scenariosimulation.api.model.ScenarioSimulationModel;
import org.drools.scenariosimulation.api.model.ScesimModelDescriptor;
Expand All @@ -53,7 +54,7 @@ public class KogitoDMNScenarioRunnerHelper extends DMNScenarioRunnerHelper {

private DMNRuntime dmnRuntime = initDmnRuntime();

private static final String targetFolder = File.separator + "target" + File.separator;
private static final String targetFolder = File.separator + AppPaths.TARGET_DIR + File.separator;
private static final String generatedResourcesFolder = targetFolder + "generated-resources" + File.separator;

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,21 @@
import org.jbpm.flow.migration.model.ProcessDefinitionMigrationPlan;
import org.jbpm.ruleflow.instance.RuleFlowProcessInstance;
import org.jbpm.workflow.instance.impl.NodeInstanceImpl;
import org.kie.kogito.Model;
import org.kie.kogito.internal.process.runtime.KogitoNodeInstance;
import org.kie.kogito.internal.process.runtime.KogitoWorkflowProcessInstance;
import org.kie.kogito.process.Processes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.google.common.base.Functions.identity;
import static java.util.stream.Collectors.toMap;

/**
* The migration system is limited in this way.
* Cannot have more that one identifier process deployed (version is fixed)
* if there are several migration plans defined for the same source only one is taken into account
*/
public class MigrationPlanService {
private static final Logger LOGGER = LoggerFactory.getLogger(MigrationPlanService.class);

Expand All @@ -49,8 +56,8 @@ public MigrationPlanService(MigrationPlanProvider migrationPlanProvider) {
this.migrations.putAll(this.migrationPlanProvider.findMigrationPlans().stream().collect(toMap(MigrationPlan::getSource, identity())));
}

public void migrateProcessElement(KogitoWorkflowProcessInstance processInstance) {
MigrationPlan plan = getMigrationPlan(processInstance);
public void migrateProcessElement(Processes processes, KogitoWorkflowProcessInstance processInstance) {
MigrationPlan plan = getMigrationPlan(processes, processInstance);
if (plan != null) {
// the process will have to do nothing as it is done by the engine itself
LOGGER.info("Process instance {} will be migrated from {} to {} with plan {}",
Expand All @@ -67,9 +74,9 @@ public void migrateProcessElement(KogitoWorkflowProcessInstance processInstance)
}
}

public void migrateNodeElement(KogitoNodeInstance nodeInstance) {
public void migrateNodeElement(Processes processes, KogitoNodeInstance nodeInstance) {
KogitoWorkflowProcessInstance pi = (KogitoWorkflowProcessInstance) nodeInstance.getProcessInstance();
MigrationPlan plan = getMigrationPlan(pi);
MigrationPlan plan = getMigrationPlan(processes, pi);
if (plan == null) {
return;
}
Expand All @@ -79,14 +86,63 @@ public void migrateNodeElement(KogitoNodeInstance nodeInstance) {
impl.setNodeId(plan.getProcessMigrationPlan().getNodeMigratedFor(nodeInstance));
}

private MigrationPlan getMigrationPlan(KogitoWorkflowProcessInstance processInstance) {
// we check the target deployed in the container is the same as the target in the migration plan
private MigrationPlan getMigrationPlan(Processes processes, KogitoWorkflowProcessInstance processInstance) {
// first check if we need a migration as the process being set should be not be the same as the process set in the
// process being loaded.
String currentProcessId = processInstance.getProcess().getId();
String currentVersion = processInstance.getProcess().getVersion();
ProcessDefinitionMigrationPlan currentProcessDefinition = new ProcessDefinitionMigrationPlan(currentProcessId, currentVersion);

RuleFlowProcessInstance pi = (RuleFlowProcessInstance) processInstance;
ProcessDefinitionMigrationPlan processStateDefinition = new ProcessDefinitionMigrationPlan(pi.getProcessId(), pi.getProcessVersion());

// check if definition and state match. we don't need to perform any migration.
if (currentProcessDefinition.equals(processStateDefinition)) {
return null;
}

// there is no migration plan define for the source
MigrationPlan plan = migrations.get(processStateDefinition);
if (plan == null) {
LOGGER.debug("No migration plan defined for process state {}.", processStateDefinition);
return null;
}

// current process definition matches the target process of the migration plan
ProcessDefinitionMigrationPlan targetDefinition = plan.getProcessMigrationPlan().getTargetProcessDefinition();
if (!targetDefinition.equals(currentProcessDefinition)) {
LOGGER.debug("Migration plan found for {} does not match target definition {}, Found plan to {}.", processStateDefinition, currentProcessDefinition, targetDefinition);
return null;
}

// target process not being deployed
if (!processes.processIds().contains(targetDefinition.getProcessId())) {
LOGGER.debug("No migration target defintion deployed in this container {} for migrating {}.", targetDefinition, processStateDefinition);
return null;
}

// target process not matching version
org.kie.kogito.process.Process<? extends Model> process = processes.processById(targetDefinition.getProcessId());
ProcessDefinitionMigrationPlan targetDeployed =
new ProcessDefinitionMigrationPlan(process.id(), process.version());

return targetDeployed.equals(targetDefinition) ? plan : null;
}

public boolean isEqualVersion(Processes processes, KogitoWorkflowProcessInstance processInstance) {
String currentProcessId = processInstance.getProcess().getId();
String currentVersion = processInstance.getProcess().getVersion();
ProcessDefinitionMigrationPlan currentProcessDefinition = new ProcessDefinitionMigrationPlan(currentProcessId, currentVersion);

RuleFlowProcessInstance pi = (RuleFlowProcessInstance) processInstance;
ProcessDefinitionMigrationPlan pd =
new ProcessDefinitionMigrationPlan(pi.getProcessId(), pi.getProcessVersion());
return migrations.get(pd);
ProcessDefinitionMigrationPlan processStateDefinition = new ProcessDefinitionMigrationPlan(pi.getProcessId(), pi.getProcessVersion());

// check if definition and state match. we don't need to perform any migration.
return currentProcessDefinition.equals(processStateDefinition);
}

public boolean shouldMigrate(KogitoWorkflowProcessInstance processInstance) {
return getMigrationPlan(processInstance) != null;
public boolean hasMigrationPlan(Processes processes, KogitoWorkflowProcessInstance processInstance) {
return getMigrationPlan(processes, processInstance) != null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.jbpm.flow.migration.MigrationPlanFile;
Expand All @@ -49,15 +51,15 @@ public class FileSystemMigrationPlanFileProvider implements MigrationPlanFilePro
public static final String EXPLODED_MIGRATION_PLAN_FOLDER = "META-INF/migration-plan/";
public static final String MIGRATION_PLAN_FOLDER = "/META-INF/migration-plan/";

private List<URI> rootPaths;
private Set<URI> rootPaths;

public FileSystemMigrationPlanFileProvider() {
try {
List<URL> url = Collections.list(JbpmClassLoaderUtil.findClassLoader().getResources(MIGRATION_PLAN_FOLDER));
if (url.isEmpty()) {
url = Collections.list(JbpmClassLoaderUtil.findClassLoader().getResources(EXPLODED_MIGRATION_PLAN_FOLDER));
}
this.rootPaths = url.stream().map(this::toURI).filter(Optional::isPresent).map(Optional::get).toList();
this.rootPaths = url.stream().map(this::toURI).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toSet());
} catch (IOException e) {
throw new IllegalArgumentException("error trying to get Migration Plan folder");
}
Expand All @@ -72,7 +74,7 @@ private Optional<URI> toURI(URL e) {
}

public FileSystemMigrationPlanFileProvider(URI rootPath) {
this.rootPaths = List.of(rootPath);
this.rootPaths = Set.of(rootPath);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@

import org.jbpm.flow.migration.MigrationPlanService;
import org.jbpm.flow.serialization.ProcessInstanceMarshallerListener;
import org.jbpm.ruleflow.instance.RuleFlowProcessInstance;
import org.kie.kogito.internal.process.runtime.KogitoNodeInstance;
import org.kie.kogito.internal.process.runtime.KogitoProcessRuntime;
import org.kie.kogito.internal.process.runtime.KogitoWorkflowProcessInstance;
import org.kie.kogito.process.Processes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -41,22 +43,28 @@ public StandardMigrationProcessInstanceMarshallerListener() {
@SuppressWarnings("deprecation")
@Override
public void afterUnmarshallProcess(KogitoProcessRuntime runtime, KogitoWorkflowProcessInstance processInstance) {
if (!migrationPlanService.shouldMigrate(processInstance)) {
if (!migrationPlanService.hasMigrationPlan(runtime.getApplication().get(Processes.class), processInstance)) {
if (!this.migrationPlanService.isEqualVersion(runtime.getApplication().get(Processes.class), processInstance)) {
LOGGER.debug("Process State version and process container mismatch. Migrating process without plan.");
RuleFlowProcessInstance ruleFlowProcessInstance = (RuleFlowProcessInstance) processInstance;
ruleFlowProcessInstance.setProcess(ruleFlowProcessInstance.getProcess());
}
return;
}
LOGGER.debug("Migration processInstance {}", processInstance);
migrationPlanService.migrateProcessElement(processInstance);
LOGGER.debug("Migration processInstance state {}-{} and definition {}-{}",
processInstance.getProcessId(), processInstance.getProcessVersion(), processInstance.getProcess().getId(), processInstance.getProcess().getVersion());
migrationPlanService.migrateProcessElement(runtime.getApplication().get(Processes.class), processInstance);
runtime.getProcessEventSupport().fireOnMigration(processInstance, runtime.getKieRuntime());

}

@Override
public void afterUnmarshallNode(KogitoProcessRuntime runtime, KogitoNodeInstance nodeInstance) {
if (!migrationPlanService.shouldMigrate((KogitoWorkflowProcessInstance) nodeInstance.getProcessInstance())) {
if (!migrationPlanService.hasMigrationPlan(runtime.getApplication().get(Processes.class), (KogitoWorkflowProcessInstance) nodeInstance.getProcessInstance())) {
return;
}
LOGGER.debug("Migration nodeInstance {}", nodeInstance);
migrationPlanService.migrateNodeElement(nodeInstance);
migrationPlanService.migrateNodeElement(runtime.getApplication().get(Processes.class), nodeInstance);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ public void testReadingFiles() {
plan.setProcessMigrationPlan(pdmp);

assertThat(plans)
.hasSize(1)
.containsExactly(plan);
.hasSize(2)
.contains(plan);

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,36 +18,91 @@
*/
package org.jbpm.flow.migration;

import java.util.Collections;

import org.jbpm.ruleflow.instance.RuleFlowProcessInstance;
import org.jbpm.workflow.instance.impl.ExtendedNodeInstanceImpl;
import org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.kie.kogito.process.Processes;
import org.mockito.Mockito;

import static org.assertj.core.api.Assertions.assertThat;
import static org.jbpm.ruleflow.core.WorkflowElementIdentifierFactory.fromExternalFormat;
import static org.mockito.Mockito.when;

@TestInstance(Lifecycle.PER_CLASS)
public class MigrationPlanServiceTest {

Processes processes;
org.kie.kogito.process.Process processB;

@BeforeAll
public void init() {
processes = Mockito.mock(Processes.class);
when(processes.processIds()).thenReturn(Collections.singletonList("process_B"));

processB = Mockito.mock(org.kie.kogito.process.Process.class);
when(processes.processById("process_B")).thenReturn(processB);
when(processB.id()).thenReturn("process_B");
when(processB.version()).thenReturn("2");
}

@Test
public void testMigrationProcessInstanceSameProcessDefinition() {
MigrationPlanService service = new MigrationPlanService();

WorkflowProcessInstanceImpl processImpl = new RuleFlowProcessInstance();
processImpl.setInternalProcess(new DummyProcess("process_A", "1"));
processImpl.setProcessId("process_A");
processImpl.setProcessVersion("1");
service.migrateProcessElement(processes, processImpl);

assertThat(processImpl)
.hasFieldOrPropertyWithValue("processId", "process_A")
.hasFieldOrPropertyWithValue("processVersion", "1");

}

@Test
public void testMigrationProcessInstance() {
MigrationPlanService service = new MigrationPlanService();

WorkflowProcessInstanceImpl processImpl = new RuleFlowProcessInstance();
processImpl.setProcess(new DummyProcess("process_A", "1"));
service.migrateProcessElement(processImpl);
processImpl.setInternalProcess(new DummyProcess("process_B", "2"));
processImpl.setProcessId("process_A");
processImpl.setProcessVersion("1");
service.migrateProcessElement(processes, processImpl);

assertThat(processImpl)
.hasFieldOrPropertyWithValue("processId", "process_B")
.hasFieldOrPropertyWithValue("processVersion", "2");

}

@Test
public void testMigrationProcessInstanceNotMatchingVersion() {
MigrationPlanService service = new MigrationPlanService();

WorkflowProcessInstanceImpl processImpl = new RuleFlowProcessInstance();
processImpl.setProcess(new DummyProcess("process_D", "1"));
service.migrateProcessElement(processes, processImpl);

assertThat(processImpl)
.hasFieldOrPropertyWithValue("processId", "process_D")
.hasFieldOrPropertyWithValue("processVersion", "1");

}

@Test
public void testMigrationProcessNonExisting() {
MigrationPlanService service = new MigrationPlanService();
WorkflowProcessInstanceImpl processImpl = new RuleFlowProcessInstance();
processImpl.setProcess(new DummyProcess("process_C", "1"));
service.migrateProcessElement(processImpl);
service.migrateProcessElement(processes, processImpl);

assertThat(processImpl)
.hasFieldOrPropertyWithValue("processId", "process_C")
Expand All @@ -59,7 +114,7 @@ public void testMigrationProcessNotRightVersion() {
MigrationPlanService service = new MigrationPlanService();
WorkflowProcessInstanceImpl processImpl = new RuleFlowProcessInstance();
processImpl.setProcess(new DummyProcess("process_A", "3"));
service.migrateProcessElement(processImpl);
service.migrateProcessElement(processes, processImpl);

assertThat(processImpl)
.hasFieldOrPropertyWithValue("processId", "process_A")
Expand All @@ -70,12 +125,14 @@ public void testMigrationProcessNotRightVersion() {
public void testMigrationNode() {
MigrationPlanService service = new MigrationPlanService();
WorkflowProcessInstanceImpl processImpl = new RuleFlowProcessInstance();
processImpl.setProcess(new DummyProcess("process_A", "1"));
processImpl.setInternalProcess(new DummyProcess("process_B", "2"));
processImpl.setProcessId("process_A");
processImpl.setProcessVersion("1");
ExtendedNodeInstanceImpl nodeInstanceImpl = new ExtendedNodeInstanceImpl() {
};
nodeInstanceImpl.setProcessInstance(processImpl);
nodeInstanceImpl.setNodeId(fromExternalFormat("node_1"));
service.migrateNodeElement(nodeInstanceImpl);
service.migrateNodeElement(processes, nodeInstanceImpl);

assertThat(nodeInstanceImpl)
.hasFieldOrPropertyWithValue("nodeId", fromExternalFormat("node_2"));
Expand All @@ -85,12 +142,14 @@ public void testMigrationNode() {
public void testMigrationNodeNextItem() {
MigrationPlanService service = new MigrationPlanService();
WorkflowProcessInstanceImpl processImpl = new RuleFlowProcessInstance();
processImpl.setProcess(new DummyProcess("process_A", "1"));
processImpl.setInternalProcess(new DummyProcess("process_B", "2"));
processImpl.setProcessId("process_A");
processImpl.setProcessVersion("1");
ExtendedNodeInstanceImpl nodeInstanceImpl = new ExtendedNodeInstanceImpl() {
};
nodeInstanceImpl.setProcessInstance(processImpl);
nodeInstanceImpl.setNodeId(fromExternalFormat("node_2"));
service.migrateNodeElement(nodeInstanceImpl);
service.migrateNodeElement(processes, nodeInstanceImpl);

assertThat(nodeInstanceImpl)
.hasFieldOrPropertyWithValue("nodeId", fromExternalFormat("node_3"));
Expand All @@ -105,7 +164,7 @@ public void testMigrationNodeNonExistent() {
};
nodeInstanceImpl.setProcessInstance(processImpl);
nodeInstanceImpl.setNodeId(fromExternalFormat("node_3"));
service.migrateNodeElement(nodeInstanceImpl);
service.migrateNodeElement(processes, nodeInstanceImpl);

assertThat(nodeInstanceImpl)
.hasFieldOrPropertyWithValue("nodeId", fromExternalFormat("node_3"));
Expand All @@ -120,7 +179,7 @@ public void testMigrationNodeNotMigratedWrongProcess() {
};
nodeInstanceImpl.setProcessInstance(processImpl);
nodeInstanceImpl.setNodeId(fromExternalFormat("node_3"));
service.migrateNodeElement(nodeInstanceImpl);
service.migrateNodeElement(processes, nodeInstanceImpl);

assertThat(nodeInstanceImpl)
.hasFieldOrPropertyWithValue("nodeId", fromExternalFormat("node_3"));
Expand Down
Loading
Loading