Using setVariable with activityId

The scope that groups all the inner instances has by convention the id <id_of_mi_activity>#multiInstanceBody. So you could try to use that to make a variable available in the scope that groups all the inner activity instances.

2 Likes

Woah, it magically works! But why?

I use the execution.getCurrentActivityId() and append it with #multiInstanceBody string. But when I try without the string appended, it fails. So what is the expected form of activityId?

*as a note, I put that code as an execution listener of a multi-instance activity with event type:start. It’s different with the code I shared which is the listener is the property of a start event of a multi-instance subprocess


Additionally: the activityId need to be unique for activity instance (appended unique number, something like mi_activity#multiInstanceBody:10253)? If not, how do the process engine differ between instances of parallel multi-instance?

I checked on my process instance with camunda cockpit, on variables tab:

  • multi-instance body scope is written with my_activity#multiInstanceBody, but the popping text (when hover the mouse in) shows mi_activity#multiInstanceBody:10253

  • multi-instance inner acticity scope (in my case, it’s a subprocess) is written with SubProcess (SubProce...), and the popping text shows mi_activity:10262

and when I click it, the filter area shows me a criteria with form like this:

Activity Instance ID = mi_activity#multiInstanceBody:10253

We must distinguish between activity ID and activity instance ID here.

Activity ID is the ID of the BPMN element as defined in the XML. This is returned by execution.getCurrentActivityId(). In a process instance, you can have many instances per activity (think about modeling a loop, multi-instance, etc.). That’s why every such instance has an id, the activity instance id accessible via execution.getActivityInstanceId(). Both, activities and activity instances are organized hierarchically according to the BPMN definition.

The setVariable API we are discussing here takes activity IDs as its parameter, not activity instance IDs. When you call setVariable("key", "value", "activityA"), this means that the variable will be set on the next higher instance of activity activityA. This instance is always unique in this context, because there can’t be two parent/grandparent instances of the same activity.

For multi-instance, we have the “magic” activity with ID <actual_activity_id>#multiInstanceBody. This is not represented explicitly in the BPMN XML, but is generated by the process engine. It can be understood like an embedded subprocess that contains the actual activity. This is not something we made up entirely, but somewhat covered by the BPMN specification. See https://blog.camunda.org/post/2015/06/why-we-re-implemented-bpmn-multi/ for details.

Cheers,
Thorben

1 Like

Hi @thorben, thanks for the explanation.

I understand most of your explanation, but I have a little confusion on what you said next higher instance. Could you please explain that?

Let’s say we have a process model like so:

When Task is executed, we have three activity instances organized in a hierarchy:

Process Instance 10 (instance of Process Definition)
                  ^
                  |
Subprocess Instance 11 (instance of Subprocess)
                  ^
                  |
Task Instance 12 (instance of Task)

Assume we call setVariable("key", "value", "Subprocess") API in the context of task instance 12. Then the API traverses the path from instance 12 upwards to the root until it finds an instance of Subprocess and sets the variable there. That’s what I mean with next higher instance. It stops searching once it finds the first such instance, because there cannot be another instance of Subprocess in that path. Of course, the overall tree can have multiple instances of Subprocess, but each path from a leaf to the root can contain at most one such instance.

3 Likes

Oh, now I got it!

But the bug is still valid, right?

Yes, it is. So you get an exception if when you specify the activity ID of the leaf node.

Okay then. Thanks for your clear explanation.

Best,
Ashlah

Hi, is there any rest api endpoint for setting a variable at activity scope?

1 Like

hi. Does this still work?

I am updating a variable in my sub process scope like this:

http://localhost:8080/engine-rest/execution/Task_09wzlbx:5467d99f-bbca-11e8-a5b2-ace2d3a04152#multiInstanceBody/localVariables/caseObject
PUT request
with variable:
{“value” : “someValue”, “type”: “String”}

but it gives me 405 (method not allowed )

Hi @Urvashi_Prasad,

Task_09wzlbx:5467d99f-bbca-11e8-a5b2-ace2d3a04152#multiInstanceBody is not an execute id but an activity instance id, so this request will not work anyway. On top of that, I guess the # symbol also messes up the URL unless you encode it properly.

Cheers,
Thorben

Hi @thorben Can you please tell me a way to add/update a variable on a subprocess scope using REST API?

I have been trying for a while now.
I have posted what all i have tried in this topic.

Thanks

Can anyone please let me know if this feature
https://docs.camunda.org/manual/7.7/user-guide/process-engine/variables/#setting-variables-to-specific-scope
is available through REST API or not.?

Hi Urvashi,

I faced the same scenario where I had to save a variable’s value at a specific scope using REST API,
This is what I found

  1. using https://docs.camunda.org/manual/7.9/reference/rest/process-instance/post-modification (hopefully)
  2. Use a unique key for the variable within a multiInstance Process.
  3. You can do a “jugaad (a flexible approach to solving a problem)” :
    • resolve/complete a task with the variable name eg testVar using rest api.
      Use the code below to save a copy of the variable’s last known value at activity scope
execution.setVariable("testVar",execution.getVariable("testVar"),execution.getCurrentActivity().getId());

OR

execution.setVariableLocal("testVar", execution.getVariable(“testVar”));

Thanks for your response Udit. I ended up doing a similar thing.
Added a process instance variable through rest api, and then use that to post it to sub-process scope.
works for now.

@thorben, I am not sure how #multiInstanceBody should be used. Let’s use the diagram you posted in this diagram. suppose I am in Task (task id = 100) now, and I want to create a variable which can be accessed in the Subprocess(parallel mulit instance) scope. Is it right that the code be like:

execution.setVariable(‘a’, ‘some value’, ‘100#multiInstanceBody’);

I tried this code, but it’s not correct, complaining scope not found.

Hi @liang,

The third parameter must have the following format: <activity ID in BPMN XML>#multiInstanceBody. So let’s say the ID of the activity named Task is task, then the parameter value should be task#multiInstanceBody.

Does that make sense?

Cheers,
Thorben

@thorben, thanks for your response. that makes sense, and it’s my understanding too.

In the Task:

var activityId = execution.getCurrentActivityId()+’#multiInstanceBody’;
execution.setVariable(‘insId’, ‘some value’, activityId);

In above code I will get an error complaining scope not found.

Hi @liang,

Please share a unit test on github reproducing this and I can take a look.

Cheers,
Thorben