Behavior of variables in embedded subprocesses
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
12-14-2015 08:15 PM
The documentation did not have any information on this, so I wanted to confirm what my experimental testing found:
1) If you have an embedded subprocesses, you don't need to re-define the variables in the start event of the subprocess. A sequence flow coming out of a gateway in an embedded subprocess can read the variable values defined in the parent.
2) If you have a naming conflict with a variable with the same ID but different default values in the parent start event and subprocess start event, activiti will use the value from the parent. I find this unintuitive, I would expect the embedded subprocess to pick up on the most "local" variable, aka the one in the subprocess start event.
See BPMN below which I tested with. In the gateway in the embedded subprocess, the variable evaluated to "true", which was the value set in the parent start event (false was the value set in the subprocess start event).
<?xml version="1.0" encoding="UTF-8"?>
<definitions expressionLanguage="http://www.w3.org/1999/XPath"
id="definitions" targetNamespace="testSubProcessWithVarCategory"
typeLanguage="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns
mgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns
mgdi="http://www.omg.org/spec/DD/20100524/DI"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<process id="subprocessvarscope" isExecutable="true" name="test sub process">
<startEvent activiti:async="true" id="start" name="Start">
<extensionElements>
<activiti:formProperty default="true" id="task1Var1Id"
name="var1_name" required="true" type="boolean"/>
<activiti:formProperty id="task1Var2Id" name="var2_name"
required="true" type="string"/>
</extensionElements>
</startEvent>
<serviceTask activiti:async="true"
activiti:class="com.google.partnerservices.symphony.core.SymphonyTaskDelegate"
id="task1" name="task 1">
<extensionElements>
<activiti:field name="variableNames">
<activiti:string><![CDATA[task1Var1Id, task1Var2Id]]></activiti:string>
</activiti:field>
</extensionElements>
</serviceTask>
<subProcess id="subProcess1" name="subProcess">
<startEvent activiti:async="true" id="subProcessStart" name="sub Process Start Event">
<extensionElements>
<activiti:formProperty default="false"
id="task1Var1Id" name="var1_name"
required="true" type="boolean"/>
</extensionElements>
</startEvent>
<serviceTask activiti:async="true"
activiti:class="com.google.partnerservices.symphony.core.SymphonyTaskDelegate"
id="task2" name="if var1 = true"/>
<endEvent activiti:async="true" id="subProcessEnd" name="sub process end event"/>
<sequenceFlow id="subProcessFlow1"
sourceRef="subProcessStart" targetRef="exclusivegateway1"/>
<sequenceFlow id="subProcessFlow2" sourceRef="task2" targetRef="subProcessEnd"/>
<exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"/>
<sequenceFlow id="flow4" sourceRef="exclusivegateway1" targetRef="task2">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${task1Var1Id == 'true'}]]></conditionExpression>
</sequenceFlow>
<serviceTask activiti:async="true"
activiti:class="com.google.partnerservices.symphony.core.SymphonyTaskDelegate"
id="servicetask1" name="Service Task"/>
<sequenceFlow id="flow5" sourceRef="exclusivegateway1" targetRef="servicetask1">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${task1Var1Id == 'false'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow6" sourceRef="servicetask1" targetRef="subProcessEnd"/>
</subProcess>
<endEvent id="end" name="End"/>
<sequenceFlow id="flow1" sourceRef="start" targetRef="task1"/>
<sequenceFlow id="flow2" sourceRef="task1" targetRef="subProcess1"/>
<sequenceFlow id="flow3" sourceRef="subProcess1" targetRef="end"/>
</process>
</definitions>
Any reason why this behavior was chosen, since it feels more unintuitive? Can this be added to the Activiti documentation?
1) If you have an embedded subprocesses, you don't need to re-define the variables in the start event of the subprocess. A sequence flow coming out of a gateway in an embedded subprocess can read the variable values defined in the parent.
2) If you have a naming conflict with a variable with the same ID but different default values in the parent start event and subprocess start event, activiti will use the value from the parent. I find this unintuitive, I would expect the embedded subprocess to pick up on the most "local" variable, aka the one in the subprocess start event.
See BPMN below which I tested with. In the gateway in the embedded subprocess, the variable evaluated to "true", which was the value set in the parent start event (false was the value set in the subprocess start event).
<?xml version="1.0" encoding="UTF-8"?>
<definitions expressionLanguage="http://www.w3.org/1999/XPath"
id="definitions" targetNamespace="testSubProcessWithVarCategory"
typeLanguage="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns

