This is an automated email from the ASF dual-hosted git repository.
josedee pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-kogito-apps.git
The following commit(s) were added to refs/heads/main by this push:
new c31279ebe [incubator-kie-isues#2321] Adding validations for REST WIH
parameters. (#2327)
c31279ebe is described below
commit c31279ebe533e5219fb965a3f8696b9c60e46aab
Author: Christine-Jose <[email protected]>
AuthorDate: Wed May 20 17:23:58 2026 +0530
[incubator-kie-isues#2321] Adding validations for REST WIH parameters.
(#2327)
* t Adding validations for REST WIH
* Review Comments
* Review Comments
* Review comments
---
.rat-excludes | 5 +
.../jitexecutor/bpmn/JITBPMNServiceImpl.java | 471 +++++++++++++++++++++
.../jitexecutor/bpmn/JITBPMNServiceImplTest.java | 65 +++
.../kie/kogito/jitexecutor/bpmn/TestingUtils.java | 10 +
.../resources/RestWIH_AllValid_Scenarios.bpmn2 | 289 +++++++++++++
.../src/test/resources/RestWIH_Invalid.bpmn2 | 195 +++++++++
.../src/test/resources/RestWIH_Valid.bpmn2 | 101 +++++
.../src/test/resources/RestWIH_Valid_Proper.bpmn2 | 112 +++++
.../src/test/resources/RestWIH_Valid_Simple.bpmn2 | 47 ++
9 files changed, 1295 insertions(+)
diff --git a/.rat-excludes b/.rat-excludes
index 08797b29e..f9371bde5 100644
--- a/.rat-excludes
+++ b/.rat-excludes
@@ -52,6 +52,11 @@
jitexecutor/jitexecutor-bpmn/src/test/resources/SingleProcess.bpmn2
jitexecutor/jitexecutor-bpmn/src/test/resources/SingleUnparsableModel.bpmn2
jitexecutor/jitexecutor-bpmn/src/test/resources/UnparsableModel.bpmn2
jitexecutor/jitexecutor-bpmn/src/test/resources/ValidModel.bpmn
+jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_AllValid_Scenarios.bpmn2
+jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Invalid.bpmn2
+jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Valid.bpmn2
+jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Valid_Proper.bpmn2
+jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Valid_Simple.bpmn2
jitexecutor/jitexecutor-dmn/src/main/resources/META-INF/resources/bundle.js
jobs/kogito-addons-springboot-embedded-jobs/src/test/resources/application.properties
jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/test/resources/application.properties
diff --git
a/jitexecutor/jitexecutor-bpmn/src/main/java/org/kie/kogito/jitexecutor/bpmn/JITBPMNServiceImpl.java
b/jitexecutor/jitexecutor-bpmn/src/main/java/org/kie/kogito/jitexecutor/bpmn/JITBPMNServiceImpl.java
index 601c3c6ea..abefebd90 100644
---
a/jitexecutor/jitexecutor-bpmn/src/main/java/org/kie/kogito/jitexecutor/bpmn/JITBPMNServiceImpl.java
+++
b/jitexecutor/jitexecutor-bpmn/src/main/java/org/kie/kogito/jitexecutor/bpmn/JITBPMNServiceImpl.java
@@ -21,9 +21,19 @@ package org.kie.kogito.jitexecutor.bpmn;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Reader;
+import java.io.StringReader;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
import org.drools.io.InputStreamResource;
import org.jbpm.bpmn2.xml.BPMNDISemanticModule;
@@ -31,8 +41,10 @@ import org.jbpm.bpmn2.xml.BPMNExtensionsSemanticModule;
import org.jbpm.bpmn2.xml.BPMNSemanticModule;
import org.jbpm.compiler.xml.XmlProcessReader;
import org.jbpm.compiler.xml.core.SemanticModules;
+import org.jbpm.process.core.Work;
import org.jbpm.process.core.validation.ProcessValidationError;
import org.jbpm.ruleflow.core.validation.RuleFlowProcessValidator;
+import org.jbpm.workflow.core.node.WorkItemNode;
import org.kie.api.definition.process.Process;
import org.kie.api.io.Resource;
import org.kie.kogito.jitexecutor.bpmn.responses.JITBPMNValidationResult;
@@ -55,6 +67,35 @@ public class JITBPMNServiceImpl implements JITBPMNService {
private static String ERROR_TEMPLATE = "Uri: %s - Process id: %s - name :
%s - error : %s";
+ private static final String NODE_ERROR_TEMPLATE = "Uri: %s - Process id:
%s - name: %s - Node: %s [%s] - error: %s";
+
+ // REST Work Item Handler validation constants
+ private static final String REST_TASK_TYPE = "Rest";
+ private static final String ACCESS_TOKEN_STRATEGY_PARAM =
"AccessTokenAcquisitionStrategy";
+ private static final String REST_SERVICE_CALL_TASK_ID_PARAM =
"RestServiceCallTaskId";
+ private static final String URL_PARAM = "Url";
+ private static final String METHOD_PARAM = "Method";
+ private static final String PROTOCOL_PARAM = "Protocol";
+ private static final String HOST_PARAM = "Host";
+ private static final String PORT_PARAM = "Port";
+ private static final String CONTENT_DATA_PARAM = "ContentData";
+ private static final String REQUEST_TIMEOUT_PARAM = "RequestTimeout";
+
+ private static final Set<String> VALID_STRATEGIES = new HashSet<>(
+ Arrays.asList("propagated", "configured", "none"));
+ private static final Set<String> VALID_HTTP_METHODS = new HashSet<>(
+ Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE"));
+ private static final Set<String> METHODS_WITH_BODY = new HashSet<>(
+ Arrays.asList("POST", "PUT", "PATCH"));
+ private static final Set<String> VALID_PROTOCOLS = new HashSet<>(
+ Arrays.asList("http", "https"));
+
+ private static final Pattern VALID_TASK_ID_PATTERN =
Pattern.compile("^[A-Za-z0-9_]+$");
+ private static final Pattern EXPRESSION_PATTERN =
Pattern.compile("^#\\{.+\\}$");
+ private static final Pattern URL_PLACEHOLDER_PATTERN =
Pattern.compile("\\{[^}]+\\}");
+ private static final Pattern QUERY_PARAM_PATTERN =
Pattern.compile("^QUERY_(.+)$");
+ private static final Pattern HEADER_PARAM_PATTERN =
Pattern.compile("^HEADER_(.+)$");
+
static {
BPMN_SEMANTIC_MODULES.addSemanticModule(new BPMNSemanticModule());
BPMN_SEMANTIC_MODULES.addSemanticModule(new
BPMNExtensionsSemanticModule());
@@ -95,6 +136,11 @@ public class JITBPMNServiceImpl implements JITBPMNService {
for (ProcessValidationError processValidationError :
processValidationErrors) {
toReturn.add(getErrorString(processValidationError,
resourceUri));
}
+ // REST Work Item Handler validation - parse XML to get
parameter values
+ Map<String, Map<String, String>> nodeParameters =
parseNodeParametersFromXml(modelXML);
+ for (Process process : processes) {
+ toReturn.addAll(validateRestWorkItems(process,
resourceUri, nodeParameters));
+ }
}
} catch (Throwable e) {
String error = e.getMessage() != null && !e.getMessage().isEmpty()
? e.getMessage() : e.toString();
@@ -137,4 +183,429 @@ public class JITBPMNServiceImpl implements JITBPMNService
{
String uri = resourceUri != null ? resourceUri : "(unknown)";
return String.format(ERROR_TEMPLATE, uri, failed.getId(),
failed.getName(), processValidationError.getMessage());
}
+
+ private static Collection<String> validateRestWorkItems(Process process,
String resourceUri, Map<String, Map<String, String>> nodeParameters) {
+ Collection<String> errors = new ArrayList<>();
+
+ if (process == null) {
+ return errors;
+ }
+
+ org.kie.api.definition.process.Node[] nodes =
((org.jbpm.workflow.core.WorkflowProcess) process).getNodes();
+ if (nodes == null) {
+ return errors;
+ }
+
+ for (org.kie.api.definition.process.Node node : nodes) {
+ if (node instanceof WorkItemNode) {
+ WorkItemNode workItemNode = (WorkItemNode) node;
+ Work work = workItemNode.getWork();
+
+ if (work != null && REST_TASK_TYPE.equals(work.getName())) {
+ // Try to get parameters using the node's UUID from
metadata
+ String nodeUuid = (String)
workItemNode.getMetaData().get("UniqueId");
+ Map<String, String> params = null;
+
+ if (nodeUuid != null) {
+ params = nodeParameters.get(nodeUuid);
+ }
+
+ if (params == null) {
+ params =
nodeParameters.get(String.valueOf(workItemNode.getId()));
+ }
+
+ errors.addAll(validateRestWorkItem(workItemNode, process,
resourceUri, params));
+ }
+ }
+ }
+
+ return errors;
+ }
+
+ private static Collection<String> validateRestWorkItem(WorkItemNode node,
Process process, String resourceUri, Map<String, String> nodeParams) {
+ Collection<String> errors = new ArrayList<>();
+ Work work = node.getWork();
+
+ errors.addAll(validateMethod(work, node, process, resourceUri,
nodeParams));
+
+ errors.addAll(validateUrl(work, node, process, resourceUri,
nodeParams));
+
+ errors.addAll(validateProtocolHostPort(work, node, process,
resourceUri, nodeParams));
+
+ errors.addAll(validateContentData(work, node, process, resourceUri,
nodeParams));
+
+ errors.addAll(validateQueryAndHeaderParams(work, node, process,
resourceUri, nodeParams));
+
+ errors.addAll(validateRequestTimeout(work, node, process, resourceUri,
nodeParams));
+
+ errors.addAll(validateAccessTokenStrategy(work, node, process,
resourceUri, nodeParams));
+
+ errors.addAll(validateRestServiceCallTaskId(work, node, process,
resourceUri, nodeParams));
+
+ return errors;
+ }
+
+ private static Collection<String> validateMethod(Work work, WorkItemNode
node, Process process, String resourceUri, Map<String, String> nodeParams) {
+ Collection<String> errors = new ArrayList<>();
+ String method = getParameterValue(work, nodeParams, METHOD_PARAM);
+
+ if (method != null && !method.trim().isEmpty()) {
+
+ if (isExpression(method)) {
+ return errors;
+ }
+
+ String upperMethod = method.toUpperCase();
+ if (!VALID_HTTP_METHODS.contains(upperMethod)) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("Method must be one of: GET, POST, PUT,
PATCH, DELETE, or an expression like #{expr}. Found: '%s'", method)));
+ }
+ }
+
+ return errors;
+ }
+
+ private static Collection<String> validateUrl(Work work, WorkItemNode
node, Process process, String resourceUri, Map<String, String> nodeParams) {
+ Collection<String> errors = new ArrayList<>();
+ String url = getParameterValue(work, nodeParams, URL_PARAM);
+
+ if (url == null || url.trim().isEmpty()) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ "Url is required for REST service call tasks"));
+ } else if (!isExpression(url)) {
+
+ if (!isValidUrlFormat(url)) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("Url must be a valid URL format. Found:
'%s'", url)));
+ } else {
+ boolean isRelativeUrl = url.startsWith("/") &&
!url.startsWith("//");
+ if (isRelativeUrl) {
+ String protocol = getParameterValue(work, nodeParams,
PROTOCOL_PARAM);
+ String host = getParameterValue(work, nodeParams,
HOST_PARAM);
+
+ if ((protocol == null || protocol.trim().isEmpty()) &&
(host == null || host.trim().isEmpty())) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("Url is a relative path '%s'.
Either provide a complete URL (e.g., 'https://example.com/users') or specify
Protocol and Host parameters", url)));
+ }
+ }
+ }
+ }
+
+ return errors;
+ }
+
+ private static Collection<String> validateProtocolHostPort(Work work,
WorkItemNode node, Process process, String resourceUri, Map<String, String>
nodeParams) {
+ Collection<String> errors = new ArrayList<>();
+ String url = getParameterValue(work, nodeParams, URL_PARAM);
+ String protocol = getParameterValue(work, nodeParams, PROTOCOL_PARAM);
+ String host = getParameterValue(work, nodeParams, HOST_PARAM);
+ String port = getParameterValue(work, nodeParams, PORT_PARAM);
+
+ if (protocol != null && !protocol.trim().isEmpty() &&
!isExpression(protocol)) {
+ String lowerProtocol = protocol.toLowerCase();
+ if (!VALID_PROTOCOLS.contains(lowerProtocol)) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("Protocol must be 'http' or 'https'.
Found: '%s'", protocol)));
+ }
+
+ if (url != null && !url.trim().isEmpty() && !isExpression(url)) {
+ if (url.startsWith("http://") || url.startsWith("https://")) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ "Protocol should not be specified when Url already
contains the protocol"));
+ }
+ }
+ }
+
+ if (host != null && !host.trim().isEmpty()) {
+ if (url != null && !url.trim().isEmpty() && !isExpression(url)) {
+ if (url.startsWith("http://") || url.startsWith("https://")) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ "Host should not be specified when Url already
contains the host"));
+ }
+ }
+ }
+
+ if (port != null && !port.trim().isEmpty() && !isExpression(port)) {
+ try {
+ int portNum = Integer.parseInt(port);
+ if (portNum < 1 || portNum > 65535) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("Port must be between 1 and 65535.
Found: %d", portNum)));
+ }
+ } catch (NumberFormatException e) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("Port must be a valid integer. Found:
'%s'", port)));
+ }
+
+ if (url != null && !url.trim().isEmpty() && !isExpression(url)) {
+ if (url.matches(".*:\\d+.*")) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ "Port should not be specified when Url already
contains the port"));
+ }
+ }
+ }
+
+ return errors;
+ }
+
+ private static Collection<String> validateContentData(Work work,
WorkItemNode node, Process process, String resourceUri, Map<String, String>
nodeParams) {
+ Collection<String> errors = new ArrayList<>();
+ String contentData = getParameterValue(work, nodeParams,
CONTENT_DATA_PARAM);
+ String method = getParameterValue(work, nodeParams, METHOD_PARAM);
+
+ if (contentData != null && !contentData.trim().isEmpty()) {
+
+ String effectiveMethod = (method != null &&
!method.trim().isEmpty()) ? method.toUpperCase() : "GET";
+
+ if (!isExpression(effectiveMethod) &&
!METHODS_WITH_BODY.contains(effectiveMethod)) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("ContentData should only be used with
methods that support request bodies (POST, PUT, PATCH). Current method: '%s'",
effectiveMethod)));
+ }
+ }
+
+ return errors;
+ }
+
+ private static Collection<String> validateQueryAndHeaderParams(Work work,
WorkItemNode node, Process process, String resourceUri, Map<String, String>
nodeParams) {
+ Collection<String> errors = new ArrayList<>();
+
+ Set<String> allParamNames = new
HashSet<>(work.getParameters().keySet());
+ if (nodeParams != null) {
+ allParamNames.addAll(nodeParams.keySet());
+ }
+
+ for (String paramName : allParamNames) {
+
+ if (QUERY_PARAM_PATTERN.matcher(paramName).matches()) {
+ String value = getParameterValue(work, nodeParams, paramName);
+ if (value == null || value.trim().isEmpty()) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("Query parameter '%s' has an empty
value", paramName)));
+ }
+ }
+
+ if (HEADER_PARAM_PATTERN.matcher(paramName).matches()) {
+ String value = getParameterValue(work, nodeParams, paramName);
+ if (value == null || value.trim().isEmpty()) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("Header parameter '%s' has an empty
value", paramName)));
+ }
+ }
+ }
+
+ return errors;
+ }
+
+ private static Collection<String> validateRequestTimeout(Work work,
WorkItemNode node, Process process, String resourceUri, Map<String, String>
nodeParams) {
+ Collection<String> errors = new ArrayList<>();
+ String timeout = getParameterValue(work, nodeParams,
REQUEST_TIMEOUT_PARAM);
+
+ if (timeout != null && !timeout.trim().isEmpty() &&
!isExpression(timeout)) {
+ try {
+ long timeoutValue = Long.parseLong(timeout);
+ if (timeoutValue < 0) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("RequestTimeout must be a
non-negative number. Found: %d", timeoutValue)));
+ }
+ } catch (NumberFormatException e) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("RequestTimeout must be a valid number.
Found: '%s'", timeout)));
+ }
+ }
+
+ return errors;
+ }
+
+ private static Collection<String> validateAccessTokenStrategy(Work work,
WorkItemNode node, Process process, String resourceUri, Map<String, String>
nodeParams) {
+ Collection<String> errors = new ArrayList<>();
+ String strategy = getParameterValue(work, nodeParams,
ACCESS_TOKEN_STRATEGY_PARAM);
+
+ if (strategy == null || strategy.trim().isEmpty()) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ "AccessTokenAcquisitionStrategy is required for REST
service call tasks"));
+ } else {
+ // Expressions are not allowed for this parameter
+ if (isExpression(strategy)) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("AccessTokenAcquisitionStrategy cannot
be an expression. Must be one of: propagated, configured, none. Found: '%s'",
strategy)));
+ } else if (!VALID_STRATEGIES.contains(strategy.toLowerCase())) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("AccessTokenAcquisitionStrategy must be
one of: propagated, configured, none. Found: '%s'", strategy)));
+ }
+ }
+
+ return errors;
+ }
+
+ private static Collection<String> validateRestServiceCallTaskId(Work work,
WorkItemNode node, Process process, String resourceUri, Map<String, String>
nodeParams) {
+ Collection<String> errors = new ArrayList<>();
+ String strategy = getParameterValue(work, nodeParams,
ACCESS_TOKEN_STRATEGY_PARAM);
+ String taskId = getParameterValue(work, nodeParams,
REST_SERVICE_CALL_TASK_ID_PARAM);
+
+ // RestServiceCallTaskId is required when strategy is "configured"
+ if (strategy != null &&
"configured".equalsIgnoreCase(strategy.trim())) {
+ if (taskId == null || taskId.trim().isEmpty()) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ "RestServiceCallTaskId is required when
AccessTokenAcquisitionStrategy is 'configured'"));
+ } else {
+ // Expressions are not allowed for this parameter
+ if (isExpression(taskId)) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("RestServiceCallTaskId cannot be an
expression. Found: '%s'", taskId)));
+ } else if (!VALID_TASK_ID_PATTERN.matcher(taskId).matches()) {
+ errors.add(formatNodeError(resourceUri, process, node,
+ String.format("RestServiceCallTaskId must contain
only alphanumeric characters and underscores. Found: '%s'", taskId)));
+ }
+ }
+ }
+
+ return errors;
+ }
+
+ private static String getParameterValue(Work work, Map<String, String>
nodeParams, String paramName) {
+ Object value = work.getParameter(paramName);
+ if (value != null) {
+ return value.toString();
+ }
+
+ if (nodeParams != null && nodeParams.containsKey(paramName)) {
+ return nodeParams.get(paramName);
+ }
+
+ return null;
+ }
+
+ private static Map<String, Map<String, String>>
parseNodeParametersFromXml(String modelXML) {
+ Map<String, Map<String, String>> result = new HashMap<>();
+
+ try {
+ DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ org.w3c.dom.Document doc = builder.parse(new
org.xml.sax.InputSource(new StringReader(modelXML)));
+
+ org.w3c.dom.NodeList tasks = doc.getElementsByTagNameNS("*",
"task");
+ if (tasks.getLength() == 0) {
+ tasks = doc.getElementsByTagName("task");
+ }
+
+ for (int i = 0; i < tasks.getLength(); i++) {
+ org.w3c.dom.Element task = (org.w3c.dom.Element) tasks.item(i);
+ String taskId = task.getAttribute("id");
+
+ if (taskId != null && !taskId.isEmpty()) {
+ Map<String, String> params = new HashMap<>();
+
+ // Find dataInputAssociation elements
+ org.w3c.dom.NodeList associations =
task.getElementsByTagNameNS("*", "dataInputAssociation");
+ if (associations.getLength() == 0) {
+ associations =
task.getElementsByTagName("dataInputAssociation");
+ }
+
+ for (int j = 0; j < associations.getLength(); j++) {
+ org.w3c.dom.Element association =
(org.w3c.dom.Element) associations.item(j);
+
+ // Get targetRef (parameter name)
+ org.w3c.dom.NodeList targetRefs =
association.getElementsByTagNameNS("*", "targetRef");
+ if (targetRefs.getLength() == 0) {
+ targetRefs =
association.getElementsByTagName("targetRef");
+ }
+
+ if (targetRefs.getLength() > 0) {
+ String targetRef =
targetRefs.item(0).getTextContent().trim();
+
+ // Extract parameter name from targetRef
+ String paramName =
getParameterNameFromDataInputId(task, targetRef);
+
+ // Get the value from assignment/from element
+ org.w3c.dom.NodeList assignments =
association.getElementsByTagNameNS("*", "assignment");
+ if (assignments.getLength() == 0) {
+ assignments =
association.getElementsByTagName("assignment");
+ }
+
+ if (assignments.getLength() > 0) {
+ org.w3c.dom.Element assignment =
(org.w3c.dom.Element) assignments.item(0);
+ org.w3c.dom.NodeList froms =
assignment.getElementsByTagNameNS("*", "from");
+ if (froms.getLength() == 0) {
+ froms =
assignment.getElementsByTagName("from");
+ }
+
+ if (froms.getLength() > 0) {
+ String value =
froms.item(0).getTextContent().trim();
+ if (paramName != null && value != null &&
!value.isEmpty()) {
+ params.put(paramName, value);
+ }
+ }
+ }
+ }
+ }
+
+ if (!params.isEmpty()) {
+ result.put(taskId, params);
+ }
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.warn("Failed to parse BPMN XML for parameter extraction",
e);
+ }
+
+ return result;
+ }
+
+ private static String getParameterNameFromDataInputId(org.w3c.dom.Element
task, String dataInputId) {
+ try {
+
+ org.w3c.dom.NodeList ioSpecs = task.getElementsByTagNameNS("*",
"ioSpecification");
+ if (ioSpecs.getLength() == 0) {
+ ioSpecs = task.getElementsByTagName("ioSpecification");
+ }
+
+ if (ioSpecs.getLength() > 0) {
+ org.w3c.dom.Element ioSpec = (org.w3c.dom.Element)
ioSpecs.item(0);
+
+ org.w3c.dom.NodeList dataInputs =
ioSpec.getElementsByTagNameNS("*", "dataInput");
+ if (dataInputs.getLength() == 0) {
+ dataInputs = ioSpec.getElementsByTagName("dataInput");
+ }
+
+ for (int i = 0; i < dataInputs.getLength(); i++) {
+ org.w3c.dom.Element dataInput = (org.w3c.dom.Element)
dataInputs.item(i);
+ String id = dataInput.getAttribute("id");
+ String name = dataInput.getAttribute("name");
+
+ if (dataInputId.equals(id) && name != null &&
!name.isEmpty()) {
+ return name;
+ }
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.warn("Failed to map dataInput id to parameter name", e);
+ }
+ return null;
+ }
+
+ private static boolean isExpression(String value) {
+ return value != null &&
EXPRESSION_PATTERN.matcher(value.trim()).matches();
+ }
+
+ private static boolean isValidUrlFormat(String url) {
+ if (url == null || url.trim().isEmpty()) {
+ return false;
+ }
+
+ if (URL_PLACEHOLDER_PATTERN.matcher(url).find()) {
+ return true;
+ }
+
+ return url.startsWith("http://") || url.startsWith("https://") ||
url.startsWith("/");
+ }
+
+ private static String formatNodeError(String resourceUri, Process process,
WorkItemNode node, String errorMessage) {
+ String uri = resourceUri != null ? resourceUri : "(unknown)";
+ String processId = process != null ? process.getId() : "(unknown)";
+ String processName = process != null ? process.getName() : "(unknown)";
+ String nodeName = node.getName() != null ? node.getName() :
"(unnamed)";
+ String nodeId = String.valueOf(node.getId());
+ return String.format(NODE_ERROR_TEMPLATE, uri, processId, processName,
nodeName, nodeId, errorMessage);
+ }
}
diff --git
a/jitexecutor/jitexecutor-bpmn/src/test/java/org/kie/kogito/jitexecutor/bpmn/JITBPMNServiceImplTest.java
b/jitexecutor/jitexecutor-bpmn/src/test/java/org/kie/kogito/jitexecutor/bpmn/JITBPMNServiceImplTest.java
index 454051070..b1d3eb52f 100644
---
a/jitexecutor/jitexecutor-bpmn/src/test/java/org/kie/kogito/jitexecutor/bpmn/JITBPMNServiceImplTest.java
+++
b/jitexecutor/jitexecutor-bpmn/src/test/java/org/kie/kogito/jitexecutor/bpmn/JITBPMNServiceImplTest.java
@@ -38,6 +38,11 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.kie.kogito.jitexecutor.bpmn.TestingUtils.MULTIPLE_BPMN2_FILE;
import static
org.kie.kogito.jitexecutor.bpmn.TestingUtils.MULTIPLE_INVALID_BPMN2_FILE;
+import static
org.kie.kogito.jitexecutor.bpmn.TestingUtils.REST_WIH_ALL_VALID_SCENARIOS_BPMN2_FILE;
+import static
org.kie.kogito.jitexecutor.bpmn.TestingUtils.REST_WIH_INVALID_BPMN2_FILE;
+import static
org.kie.kogito.jitexecutor.bpmn.TestingUtils.REST_WIH_VALID_BPMN2_FILE;
+import static
org.kie.kogito.jitexecutor.bpmn.TestingUtils.REST_WIH_VALID_PROPER_BPMN2_FILE;
+import static
org.kie.kogito.jitexecutor.bpmn.TestingUtils.REST_WIH_VALID_SIMPLE_BPMN2_FILE;
import static org.kie.kogito.jitexecutor.bpmn.TestingUtils.SINGLE_BPMN2_FILE;
import static
org.kie.kogito.jitexecutor.bpmn.TestingUtils.SINGLE_INVALID_BPMN2_FILE;
import static
org.kie.kogito.jitexecutor.bpmn.TestingUtils.SINGLE_UNPARSABLE_BPMN2_FILE;
@@ -160,4 +165,64 @@ class JITBPMNServiceImplTest {
assertThat(retrieved).isEqualTo(expected);
}
+ @Test
+ void validateModel_RestWIHValid_ParsesSuccessfully() throws IOException {
+ String toValidate = new
String(IoUtils.readBytesFromInputStream(Objects.requireNonNull(JITBPMNService.class.getResourceAsStream(REST_WIH_VALID_BPMN2_FILE))));
+ JITBPMNValidationResult retrieved =
jitBpmnService.validateModel(toValidate);
+
+ assertThat(retrieved).isNotNull();
+ assertThat(retrieved.getErrors()).isNotNull();
+
+ assertThat(retrieved.getErrors()).allMatch(error ->
error.contains("Url is required") ||
error.contains("AccessTokenAcquisitionStrategy is required"));
+ }
+
+ @Test
+ void validateModel_RestWIHValidProper_ParsesSuccessfully() throws
IOException {
+ String toValidate = new
String(IoUtils.readBytesFromInputStream(Objects.requireNonNull(JITBPMNService.class.getResourceAsStream(REST_WIH_VALID_PROPER_BPMN2_FILE))));
+ JITBPMNValidationResult retrieved =
jitBpmnService.validateModel(toValidate);
+
+ assertThat(retrieved).isNotNull();
+ assertThat(retrieved.getErrors()).isNotNull();
+
+ assertThat(retrieved.getErrors()).allMatch(error ->
error.contains("Url is required") ||
error.contains("AccessTokenAcquisitionStrategy is required"));
+ }
+
+ @Test
+ void validateModel_RestWIHValidSimple_ParsesSuccessfully() throws
IOException {
+ String toValidate = new
String(IoUtils.readBytesFromInputStream(Objects.requireNonNull(JITBPMNService.class.getResourceAsStream(REST_WIH_VALID_SIMPLE_BPMN2_FILE))));
+ JITBPMNValidationResult retrieved =
jitBpmnService.validateModel(toValidate);
+
+ assertThat(retrieved).isNotNull();
+ assertThat(retrieved.getErrors()).isNotNull();
+
+ assertThat(retrieved.getErrors()).allMatch(error ->
error.contains("Url is required") ||
error.contains("AccessTokenAcquisitionStrategy is required"));
+ }
+
+ @Test
+ void validateModel_RestWIHInvalid_HasValidationErrors() throws IOException
{
+ String toValidate = new
String(IoUtils.readBytesFromInputStream(Objects.requireNonNull(JITBPMNService.class.getResourceAsStream(REST_WIH_INVALID_BPMN2_FILE))));
+ JITBPMNValidationResult retrieved =
jitBpmnService.validateModel(toValidate);
+
+ assertThat(retrieved).isNotNull();
+ assertThat(retrieved.getErrors()).isNotNull().isNotEmpty();
+
+ assertThat(retrieved.getErrors()).anyMatch(error ->
error.contains("Missing Strategy") &&
error.contains("AccessTokenAcquisitionStrategy is required"));
+ assertThat(retrieved.getErrors()).anyMatch(error ->
error.contains("Invalid Strategy") &&
error.contains("AccessTokenAcquisitionStrategy must be one of"));
+ assertThat(retrieved.getErrors()).anyMatch(error ->
error.contains("Missing TaskId") && error.contains("RestServiceCallTaskId is
required"));
+ assertThat(retrieved.getErrors()).anyMatch(error ->
error.contains("Invalid TaskId Format") &&
error.contains("RestServiceCallTaskId must contain only alphanumeric"));
+ assertThat(retrieved.getErrors()).anyMatch(error ->
error.contains("Missing URL") && error.contains("Url is required"));
+ }
+
+ @Test
+ void validateModel_AllValidScenarios_ParsesSuccessfully() throws
IOException {
+ String toValidate = new
String(IoUtils.readBytesFromInputStream(Objects.requireNonNull(JITBPMNService.class.getResourceAsStream(REST_WIH_ALL_VALID_SCENARIOS_BPMN2_FILE))));
+ JITBPMNValidationResult retrieved =
jitBpmnService.validateModel(toValidate);
+
+ assertThat(retrieved).isNotNull();
+ assertThat(retrieved.getErrors()).isNotNull();
+
+ // The BPMN file should parse successfully
+ // Similar to above, validation errors for required fields will be
present
+ }
+
}
diff --git
a/jitexecutor/jitexecutor-bpmn/src/test/java/org/kie/kogito/jitexecutor/bpmn/TestingUtils.java
b/jitexecutor/jitexecutor-bpmn/src/test/java/org/kie/kogito/jitexecutor/bpmn/TestingUtils.java
index 6364c090f..440ddeedb 100644
---
a/jitexecutor/jitexecutor-bpmn/src/test/java/org/kie/kogito/jitexecutor/bpmn/TestingUtils.java
+++
b/jitexecutor/jitexecutor-bpmn/src/test/java/org/kie/kogito/jitexecutor/bpmn/TestingUtils.java
@@ -36,6 +36,16 @@ public class TestingUtils {
public static final String UNPARSABLE_BPMN2_FILE =
"/UnparsableModel.bpmn2";
+ public static final String REST_WIH_VALID_BPMN2_FILE =
"/RestWIH_Valid.bpmn2";
+
+ public static final String REST_WIH_VALID_PROPER_BPMN2_FILE =
"/RestWIH_Valid_Proper.bpmn2";
+
+ public static final String REST_WIH_VALID_SIMPLE_BPMN2_FILE =
"/RestWIH_Valid_Simple.bpmn2";
+
+ public static final String REST_WIH_INVALID_BPMN2_FILE =
"/RestWIH_Invalid.bpmn2";
+
+ public static final String REST_WIH_ALL_VALID_SCENARIOS_BPMN2_FILE =
"/RestWIH_AllValid_Scenarios.bpmn2";
+
public static String getFilePath(String fileName) {
return "src/test/resources" + fileName;
}
diff --git
a/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_AllValid_Scenarios.bpmn2
b/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_AllValid_Scenarios.bpmn2
new file mode 100644
index 000000000..43905adb0
--- /dev/null
+++
b/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_AllValid_Scenarios.bpmn2
@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:bpmn2="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"
+ id="_RestWIHAllValidScenarios"
+ targetNamespace="http://www.omg.org/bpmn20">
+ <bpmn2:itemDefinition id="_StringItem" structureRef="String"/>
+ <bpmn2:process id="RestWIHAllValidScenarios"
drools:packageName="com.example" drools:version="1.0" drools:adHoc="false"
name="rest-wih-all-valid-scenarios" isExecutable="true" processType="Public">
+ <bpmn2:startEvent id="_1" name="Start">
+ <bpmn2:outgoing>_1-_2</bpmn2:outgoing>
+ </bpmn2:startEvent>
+
+ <!-- Valid: POST with ContentData -->
+ <bpmn2:task id="_2" name="Valid POST with Body" drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Valid POST with Body]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_1-_2</bpmn2:incoming>
+ <bpmn2:outgoing>_2-_3</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_2_MethodInput" itemSubjectRef="_StringItem"
name="Method"/>
+ <bpmn2:dataInput id="_2_ContentDataInput" itemSubjectRef="_StringItem"
name="ContentData"/>
+ <bpmn2:dataInput id="_2_UrlInput" itemSubjectRef="_StringItem"
name="Url"/>
+ <bpmn2:dataInput id="_2_AccessTokenAcquisitionStrategyInput"
itemSubjectRef="_StringItem" name="AccessTokenAcquisitionStrategy"/>
+ <bpmn2:dataInput id="_2_HEADER_Content_TypeInput"
itemSubjectRef="_StringItem" name="HEADER_Content-Type"/>
+ <bpmn2:inputSet>
+ <bpmn2:dataInputRefs>_2_MethodInput</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_2_ContentDataInput</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_2_UrlInput</bpmn2:dataInputRefs>
+
<bpmn2:dataInputRefs>_2_AccessTokenAcquisitionStrategyInput</bpmn2:dataInputRefs>
+
<bpmn2:dataInputRefs>_2_HEADER_Content_TypeInput</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_2_MethodInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[POST]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_2_MethodInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_2_ContentDataInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from xsi:type="bpmn2:tFormalExpression"><![CDATA[{"name":
"John", "age": 30}]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_2_ContentDataInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_2_UrlInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[https://api.example.com/users]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_2_UrlInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_2_AccessTokenAcquisitionStrategyInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[propagated]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_2_AccessTokenAcquisitionStrategyInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_2_HEADER_Content_TypeInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[application/json]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_2_HEADER_Content_TypeInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:task>
+
+ <!-- Valid: Method with expression -->
+ <bpmn2:task id="_3" name="Valid Method Expression" drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Valid Method
Expression]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_2-_3</bpmn2:incoming>
+ <bpmn2:outgoing>_3-_4</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_3_MethodInput" itemSubjectRef="_StringItem"
name="Method"/>
+ <bpmn2:dataInput id="_3_UrlInput" itemSubjectRef="_StringItem"
name="Url"/>
+ <bpmn2:dataInput id="_3_AccessTokenAcquisitionStrategyInput"
itemSubjectRef="_StringItem" name="AccessTokenAcquisitionStrategy"/>
+ <bpmn2:inputSet>
+ <bpmn2:dataInputRefs>_3_MethodInput</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_3_UrlInput</bpmn2:dataInputRefs>
+
<bpmn2:dataInputRefs>_3_AccessTokenAcquisitionStrategyInput</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_3_MethodInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[#{httpMethod}]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_3_MethodInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_3_UrlInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[https://api.example.com/data]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_3_UrlInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_3_AccessTokenAcquisitionStrategyInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[none]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_3_AccessTokenAcquisitionStrategyInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:task>
+
+ <!-- Valid: URL with placeholders -->
+ <bpmn2:task id="_4" name="Valid URL Placeholders" drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Valid URL
Placeholders]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_3-_4</bpmn2:incoming>
+ <bpmn2:outgoing>_4-_5</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_4_UrlInput" itemSubjectRef="_StringItem"
name="Url"/>
+ <bpmn2:dataInput id="_4_AccessTokenAcquisitionStrategyInput"
itemSubjectRef="_StringItem" name="AccessTokenAcquisitionStrategy"/>
+ <bpmn2:inputSet>
+ <bpmn2:dataInputRefs>_4_UrlInput</bpmn2:dataInputRefs>
+
<bpmn2:dataInputRefs>_4_AccessTokenAcquisitionStrategyInput</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_4_UrlInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[https://api.example.com/users/{userId}/profile]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_4_UrlInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_4_AccessTokenAcquisitionStrategyInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[none]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_4_AccessTokenAcquisitionStrategyInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:task>
+
+ <!-- Valid: Query and Header parameters -->
+ <bpmn2:task id="_5" name="Valid Query and Headers" drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Valid Query and
Headers]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_4-_5</bpmn2:incoming>
+ <bpmn2:outgoing>_5-_6</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_5_UrlInput" itemSubjectRef="_StringItem"
name="Url"/>
+ <bpmn2:dataInput id="_5_AccessTokenAcquisitionStrategyInput"
itemSubjectRef="_StringItem" name="AccessTokenAcquisitionStrategy"/>
+ <bpmn2:dataInput id="_5_QUERY_pageInput" itemSubjectRef="_StringItem"
name="QUERY_page"/>
+ <bpmn2:dataInput id="_5_QUERY_limitInput" itemSubjectRef="_StringItem"
name="QUERY_limit"/>
+ <bpmn2:dataInput id="_5_HEADER_AcceptInput"
itemSubjectRef="_StringItem" name="HEADER_Accept"/>
+ <bpmn2:inputSet>
+ <bpmn2:dataInputRefs>_5_UrlInput</bpmn2:dataInputRefs>
+
<bpmn2:dataInputRefs>_5_AccessTokenAcquisitionStrategyInput</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_5_QUERY_pageInput</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_5_QUERY_limitInput</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_5_HEADER_AcceptInput</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_5_UrlInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[https://api.example.com/users]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_5_UrlInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_5_AccessTokenAcquisitionStrategyInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[none]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_5_AccessTokenAcquisitionStrategyInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_5_QUERY_pageInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[1]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_5_QUERY_pageInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_5_QUERY_limitInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[10]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_5_QUERY_limitInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_5_HEADER_AcceptInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[application/json]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_5_HEADER_AcceptInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:task>
+
+ <!-- Valid: Valid RequestTimeout -->
+ <bpmn2:task id="_6" name="Valid Timeout" drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Valid Timeout]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_5-_6</bpmn2:incoming>
+ <bpmn2:outgoing>_6-_7</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_6_RequestTimeoutInput"
itemSubjectRef="_StringItem" name="RequestTimeout"/>
+ <bpmn2:dataInput id="_6_UrlInput" itemSubjectRef="_StringItem"
name="Url"/>
+ <bpmn2:dataInput id="_6_AccessTokenAcquisitionStrategyInput"
itemSubjectRef="_StringItem" name="AccessTokenAcquisitionStrategy"/>
+ <bpmn2:inputSet>
+ <bpmn2:dataInputRefs>_6_RequestTimeoutInput</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_6_UrlInput</bpmn2:dataInputRefs>
+
<bpmn2:dataInputRefs>_6_AccessTokenAcquisitionStrategyInput</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_6_RequestTimeoutInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[30000]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_6_RequestTimeoutInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_6_UrlInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[https://api.example.com/data]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_6_UrlInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_6_AccessTokenAcquisitionStrategyInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[none]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_6_AccessTokenAcquisitionStrategyInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:task>
+
+ <bpmn2:endEvent id="_7" name="End">
+ <bpmn2:incoming>_6-_7</bpmn2:incoming>
+ </bpmn2:endEvent>
+
+ <bpmn2:sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2"/>
+ <bpmn2:sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3"/>
+ <bpmn2:sequenceFlow id="_3-_4" sourceRef="_3" targetRef="_4"/>
+ <bpmn2:sequenceFlow id="_4-_5" sourceRef="_4" targetRef="_5"/>
+ <bpmn2:sequenceFlow id="_5-_6" sourceRef="_5" targetRef="_6"/>
+ <bpmn2:sequenceFlow id="_6-_7" sourceRef="_6" targetRef="_7"/>
+ </bpmn2:process>
+ <bpmndi:BPMNDiagram>
+ <bpmndi:BPMNPlane bpmnElement="RestWIHAllValidScenarios">
+ <bpmndi:BPMNShape id="shape__1" bpmnElement="_1">
+ <dc:Bounds height="56" width="56" x="100" y="100"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__2" bpmnElement="_2">
+ <dc:Bounds height="102" width="154" x="236" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__3" bpmnElement="_3">
+ <dc:Bounds height="102" width="154" x="470" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__4" bpmnElement="_4">
+ <dc:Bounds height="102" width="154" x="704" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__5" bpmnElement="_5">
+ <dc:Bounds height="102" width="154" x="938" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__6" bpmnElement="_6">
+ <dc:Bounds height="102" width="154" x="1172" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__7" bpmnElement="_7">
+ <dc:Bounds height="56" width="56" x="1406" y="100"/>
+ </bpmndi:BPMNShape>
+ </bpmndi:BPMNPlane>
+ </bpmndi:BPMNDiagram>
+</bpmn2:definitions>
\ No newline at end of file
diff --git
a/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Invalid.bpmn2
b/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Invalid.bpmn2
new file mode 100644
index 000000000..6c0c263c2
--- /dev/null
+++ b/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Invalid.bpmn2
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:bpmn2="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"
+ id="_RestWIHInvalidTest"
+ targetNamespace="http://www.omg.org/bpmn20">
+ <bpmn2:process id="RestWIHInvalid" drools:packageName="com.example"
drools:version="1.0" drools:adHoc="false" name="rest-wih-invalid-process"
isExecutable="true" processType="Public">
+ <bpmn2:startEvent id="_1" name="Start">
+ <bpmn2:outgoing>_1-_2</bpmn2:outgoing>
+ </bpmn2:startEvent>
+ <bpmn2:task id="_2" name="Missing Strategy" drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Missing Strategy]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_1-_2</bpmn2:incoming>
+ <bpmn2:outgoing>_2-_3</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_2_UrlInput" name="Url"/>
+ <bpmn2:inputSet>
+ <bpmn2:dataInputRefs>_2_UrlInput</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_2_UrlInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression">https://api.example.com/data</bpmn2:from>
+ <bpmn2:to xsi:type="bpmn2:tFormalExpression">_2_UrlInput</bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:task>
+ <bpmn2:task id="_3" name="Invalid Strategy" drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Invalid Strategy]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_2-_3</bpmn2:incoming>
+ <bpmn2:outgoing>_3-_4</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_3_AccessTokenAcquisitionStrategyInput"
name="AccessTokenAcquisitionStrategy"/>
+ <bpmn2:dataInput id="_3_UrlInput" name="Url"/>
+ <bpmn2:inputSet>
+
<bpmn2:dataInputRefs>_3_AccessTokenAcquisitionStrategyInput</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_3_UrlInput</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_3_AccessTokenAcquisitionStrategyInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression">invalid_strategy</bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression">_3_AccessTokenAcquisitionStrategyInput</bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_3_UrlInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression">https://api.example.com/data</bpmn2:from>
+ <bpmn2:to xsi:type="bpmn2:tFormalExpression">_3_UrlInput</bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:task>
+ <bpmn2:task id="_4" name="Missing TaskId" drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Missing TaskId]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_3-_4</bpmn2:incoming>
+ <bpmn2:outgoing>_4-_5</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_4_AccessTokenAcquisitionStrategyInput"
name="AccessTokenAcquisitionStrategy"/>
+ <bpmn2:dataInput id="_4_UrlInput" name="Url"/>
+ <bpmn2:inputSet>
+
<bpmn2:dataInputRefs>_4_AccessTokenAcquisitionStrategyInput</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_4_UrlInput</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_4_AccessTokenAcquisitionStrategyInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression">configured</bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression">_4_AccessTokenAcquisitionStrategyInput</bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_4_UrlInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression">https://api.example.com/secure</bpmn2:from>
+ <bpmn2:to xsi:type="bpmn2:tFormalExpression">_4_UrlInput</bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:task>
+ <bpmn2:task id="_5" name="Invalid TaskId Format" drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Invalid TaskId
Format]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_4-_5</bpmn2:incoming>
+ <bpmn2:outgoing>_5-_6</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_5_AccessTokenAcquisitionStrategyInput"
name="AccessTokenAcquisitionStrategy"/>
+ <bpmn2:dataInput id="_5_RestServiceCallTaskIdInput"
name="RestServiceCallTaskId"/>
+ <bpmn2:dataInput id="_5_UrlInput" name="Url"/>
+ <bpmn2:inputSet>
+
<bpmn2:dataInputRefs>_5_AccessTokenAcquisitionStrategyInput</bpmn2:dataInputRefs>
+
<bpmn2:dataInputRefs>_5_RestServiceCallTaskIdInput</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_5_UrlInput</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_5_AccessTokenAcquisitionStrategyInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression">configured</bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression">_5_AccessTokenAcquisitionStrategyInput</bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_5_RestServiceCallTaskIdInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression">Invalid-Task-ID!</bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression">_5_RestServiceCallTaskIdInput</bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_5_UrlInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression">https://api.example.com/secure</bpmn2:from>
+ <bpmn2:to xsi:type="bpmn2:tFormalExpression">_5_UrlInput</bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:task>
+ <bpmn2:task id="_6" name="Missing URL" drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Missing URL]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_5-_6</bpmn2:incoming>
+ <bpmn2:outgoing>_6-_7</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_6_AccessTokenAcquisitionStrategyInput"
name="AccessTokenAcquisitionStrategy"/>
+ <bpmn2:inputSet>
+
<bpmn2:dataInputRefs>_6_AccessTokenAcquisitionStrategyInput</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_6_AccessTokenAcquisitionStrategyInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from xsi:type="bpmn2:tFormalExpression">none</bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression">_6_AccessTokenAcquisitionStrategyInput</bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:task>
+ <bpmn2:endEvent id="_7" name="End">
+ <bpmn2:incoming>_6-_7</bpmn2:incoming>
+ </bpmn2:endEvent>
+ <bpmn2:sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2"/>
+ <bpmn2:sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3"/>
+ <bpmn2:sequenceFlow id="_3-_4" sourceRef="_3" targetRef="_4"/>
+ <bpmn2:sequenceFlow id="_4-_5" sourceRef="_4" targetRef="_5"/>
+ <bpmn2:sequenceFlow id="_5-_6" sourceRef="_5" targetRef="_6"/>
+ <bpmn2:sequenceFlow id="_6-_7" sourceRef="_6" targetRef="_7"/>
+ </bpmn2:process>
+ <bpmndi:BPMNDiagram>
+ <bpmndi:BPMNPlane bpmnElement="RestWIHInvalid">
+ <bpmndi:BPMNShape id="shape__1" bpmnElement="_1">
+ <dc:Bounds height="56" width="56" x="100" y="100"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__2" bpmnElement="_2">
+ <dc:Bounds height="102" width="154" x="236" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__3" bpmnElement="_3">
+ <dc:Bounds height="102" width="154" x="470" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__4" bpmnElement="_4">
+ <dc:Bounds height="102" width="154" x="704" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__5" bpmnElement="_5">
+ <dc:Bounds height="102" width="154" x="938" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__6" bpmnElement="_6">
+ <dc:Bounds height="102" width="154" x="1172" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__7" bpmnElement="_7">
+ <dc:Bounds height="56" width="56" x="1406" y="100"/>
+ </bpmndi:BPMNShape>
+ </bpmndi:BPMNPlane>
+ </bpmndi:BPMNDiagram>
+</bpmn2:definitions>
\ No newline at end of file
diff --git
a/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Valid.bpmn2
b/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Valid.bpmn2
new file mode 100644
index 000000000..f714fe23f
--- /dev/null
+++ b/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Valid.bpmn2
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:bpmn2="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" id="_RestWIHValidTest"
targetNamespace="http://www.omg.org/bpmn20">
+ <bpmn2:process id="RestWIHValid" drools:packageName="com.example"
drools:version="1.0" drools:adHoc="false" name="rest-wih-valid-process"
isExecutable="true" processType="Public">
+ <bpmn2:endEvent id="_4" name="End">
+ <bpmn2:incoming>_3-_4</bpmn2:incoming>
+ </bpmn2:endEvent>
+ <bpmn2:sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2" />
+ <bpmn2:sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3" />
+ <bpmn2:sequenceFlow id="_3-_4" sourceRef="_3" targetRef="_4" />
+ <bpmn2:startEvent id="_1" name="Start">
+ <bpmn2:outgoing>_1-_2</bpmn2:outgoing>
+ </bpmn2:startEvent>
+ <bpmn2:task id="_2" name="REST Call with Propagated"
drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue>REST Call with Propagated</drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_1-_2</bpmn2:incoming>
+ <bpmn2:outgoing>_2-_3</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_2_AccessTokenAcquisitionStrategyInput"
name="AccessTokenAcquisitionStrategy" />
+ <bpmn2:dataInput id="_2_UrlInput" name="Url" />
+ <bpmn2:inputSet>
+
<bpmn2:dataInputRefs>_2_AccessTokenAcquisitionStrategyInput</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_2_UrlInput</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_2_AccessTokenAcquisitionStrategyInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression">propagated</bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression">_2_AccessTokenAcquisitionStrategyInput</bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_2_UrlInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression">https://api.example.com/data</bpmn2:from>
+ <bpmn2:to xsi:type="bpmn2:tFormalExpression">_2_UrlInput</bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:task>
+ <bpmn2:task id="_3" name="REST Call with Configured"
drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue>REST Call with Configured</drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_2-_3</bpmn2:incoming>
+ <bpmn2:outgoing>_3-_4</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_3_AccessTokenAcquisitionStrategyInput"
name="AccessTokenAcquisitionStrategy" />
+ <bpmn2:dataInput id="_3_RestServiceCallTaskIdInput"
name="RestServiceCallTaskId" />
+ <bpmn2:dataInput id="_3_UrlInput" name="Url" />
+ <bpmn2:inputSet>
+
<bpmn2:dataInputRefs>_3_AccessTokenAcquisitionStrategyInput</bpmn2:dataInputRefs>
+
<bpmn2:dataInputRefs>_3_RestServiceCallTaskIdInput</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_3_UrlInput</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_3_AccessTokenAcquisitionStrategyInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression">configured</bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression">_3_AccessTokenAcquisitionStrategyInput</bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_3_RestServiceCallTaskIdInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression">Valid_Task_ID_123</bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression">_3_RestServiceCallTaskIdInput</bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_3_UrlInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression">https://api.example.com/secure</bpmn2:from>
+ <bpmn2:to xsi:type="bpmn2:tFormalExpression">_3_UrlInput</bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:task>
+ </bpmn2:process>
+ <bpmndi:BPMNDiagram id="_4167B2C8-5737-464B-9678-2B1449184FF8">
+ <bpmndi:BPMNPlane bpmnElement="RestWIHValid"
id="_5CFD32BB-E1FD-4F50-B91C-F891F001E44C">
+ <bpmndi:BPMNShape id="shape__1" bpmnElement="_1">
+ <dc:Bounds height="56" width="56" x="100" y="100" />
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__2" bpmnElement="_2">
+ <dc:Bounds height="102" width="154" x="236" y="77" />
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__3" bpmnElement="_3">
+ <dc:Bounds height="102" width="154" x="470" y="77" />
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__4" bpmnElement="_4">
+ <dc:Bounds height="56" width="56" x="704" y="100" />
+ </bpmndi:BPMNShape>
+ </bpmndi:BPMNPlane>
+ </bpmndi:BPMNDiagram>
+</bpmn2:definitions>
diff --git
a/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Valid_Proper.bpmn2
b/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Valid_Proper.bpmn2
new file mode 100644
index 000000000..9dd7d53d6
--- /dev/null
+++ b/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Valid_Proper.bpmn2
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:bpmn2="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:tns="http://www.jboss.org/drools"
+ id="_RestWIHValidProperTest"
+ targetNamespace="http://www.omg.org/bpmn20">
+ <bpmn2:itemDefinition id="_AccessTokenAcquisitionStrategyItem"
structureRef="String"/>
+ <bpmn2:itemDefinition id="_RestServiceCallTaskIdItem" structureRef="String"/>
+ <bpmn2:itemDefinition id="_UrlItem" structureRef="String"/>
+ <bpmn2:process id="RestWIHValidProper" drools:packageName="com.example"
drools:version="1.0" drools:adHoc="false" name="rest-wih-valid-proper"
isExecutable="true" processType="Public">
+ <bpmn2:startEvent id="_1" name="Start">
+ <bpmn2:outgoing>_1-_2</bpmn2:outgoing>
+ </bpmn2:startEvent>
+ <bpmn2:task id="_2" name="REST Call Propagated" drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[REST Call Propagated]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_1-_2</bpmn2:incoming>
+ <bpmn2:outgoing>_2-_3</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_2_AccessTokenAcquisitionStrategyInput"
itemSubjectRef="_AccessTokenAcquisitionStrategyItem"
name="AccessTokenAcquisitionStrategy"/>
+ <bpmn2:dataInput id="_2_UrlInput" itemSubjectRef="_UrlItem"
name="Url"/>
+ <bpmn2:inputSet>
+
<bpmn2:dataInputRefs>_2_AccessTokenAcquisitionStrategyInput</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_2_UrlInput</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_2_AccessTokenAcquisitionStrategyInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[propagated]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_2_AccessTokenAcquisitionStrategyInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_2_UrlInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[https://api.example.com/data]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_2_UrlInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:task>
+ <bpmn2:task id="_3" name="REST Call Configured" drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[REST Call Configured]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_2-_3</bpmn2:incoming>
+ <bpmn2:outgoing>_3-_4</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_3_AccessTokenAcquisitionStrategyInput"
itemSubjectRef="_AccessTokenAcquisitionStrategyItem"
name="AccessTokenAcquisitionStrategy"/>
+ <bpmn2:dataInput id="_3_RestServiceCallTaskIdInput"
itemSubjectRef="_RestServiceCallTaskIdItem" name="RestServiceCallTaskId"/>
+ <bpmn2:dataInput id="_3_UrlInput" itemSubjectRef="_UrlItem"
name="Url"/>
+ <bpmn2:inputSet>
+
<bpmn2:dataInputRefs>_3_AccessTokenAcquisitionStrategyInput</bpmn2:dataInputRefs>
+
<bpmn2:dataInputRefs>_3_RestServiceCallTaskIdInput</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_3_UrlInput</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_3_AccessTokenAcquisitionStrategyInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[configured]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_3_AccessTokenAcquisitionStrategyInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_3_RestServiceCallTaskIdInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[Valid_Task_ID_123]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_3_RestServiceCallTaskIdInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_3_UrlInput</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[https://api.example.com/secure]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_3_UrlInput]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:task>
+ <bpmn2:endEvent id="_4" name="End">
+ <bpmn2:incoming>_3-_4</bpmn2:incoming>
+ </bpmn2:endEvent>
+ <bpmn2:sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2"/>
+ <bpmn2:sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3"/>
+ <bpmn2:sequenceFlow id="_3-_4" sourceRef="_3" targetRef="_4"/>
+ </bpmn2:process>
+ <bpmndi:BPMNDiagram>
+ <bpmndi:BPMNPlane bpmnElement="RestWIHValidProper">
+ <bpmndi:BPMNShape id="shape__1" bpmnElement="_1">
+ <dc:Bounds height="56" width="56" x="100" y="100"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__2" bpmnElement="_2">
+ <dc:Bounds height="102" width="154" x="236" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__3" bpmnElement="_3">
+ <dc:Bounds height="102" width="154" x="470" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__4" bpmnElement="_4">
+ <dc:Bounds height="56" width="56" x="704" y="100"/>
+ </bpmndi:BPMNShape>
+ </bpmndi:BPMNPlane>
+ </bpmndi:BPMNDiagram>
+</bpmn2:definitions>
\ No newline at end of file
diff --git
a/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Valid_Simple.bpmn2
b/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Valid_Simple.bpmn2
new file mode 100644
index 000000000..9066e0a45
--- /dev/null
+++ b/jitexecutor/jitexecutor-bpmn/src/test/resources/RestWIH_Valid_Simple.bpmn2
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:bpmn2="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:tns="http://www.jboss.org/drools"
+ id="_RestWIHValidSimpleTest"
+ targetNamespace="http://www.omg.org/bpmn20">
+ <bpmn2:process id="RestWIHValidSimple" drools:packageName="com.example"
drools:version="1.0" drools:adHoc="false" name="rest-wih-valid-simple"
isExecutable="true" processType="Public">
+ <bpmn2:startEvent id="_1" name="Start">
+ <bpmn2:outgoing>_1-_2</bpmn2:outgoing>
+ </bpmn2:startEvent>
+ <bpmn2:task id="_2" name="REST Call" drools:taskName="Rest">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[REST Call]]></drools:metaValue>
+ </drools:metaData>
+ <drools:onEntry-script scriptFormat="http://www.java.com/java">
+
<drools:script><![CDATA[kcontext.setVariable("AccessTokenAcquisitionStrategy",
"propagated");
+kcontext.setVariable("Url", "https://api.example.com/data");]]></drools:script>
+ </drools:onEntry-script>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_1-_2</bpmn2:incoming>
+ <bpmn2:outgoing>_2-_3</bpmn2:outgoing>
+ </bpmn2:task>
+ <bpmn2:endEvent id="_3" name="End">
+ <bpmn2:incoming>_2-_3</bpmn2:incoming>
+ </bpmn2:endEvent>
+ <bpmn2:sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2"/>
+ <bpmn2:sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3"/>
+ </bpmn2:process>
+ <bpmndi:BPMNDiagram>
+ <bpmndi:BPMNPlane bpmnElement="RestWIHValidSimple">
+ <bpmndi:BPMNShape id="shape__1" bpmnElement="_1">
+ <dc:Bounds height="56" width="56" x="100" y="100"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__2" bpmnElement="_2">
+ <dc:Bounds height="102" width="154" x="236" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__3" bpmnElement="_3">
+ <dc:Bounds height="56" width="56" x="470" y="100"/>
+ </bpmndi:BPMNShape>
+ </bpmndi:BPMNPlane>
+ </bpmndi:BPMNDiagram>
+</bpmn2:definitions>
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]