How to access an object field from task input param?

Hi,
I am new on Camunda (and enjoy it a lot so far).
I am trying to transfer information from a Javascript application to a workflow, via an external task.

  1. In Javascript, the service task sets a variable this way:
variables = new Variables()
variables.set('person', { firstname: 'John', lastname: 'Doe', id: 123 })
await taskService.complete(task, null, variables)
  1. In the service task, an output parameters is set up as:
person <- ${person}

So that the process variable person is set to the person object (btw, when I do complete(task, variables), hoping, that the person process variable is set, it does not work. It seems this is due to the fact that person already exists as a process variable, before the task is executed, but I don’t understand why it is not allowed to override a process variable that way).

  1. In a following task, I would like to set an input parameter as follows:
personId = ${person.id}

but this does not work: the service task appears as still running, even though it has been executed, and is retried (re-executed) periodically.

Do you know how to access the person ID properly?

A workaround I have tried is to have an intermediate script task (Javascript) as follows:

var c = S(person)
var personId = c.prop("id")
execution.setVariable("personId", personId)

But I find this overly complex for a “business” process.

Many thanks for your help!

What is the null parameter supposed to be? I am not very good with Javascript but at least the Java api does not contain taskService.complete with three different parameters.

In Java you would need to do this with taskService.complete(task, variables)

Thanks for your post.

The documentation (https://github.com/camunda/camunda-external-task-client-js#exchange-process–local-task-variables) says that 2nd parameter is processVariables, and 3rd param is localVariables (this is indeed strange because the REST API does not seem to make a difference).

Best regards

If you set localVariables they cease to exist when the scope of execution ends.

Not having seen you process I don’t know if you scope is process lever or some limited scope of execution.

Can you attach your BPMN model so I might check it?

And I do believe that the problem is that your external task does not seem to complete at all. have you checked logs and cockpit for problems?

Thank you.

I was actually mentioning 2 issues in my request:

  1. it looks like an external task cannot modify a process variable from JavaScript, if this process variable was already existing in the process. (but it works if I set a new process variable, though. And it also works if I assign a process variable from a local variable, in the Output Parameters settings in the modeler)

  2. it looks like accessing a process variable field (like person.id) from a task following an external service task, causes the service task not to complete.

I am sorry, I cannot send the workflow for now.

I have checked the various cockpit panels/tabs, but could not see any issue. About the logs, do you mean there is a log file? Where can it be found (I am running the provided docker container installation)

Many thanks again!

The docker image should printout its log to docker desktop or similar run environment.

1 Like

And if you are doing that assignment that fails in the external task worker, I believe it should be done like this:

var person = JSON.parse(task.variables.get(‘person’));
var personId = person.id;

Pardon my lousy JavaScript skills :slight_smile:

1 Like

Thanks, but it’s not in the javascript task that I need to access the ID, but in the task which follows in the workflow. And I need to output the full “person” out from the javascript task.

Ok, what kind of service task it is that you are trying to access the id in?

Are you accessing it int the BPM definition or in a component implementing the task?

Have you verified that your first step has indeed stored the result into the process?

Hi again,
So I could investigate further thanks to your recommendations.

See the attached workflow.

Here is the Javascript code used for the “CreateContact” external service task:

    let processVariables = new Variables();
    processVariables.set('instanceOut', { firstname: 'a', lastname: 'b', id: 123})
    let ret = await taskService.complete(task, processVariables)

In the “Send Email” task, I then try to access ${instanceOut.id} to set an input variable. But I get this error in the logs:

[nio-8080-exec-5] org.camunda.bpm.engine.rest.exception : ENGINE-REST-HTTP500 org.camunda.bpm.engine.ProcessEngineException: Unknown property used in expression: ${instanceOut.id}. Cause: Could not find property id in class org.camunda.spin.impl.json.jackson.JacksonJsonNode

As you may check in the BPMN file, I try to access the ID with the expression ${instanceOut.id}

It looks like this cannot work, but do you know how to access the id attribute of the instanceOut object?

Many thanks!

issue1.bpmn (4.3 KB)

I could actually fix it by using instead ${S(instanceOut).prop("id")}

However the syntax is not really user friendly. would there be something closer to simply instanceOut.id ?

And I now have another issue, which confirms what I was assuming in my initial message: an external task seems to not be able to update a process variables if it was already existing.

In the attached diagram, I now try to acces the instance process variable from the SendEmail task.

In the JavaScript code of the external service task, I have renamed instanceOut to instance:

let processVariables = new Variables();
processVariables.set('instanceOut', { firstname: 'a', lastname: 'b', id: 123})
let ret = await taskService.complete(task, processVariables)

And then I get this error:
[nio-8080-exec-7] org.camunda.bpm.engine.rest.exception : ENGINE-REST-HTTP500 org.camunda.bpm.engine.ProcessEngineException: Error while evaluating expression: ${S(instance).prop(“id”)}. Cause: org.camunda.spin.json.SpinJsonPropertyException: SPIN/JACKSON-JSON-01004 Unable to find ‘id’

Please note that the ‘User create’ event is triggered by a signal, which provides an instance variable to the process, but which has no id attribute. In the process instance panel of the cockpit, I can see 2 rows for the instance variable. They are both of type Json, but one has the process scope “CreateContactFromSignal”, and the other one the “Create Contact” task scope.

So, do you see why the instance process variable cannot be modified by the Javascript service task?

Many thanks!

issue2.bpmn (4.2 KB)

Maybe my 2 last posts were not clear enough - I still have 2 pending issues for which help would be greatly appreciated :slight_smile:

  1. is it possible to have a more friendly syntax to access intanceOut.id?
  2. why my process variable cannot be updated from the external task?

Many thanks for any help, even partial!

Hi @bfredo123,

There is an alternative with jsonPath:

${instance.jsonPath("id").numberValue()}

https://docs.camunda.org/manual/7.16/user-guide/data-formats/json/#expression-language-integration

But I don’t know if it is easier.

At the CamundaCon 2021, Franz showed an extension about handling json data more easy: CamundaCon LIVE 2021 - JSON Handling in Camunda

All process variables are handled as a map in the process engine. If you provide a new value to an existing key (variable name), the old value will be overwritten. Do you see any exceptions from the external task worker or in the engine log?

Hope this helps, Ingo