It appears as though this is not the case for variables defined programmatically resulting to two different access patterns. Also, just out of curiosity, what were the primary motivations for adopting FEEL?
Hi @philipp.ossler, thanks for the quick response. I have attached a workflow which worked with the previous release. It deployed and ran just fine.
I have made modifications in the flow to use FEEL expressions and have also have highlighted changes in the code which were necessary to get the workflow executing correctly. I wonder if the code changes could have been avoided. A feel variable defined as =variableName defined in the workflow should not imply the code expect or attempt to resolve a variable named =variableName from the variable stack. Instead code should be expecting variable variableName.
The working code is here:
[import io.zeebe.client.ZeebeClient;
import io.zeebe.client.api.response.DeploymentEvent;
import io.zeebe.client.api.response.WorkflowInstanceEvent;
import io.zeebe.client.api.worker.JobWorker;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class SimpleOrderProcessWithMultiSubprocessApp {
public static void main(String[] args) {
final String contactPoint = args.length >= 1 ? args[0] : "127.0.0.1:26500";
System.out.println("Connecting to broker: " + contactPoint);
final ZeebeClient client = ZeebeClient.newClientBuilder().brokerContactPoint(contactPoint).usePlaintext().build();
System.out.println("Connected to broker: " + contactPoint);
final DeploymentEvent deployment =
client.newDeployCommand().addResourceFromClasspath("order-process-simple-with-multi-subprocess.bpmn").send().join();
final int version = deployment.getWorkflows().get(0).getVersion();
System.out.println("Workflow deployed. Version: " + version);
final Map<String, Object> data = new HashMap<>();
data.put("orderId", 31243);
data.put("orderItems", Arrays.asList(435, 182, 376));
final WorkflowInstanceEvent wfInstance =
client
.newCreateInstanceCommand()
.bpmnProcessId("order-process-with-simple-multi-subprocess")
.latestVersion()
.variables(data)
.send()
.join();
final long workflowInstanceKey = wfInstance.getWorkflowInstanceKey();
System.out.println("Workflow instance created. Key: " + workflowInstanceKey);
final JobWorker jobWorker =
client
.newWorker()
.jobType("payment-service")
.handler(
(jobClient, job) -> {
final Map<String, Object> variables = job.getVariablesAsMap();
System.out.println("Process order: " + variables.get("orderId"));
System.out.println("Collect money");
final Map<String, Object> result = new HashMap<>();
result.put("totalPrice", 46.50);
jobClient.newCompleteCommand(job.getKey()).variables(result).send().join();
})
.fetchVariables("orderId")
.open();
final JobWorker emailWorker =
client
.newWorker()
.jobType("customer-service")
.handler(
(jobClient, job) -> {
final Map<String, Object> variables = job.getVariablesAsMap();
System.out.println("Competing order: " + variables.get("orderId"));
String itemsShipped = variables.get("=shipments").toString(); // v0.23.1 had to use == here
System.out.println("Order completed with these items shipped: " + itemsShipped);
jobClient.newCompleteCommand(job.getKey()).send().join();
})
.open();
// subprocess workers
final JobWorker packagingWorker =
client
.newWorker()
.jobType("packaging-service")
.handler(
(jobClient, job) -> {
final Map<String, Object> variables = job.getVariablesAsMap();
System.out.println("Packaging item for order: " + variables.get("orderId"));
String orderItem = variables.get("=orderItem").toString(); // v0.23.1: had to use = here
System.out.println("\t Preparing packaging for item: " + orderItem);
final Map<String, Object> result = new HashMap<>();
result.put("packageItem", orderItem + ".packaging");
jobClient.newCompleteCommand(job.getKey()).variables(result).send().join();
})
.open();
final JobWorker shippingWorker =
client
.newWorker()
.jobType("shipping-service")
.handler(
(jobClient, job) -> {
final Map<String, Object> variables = job.getVariablesAsMap();
System.out.println("Processing order: " + variables.get("orderId"));
String packageItem = variables.get("packageItem").toString();
System.out.println("\t Preparing shipment for package item: " + packageItem);
final Map<String, Object> result = new HashMap<>();
result.put("shipment", packageItem + ".shipment");
jobClient.newCompleteCommand(job.getKey()).variables(result).send().join();
})
.open();
waitUntilClose();
jobWorker.close();
emailWorker.close();
packagingWorker.close();
client.close();
System.out.println("Closed.");
}
public static void waitUntilClose() {
try (Scanner scanner = new Scanner(System.in)) {
while (scanner.hasNextLine()) {
final String nextLine = scanner.nextLine();
if (nextLine.contains("close")) {
return;
}
}
}
}
}]
@philipp.ossler, if I do not include an “=” infront of any of the properties of the multi-instance subprocess, I get the following deployment errors:
Connected to broker: 127.0.0.1:26500
Exception in thread "main" io.zeebe.client.api.command.ClientStatusException: Command rejected with code 'CREATE': Expected to deploy new resources, but encountered the following errors:
'order-process-with-multiple-invoices.bpmn': - Element: SubProcess_03najjz > multiInstanceLoopCharacteristics > extensionElements > loopCharacteristics
- ERROR: Expected expression but found static value 'shipment'. An expression must start with '=' (e.g. '=shipment').
at io.zeebe.client.impl.ZeebeClientFutureImpl.transformExecutionException(ZeebeClientFutureImpl.java:93)
at io.zeebe.client.impl.ZeebeClientFutureImpl.join(ZeebeClientFutureImpl.java:50)
at OrderProcessWithMultipleInvoicesApp.main(OrderProcessWithMultipleInvoicesApp.java:104)
Caused by: java.util.concurrent.ExecutionException: io.grpc.StatusRuntimeException: INVALID_ARGUMENT: Command rejected with code 'CREATE': Expected to deploy new resources, but encountered the following errors:
'order-process-with-multiple-invoices.bpmn': - Element: SubProcess_03najjz > multiInstanceLoopCharacteristics > extensionElements > loopCharacteristics
- ERROR: Expected expression but found static value 'shipment'. An expression must start with '=' (e.g. '=shipment').
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at io.zeebe.client.impl.ZeebeClientFutureImpl.join(ZeebeClientFutureImpl.java:48)
... 1 more
Caused by: io.grpc.StatusRuntimeException: INVALID_ARGUMENT: Command rejected with code 'CREATE': Expected to deploy new resources, but encountered the following errors:
'order-process-with-multiple-invoices.bpmn': - Element: SubProcess_03najjz > multiInstanceLoopCharacteristics > extensionElements > loopCharacteristics
- ERROR: Expected expression but found static value 'shipment'. An expression must start with '=' (e.g. '=shipment').
and if I do not access the inputElement with an equal sign like this =invoice, my process cannot proceed.
Also from your correction, why does the inputCollection have the = and yet the outputCollection does not?
Another issue I just ran across was with the Kafka Connector. I reran the sample ping-pong example against 0.23.1. First I had to modify the same process as follows:
Command rejected with code 'CREATE': Expected to deploy new resources, but encountered the following errors:
'kafka-test-process': - Element: Message_19mpeg2 > extensionElements > subscription
- ERROR: Expected expression but found static value 'key'. An expression must start with '=' (e.g. '=key').
Once I make the change, I can deploy the workflow but now the Kafka sink can no longer correlate to this message. Error is:
\n\t... 10 more\nCaused by: com.jayway.jsonpath.PathNotFoundException: No results for path: $['variablesAsMap']['key']\n\tat com.jayway.jsonpath.internal.path.EvaluationContextImpl.getValue(EvaluationContextImpl.java:133)\n\tat com.jayway.jsonpath.JsonPath.read(JsonPath.java:187)\n\tat com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:102)\n\tat
adding a lot to this but there appears to be an issue.
You need to add = in front of the inputCollection and the outputElement. I provided the correct attributes in the previous comment. This is also described in the documentation.
What do you mean by this? What is the error?
The outputCollection and the inputElement does not access a variable. Instead, these attributes define the variable or the nested property where the value should be stored. It’s like a pointer or an assignment in a programming language.