camunda / camunda-bpm-platform

Flexible framework for workflow and decision automation with BPMN and DMN. Integration with Quarkus, Spring, Spring Boot, CDI.
https://camunda.com/
Apache License 2.0
4.13k stars 1.56k forks source link

Java External Task client unable to load value of local file variable #4523

Closed venetrius closed 1 month ago

venetrius commented 3 months ago

Environment (Required on creation)

Reported and reproduced on 7.21-ee

Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket)

When trying to access the value of a local file Variable vars.getValueTyped("localFile") .getValue();, we get the following error message:

TASK/CLIENT-01008 Exception while loading deferred file: execution variable with name File does not exist

Steps to reproduce (Required on creation)

def sampleContent = "someRandomFileContent"; def file = Variables.fileValue("sample.txt").file(sampleContent.getBytes()).mimeType("text/plain").create();

execution.setVariable('fileInProcess', file);

- Create an external task that has a local input variable, lets call it `localFile`

${execution.getVariableTyped("fileInProcess")}


- Attempt to load the `localFile` variable in the external client:
```java
      client.subscribe("DEMO_TOPIC")
          .localVariables(true)
          .includeExtensionProperties(true)
          .handler((ExternalTask externalTask, ExternalTaskService externalTaskService) -> {
            VariableMap vars = externalTask.getAllVariablesTyped();
            vars.getValueTyped("localFile")
                .getValue();
           // same result if `externalTask.getVariableTyped("localFile").getValue()` is called (without `.localVariables(true)`)
            externalTaskService.complete(externalTask);
          })
          .open();
    }

See example bpmn and process in [JIRA](https://jira.camunda.com/browse/SUPPORT-23079)
### Observed Behavior (Required on creation)
When trying to access the value of a local file Variable `vars.getValueTyped("localFile")
                .getValue();`, we get the following error message: 
```log
TASK/CLIENT-01008 Exception while loading deferred file: execution variable with name File does not exist

Expected behavior (Required on creation)

The call to VariableMap::getValueTyped should return the actual value of the fileValue and don’t throw an error.

Root Cause (Required on prioritization)

In the class org.camunda.bpm.client.impl.EngineClient, the method getLocalBinaryVariable gets called from DeferredFileValueImpl::load with the processInstanceId instead of the executionId. The request sent to the rest-api looks like: {{GET /execution/{processInstanceId}/localVariables/{name}/data}} It tries to resolve a variable from the top level process instance execution instead of using the actual child execution where the local variable is set.

When executing the request (with the processInstanceId) in postman, i get the same error. When using the actual executionId of the externalTask {{GET /execution/{excecutionId}/localVariables/{name}/data}}, i get the correct variable value/file content.

Solution Ideas

Current attempt to retrieve content of a Variable:

 public byte[] getLocalBinaryVariable(String variableName, String processInstanceId) {
    String resourcePath = this.baseUrl + "/execution/{id}/localVariables/{name}/data".replace("{id}", processInstanceId).replace("{name}", variableName);
    return this.engineInteraction.getRequest(resourcePath);
  }

Using https://docs.camunda.org/rest/camunda-bpm-platform/7.21/#tag/Process-Instance/operation/getProcessInstanceVariableBinary with the executionId would work for both local and global variables:

 public byte[] getProcessInstanceVariableBinary(String variableName, String executionId) {
    String resourcePath = this.baseUrl + "/process-instance/{executionId}/variables/{name}/data".replace("{id}", executionId).replace("{name}", variableName);
    return this.engineInteraction.getRequest(resourcePath);
  }

The executionId can be set on the DeferredFileValueImpl instance when the instanceVariable is returned from ExternalTaskImpl.java getVariable, getAllVariablesTyped, getVariableTyped functions.

Hints

Links

tasso94 commented 3 months ago

Let's try to fix it in the NodeJS XTaC as well or create a follow-up issue.

venetrius commented 2 months ago

I still have to create a new task for External JavaScript Client or apply a fix in this ticket.

venetrius commented 2 months ago

@gbetances089 QA hand over note. Scenarios to test:

Please see linked Jira issue for example BPMN.

gbetances089 commented 1 month ago

Tested on 7.22.0-alpha6 release candidate.