This is an automated email from the ASF dual-hosted git repository.
gitgabrio pushed a commit to branch main
in repository
https://gitbox.apache.org/repos/asf/incubator-kie-kogito-runtimes.git
The following commit(s) were added to refs/heads/main by this push:
new d67f9297cb [incubator-kie-issues#1497] Using the
getSerializableNodeInstances inside ProtobufProcessInstanceWriter (#3707)
d67f9297cb is described below
commit d67f9297cbabcefd5cfe626fdd055a9bab24b4f9
Author: Gabriele Cardosi <[email protected]>
AuthorDate: Fri Oct 18 12:39:54 2024 +0200
[incubator-kie-issues#1497] Using the getSerializableNodeInstances inside
ProtobufProcessInstanceWriter (#3707)
* [incubator-kie-issues#1497] Using the getSerializableNodeInstances inside
ProtobufProcessInstanceWriter
* [incubator-kie-issues#1497] Overriding getSerializableNodeInstances
inside CompositeNodeInstance
* [incubator-kie-issues#1497] Implementing getNotSerializableClasses
inside CompositeNodeInstance - overriding in ForEachNodeInstance
* [incubator-kie-issues#1497] Unit-testing ForEachNodeInstance
* [incubator-kie-issues#1497] Improving Serializable Nodes management -
avoid stream/filter on each getSerializableNodeInstances invocation
* [incubator-kie-issues#1497] Fix formatting
* [incubator-kie-issues#1497] Fix imports
* [incubator-kie-issues#1497] Implemented
ProtobufProcessInstanceWriterTest.buildWorkflowContext unit test
* [incubator-kie-issues#1497] Removing serializableNodes list
* [incubator-kie-issues#1497] Reverting to modification only in
ForEachNodeInstance
* [incubator-kie-issues#1497] Fix format/imports
---------
Co-authored-by: Gabriele-Cardosi <[email protected]>
---
.../instance/node/CompositeNodeInstance.java | 6 +-
.../instance/node/ForEachNodeInstance.java | 21 ++-
.../instance/node/ForEachNodeInstanceTest.java | 75 +++++++++++
.../impl/ProtobufProcessInstanceWriter.java | 6 +-
.../impl/ProtobufProcessInstanceWriterTest.java | 149 +++++++++++++++++++++
5 files changed, 250 insertions(+), 7 deletions(-)
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/CompositeNodeInstance.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/CompositeNodeInstance.java
index 2612be7998..ea9a677462 100755
---
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/CompositeNodeInstance.java
+++
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/CompositeNodeInstance.java
@@ -54,7 +54,7 @@ import static
org.kie.kogito.internal.process.runtime.KogitoProcessInstance.STAT
/**
* Runtime counterpart of a composite node.
- *
+ *
*/
public class CompositeNodeInstance extends StateBasedNodeInstance implements
NodeInstanceContainer, EventNodeInstanceInterface,
EventBasedNodeInstanceInterface {
@@ -190,7 +190,7 @@ public class CompositeNodeInstance extends
StateBasedNodeInstance implements Nod
@Override
public void addNodeInstance(final NodeInstance nodeInstance) {
if (nodeInstance.getStringId() == null) {
- // assign new id only if it does not exist as it might already be
set by marshalling
+ // assign new id only if it does not exist as it might already be
set by marshalling
// it's important to keep same ids of node instances as they might
be references e.g. exclusive group
((NodeInstanceImpl)
nodeInstance).setId(UUID.randomUUID().toString());
}
@@ -204,7 +204,7 @@ public class CompositeNodeInstance extends
StateBasedNodeInstance implements Nod
@Override
public Collection<org.kie.api.runtime.process.NodeInstance>
getNodeInstances() {
- return new ArrayList<>(getNodeInstances(false));
+ return Collections.unmodifiableCollection(nodeInstances);
}
@Override
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/ForEachNodeInstance.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/ForEachNodeInstance.java
index 339f48d3f2..9b17022e46 100755
---
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/ForEachNodeInstance.java
+++
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/ForEachNodeInstance.java
@@ -26,6 +26,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
import org.jbpm.process.core.ContextContainer;
import org.jbpm.process.core.context.variable.VariableScope;
@@ -58,6 +60,8 @@ import org.mvel2.integration.impl.SimpleValueResolver;
public class ForEachNodeInstance extends CompositeContextNodeInstance {
private static final long serialVersionUID = 510L;
+ private static final Set<Class<? extends
org.kie.api.runtime.process.NodeInstance>> NOT_SERIALIZABLE_CLASSES =
Set.of(ForEachJoinNodeInstance.class); // using Arrays.asList to allow multiple
exclusions
+
public static final String TEMP_OUTPUT_VAR = "foreach_output";
private int totalInstances;
@@ -346,10 +350,25 @@ public class ForEachNodeInstance extends
CompositeContextNodeInstance {
@Override
public int getLevelForNode(String uniqueID) {
- // always 1 for for each
+ // always 1 for each
return 1;
}
+ @Override
+ public Collection<org.kie.api.runtime.process.NodeInstance>
getSerializableNodeInstances() {
+ return
getNodeInstances().stream().filter(ForEachNodeInstance::isSerializable).collect(Collectors.toUnmodifiableList());
+ }
+
+ /**
+ * Check if the given
<code>org.kie.api.runtime.process.NodeInstance</code> is serializable.
+ *
+ * @param toCheck
+ * @return
+ */
+ static boolean isSerializable(org.kie.api.runtime.process.NodeInstance
toCheck) {
+ return !NOT_SERIALIZABLE_CLASSES.contains(toCheck.getClass());
+ }
+
private class ForEachNodeInstanceResolverFactory extends
NodeInstanceResolverFactory {
private static final long serialVersionUID = -8856846610671009685L;
diff --git
a/jbpm/jbpm-flow/src/test/java/org/jbpm/workflow/instance/node/ForEachNodeInstanceTest.java
b/jbpm/jbpm-flow/src/test/java/org/jbpm/workflow/instance/node/ForEachNodeInstanceTest.java
new file mode 100644
index 0000000000..23194d3027
--- /dev/null
+++
b/jbpm/jbpm-flow/src/test/java/org/jbpm/workflow/instance/node/ForEachNodeInstanceTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+package org.jbpm.workflow.instance.node;
+
+import java.util.Collection;
+
+import org.junit.jupiter.api.Test;
+import org.kie.api.runtime.process.NodeInstance;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ForEachNodeInstanceTest {
+
+ @Test
+ void getNodeInstances() {
+ ForEachNodeInstance toTest = new ForEachNodeInstance();
+ CompositeNodeInstance compositeNodeInstance = new
CompositeNodeInstance();
+ toTest.addNodeInstance(compositeNodeInstance);
+ Collection<NodeInstance> nodeInstances = toTest.getNodeInstances();
+ assertThat(nodeInstances)
+ .isNotNull()
+ .hasSize(1)
+ .contains(compositeNodeInstance);
+ ForEachNodeInstance.ForEachJoinNodeInstance forEachJoinNodeInstance =
toTest.new ForEachJoinNodeInstance();
+ toTest.addNodeInstance(forEachJoinNodeInstance);
+ nodeInstances = toTest.getNodeInstances();
+ assertThat(nodeInstances)
+ .isNotNull()
+ .hasSize(2)
+ .contains(compositeNodeInstance, forEachJoinNodeInstance);
+ }
+
+ @Test
+ void getSerializableNodeInstances() {
+ ForEachNodeInstance toTest = new ForEachNodeInstance();
+ CompositeNodeInstance compositeNodeInstance = new
CompositeNodeInstance();
+ toTest.addNodeInstance(compositeNodeInstance);
+ Collection<NodeInstance> serializableNodeInstances =
toTest.getSerializableNodeInstances();
+ assertThat(serializableNodeInstances)
+ .isNotNull()
+ .hasSize(1)
+ .contains(compositeNodeInstance);
+ ForEachNodeInstance.ForEachJoinNodeInstance forEachJoinNodeInstance =
toTest.new ForEachJoinNodeInstance();
+ toTest.addNodeInstance(forEachJoinNodeInstance);
+ serializableNodeInstances = toTest.getSerializableNodeInstances();
+ assertThat(serializableNodeInstances)
+ .isNotNull()
+ .hasSize(1)
+ .contains(compositeNodeInstance);
+ }
+
+ @Test
+ void isSerializable() {
+ assertThat(ForEachNodeInstance.isSerializable(new
CompositeNodeInstance())).isTrue();
+ assertThat(ForEachNodeInstance.isSerializable(new
ForEachNodeInstance())).isTrue();
+ assertThat(ForEachNodeInstance.isSerializable(new
ForEachNodeInstance().new ForEachJoinNodeInstance())).isFalse();
+ }
+
+}
diff --git
a/jbpm/process-serialization-protobuf/src/main/java/org/jbpm/flow/serialization/impl/ProtobufProcessInstanceWriter.java
b/jbpm/process-serialization-protobuf/src/main/java/org/jbpm/flow/serialization/impl/ProtobufProcessInstanceWriter.java
index b0f67430db..700d7abd42 100644
---
a/jbpm/process-serialization-protobuf/src/main/java/org/jbpm/flow/serialization/impl/ProtobufProcessInstanceWriter.java
+++
b/jbpm/process-serialization-protobuf/src/main/java/org/jbpm/flow/serialization/impl/ProtobufProcessInstanceWriter.java
@@ -175,7 +175,7 @@ public class ProtobufProcessInstanceWriter {
return contexts;
}
- private KogitoTypesProtobuf.WorkflowContext
buildWorkflowContext(List<NodeInstance> nodeInstances,
+ protected KogitoTypesProtobuf.WorkflowContext
buildWorkflowContext(List<NodeInstance> nodeInstances,
List<ContextInstance> exclusiveGroupInstances,
List<Entry<String, Object>> variables,
List<Entry<String, Integer>> iterationlevels) {
@@ -248,8 +248,8 @@ public class ProtobufProcessInstanceWriter {
return null;
}
- private <T extends NodeInstanceContainer & ContextInstanceContainer &
ContextableInstance> WorkflowContext buildWorkflowContext(T nodeInstance) {
- List<NodeInstance> nodeInstances = new
ArrayList<>(nodeInstance.getNodeInstances());
+ protected <T extends NodeInstanceContainer & ContextInstanceContainer &
ContextableInstance> WorkflowContext buildWorkflowContext(T nodeInstance) {
+ List<NodeInstance> nodeInstances = new
ArrayList<>(nodeInstance.getSerializableNodeInstances());
List<ContextInstance> exclusiveGroupInstances =
nodeInstance.getContextInstances(ExclusiveGroup.EXCLUSIVE_GROUP);
VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
nodeInstance.getContextInstance(VariableScope.VARIABLE_SCOPE);
List<Map.Entry<String, Object>> variables = (variableScopeInstance !=
null) ? new ArrayList<>(variableScopeInstance.getVariables().entrySet()) :
Collections.emptyList();
diff --git
a/jbpm/process-serialization-protobuf/src/test/java/org/jbpm/flow/serialization/impl/ProtobufProcessInstanceWriterTest.java
b/jbpm/process-serialization-protobuf/src/test/java/org/jbpm/flow/serialization/impl/ProtobufProcessInstanceWriterTest.java
new file mode 100644
index 0000000000..4d37ade30f
--- /dev/null
+++
b/jbpm/process-serialization-protobuf/src/test/java/org/jbpm/flow/serialization/impl/ProtobufProcessInstanceWriterTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+package org.jbpm.flow.serialization.impl;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+import org.jbpm.flow.serialization.MarshallerContextName;
+import org.jbpm.flow.serialization.NodeInstanceWriter;
+import org.jbpm.flow.serialization.ObjectMarshallerStrategyHelper;
+import org.jbpm.process.core.context.variable.VariableScope;
+import org.jbpm.process.instance.ContextInstance;
+import org.jbpm.process.instance.context.variable.VariableScopeInstance;
+import org.jbpm.ruleflow.core.WorkflowElementIdentifierFactory;
+import org.jbpm.util.JbpmClassLoaderUtil;
+import org.jbpm.workflow.core.impl.WorkflowProcessImpl;
+import org.jbpm.workflow.instance.node.ForEachNodeInstance;
+import org.jbpm.workflow.instance.node.HumanTaskNodeInstance;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.kie.api.definition.process.WorkflowElementIdentifier;
+import org.kie.api.runtime.process.NodeInstance;
+import org.kie.kogito.internal.process.runtime.KogitoProcessRuntime;
+import org.kie.kogito.process.impl.AbstractProcess;
+import org.mockito.ArgumentCaptor;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class ProtobufProcessInstanceWriterTest {
+
+ private static AbstractProcess<?> mockProcess;
+ private static NodeInstanceWriter[] nodeInstanceWriters;
+ private ProtobufProcessMarshallerWriteContext writeContext;
+
+ @BeforeAll
+ static void setup() {
+ ServiceLoader<NodeInstanceWriter> writerLoader =
ServiceLoader.load(NodeInstanceWriter.class,
JbpmClassLoaderUtil.findClassLoader());
+ int items = (int) writerLoader.stream().count();
+ nodeInstanceWriters =
writerLoader.stream().map(ServiceLoader.Provider::get).map(NodeInstanceWriter.class::cast).toArray(value
-> new NodeInstanceWriter[items]);
+ mockProcess = getMockedProcess();
+ }
+
+ @BeforeEach
+ void init() {
+ writeContext = new ProtobufProcessMarshallerWriteContext(new
ByteArrayOutputStream());
+ writeContext.set(MarshallerContextName.OBJECT_MARSHALLING_STRATEGIES,
ObjectMarshallerStrategyHelper.defaultStrategies());
+ writeContext.set(MarshallerContextName.MARSHALLER_PROCESS,
mockProcess);
+
writeContext.set(MarshallerContextName.MARSHALLER_NODE_INSTANCE_WRITER,
nodeInstanceWriters);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ void buildWorkflowContext() {
+ ProtobufProcessInstanceWriter spiedProtobufProcessInstanceWriter =
spy(new ProtobufProcessInstanceWriter(writeContext));
+ ForEachNodeInstance nodeInstance = getNodeInstanceContainer();
+ try {
+
spiedProtobufProcessInstanceWriter.buildWorkflowContext(nodeInstance);
+ } catch (Exception e) {
+ // expected due to partial instantiation
+ assertThat(e).isInstanceOf(NullPointerException.class);
+ ArgumentCaptor<List<NodeInstance>> nodeInstancesCapture =
ArgumentCaptor.forClass(ArrayList.class);
+ ArgumentCaptor<List<ContextInstance>>
exclusiveGroupInstancesCapture = ArgumentCaptor.forClass(ArrayList.class);
+ ArgumentCaptor<List<Map.Entry<String, Object>>> variablesCapture =
ArgumentCaptor.forClass(ArrayList.class);
+ ArgumentCaptor<List<Map.Entry<String, Integer>>>
iterationlevelsCapture = ArgumentCaptor.forClass(ArrayList.class);
+
verify(spiedProtobufProcessInstanceWriter).buildWorkflowContext(nodeInstancesCapture.capture(),
exclusiveGroupInstancesCapture.capture(), variablesCapture.capture(),
+ iterationlevelsCapture.capture());
+ Collection<NodeInstance> expected =
nodeInstance.getSerializableNodeInstances();
+ List<NodeInstance> retrieved = nodeInstancesCapture.getValue();
+
assertThat(retrieved).isNotNull().hasSize(expected.size()).allMatch(expected::contains);
+ }
+ }
+
+ private ForEachNodeInstance getNodeInstanceContainer() {
+ String id = "NodeInstanceContainer";
+ ForEachNodeInstance toReturn = new ForEachNodeInstance();
+ toReturn.setId(id);
+ toReturn.setLevel(1);
+ toReturn.addNodeInstance(getNodeInstanceSerializable(id));
+ toReturn.addNodeInstance(getNodeInstanceNotSerializable(id));
+ toReturn.setNodeId(getWorkflowElementIdentifier(id));
+ toReturn.setContextInstance(VariableScope.VARIABLE_SCOPE, new
VariableScopeInstance());
+ Collection<NodeInstance> nodeInstances = toReturn.getNodeInstances();
+ assertThat(nodeInstances)
+ .isNotNull()
+ .hasSize(2)
+ .anyMatch(HumanTaskNodeInstance.class::isInstance)
+
.anyMatch(ForEachNodeInstance.ForEachJoinNodeInstance.class::isInstance);
+ Collection<NodeInstance> serializableNodeInstances =
toReturn.getSerializableNodeInstances();
+ assertThat(serializableNodeInstances)
+ .isNotNull()
+ .hasSize(1)
+ .allMatch(HumanTaskNodeInstance.class::isInstance);
+ return toReturn;
+ }
+
+ private ForEachNodeInstance.ForEachJoinNodeInstance
getNodeInstanceNotSerializable(String parent) {
+ String id = String.format("%s-%s", parent,
"nestedNodeInstanceNotSerializable");
+ ForEachNodeInstance.ForEachJoinNodeInstance toReturn = new
ForEachNodeInstance().new ForEachJoinNodeInstance();
+ toReturn.setId(id);
+ toReturn.setLevel(2);
+ return toReturn;
+ }
+
+ private HumanTaskNodeInstance getNodeInstanceSerializable(String parent) {
+ String id = String.format("%s-%s", parent,
"nestedNodeInstanceSerializable");
+ HumanTaskNodeInstance toReturn = new HumanTaskNodeInstance();
+ toReturn.setId(id);
+ toReturn.setNodeId(getWorkflowElementIdentifier(id));
+ return toReturn;
+ }
+
+ private WorkflowElementIdentifier getWorkflowElementIdentifier(String
parent) {
+ String id = String.format("%s-%s", parent,
"workflowElementIdentifier");
+ return WorkflowElementIdentifierFactory.fromExternalFormat(id);
+ }
+
+ private static AbstractProcess<?> getMockedProcess() {
+ AbstractProcess<?> toReturn = mock(AbstractProcess.class);
+
when(toReturn.getProcessRuntime()).thenReturn(mock(KogitoProcessRuntime.class));
+ when(toReturn.get()).thenReturn(new WorkflowProcessImpl());
+ return toReturn;
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]