xmlns

xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<process id="subprocessvarscope" isExecutable="true" name="test sub process">
<startEvent activiti:async="true" id="start" name="Start">
<extensionElements>
<activiti:formProperty default="true" id="task1Var1Id"
name="var1_name" required="true" type="boolean"/>
<activiti:formProperty id="task1Var2Id" name="var2_name"
required="true" type="string"/>
</extensionElements>
</startEvent>
<serviceTask activiti:async="true"
activiti:class="com.google.partnerservices.symphony.core.SymphonyTaskDelegate"
id="task1" name="task 1">
<extensionElements>
<activiti:field name="variableNames">
<activiti:string><![CDATA[task1Var1Id, task1Var2Id]]></activiti:string>
</activiti:field>
</extensionElements>
</serviceTask>
<subProcess id="subProcess1" name="subProcess">
<startEvent activiti:async="true" id="subProcessStart" name="sub Process Start Event">
<extensionElements>
<activiti:formProperty default="false"
id="task1Var1Id" name="var1_name"
required="true" type="boolean"/>
</extensionElements>
</startEvent>
<serviceTask activiti:async="true"
activiti:class="com.google.partnerservices.symphony.core.SymphonyTaskDelegate"
id="task2" name="if var1 = true"/>
<endEvent activiti:async="true" id="subProcessEnd" name="sub process end event"/>
<sequenceFlow id="subProcessFlow1"
sourceRef="subProcessStart" targetRef="exclusivegateway1"/>
<sequenceFlow id="subProcessFlow2" sourceRef="task2" targetRef="subProcessEnd"/>
<exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"/>
<sequenceFlow id="flow4" sourceRef="exclusivegateway1" targetRef="task2">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${task1Var1Id == 'true'}]]></conditionExpression>
</sequenceFlow>
<serviceTask activiti:async="true"
activiti:class="com.google.partnerservices.symphony.core.SymphonyTaskDelegate"
id="servicetask1" name="Service Task"/>
<sequenceFlow id="flow5" sourceRef="exclusivegateway1" targetRef="servicetask1">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${task1Var1Id == 'false'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow6" sourceRef="servicetask1" targetRef="subProcessEnd"/>
</subProcess>
<endEvent id="end" name="End"/>
<sequenceFlow id="flow1" sourceRef="start" targetRef="task1"/>
<sequenceFlow id="flow2" sourceRef="task1" targetRef="subProcess1"/>
<sequenceFlow id="flow3" sourceRef="subProcess1" targetRef="end"/>
</process>
</definitions>
Any reason why this behavior was chosen, since it feels more unintuitive? Can this be added to the Activiti documentation?
Labels:
- Labels:
-
Archive
2 REPLIES 2
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
12-16-2015 04:39 AM
1. Correct. Embedded subprocesses are a part of the process instance like any other activity. Call Activity is the only exception to that.
2. True. This is one of the shortcomings in v5 we're fixing in v6. In v6, there will be a 'subprocess scope' for variables and it will work as you describe (with the local variables)
But in this particular case, I would think the local variable did get chosen. It seems your example is missing from the post. Can you reupload it?
2. True. This is one of the shortcomings in v5 we're fixing in v6. In v6, there will be a 'subprocess scope' for variables and it will work as you describe (with the local variables)
But in this particular case, I would think the local variable did get chosen. It seems your example is missing from the post. Can you reupload it?
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
12-17-2015 04:20 PM
Hrm, this BPMN just does not want to post… I tried yesterday and got stuck in an approval queue. Trying again, uploading as an attachment.
