cancel
Showing results for 
Search instead for 
Did you mean: 

Skip expression on User Task

hari
Star Contributor
Star Contributor
Hi,

I see a property called "Skip expression" on a user task in eclipse. I could not see any information being available about it anywhere so I am requesting you here to please tell us more about it.

Thanks,
Hari.
11 REPLIES 11

martin_grofcik
Confirmed Champ
Confirmed Champ
Hi Hari,

Have a look on org.activiti.examples.bpmn.usertask.SkipExpressionUserTaskTest
Regards
Martin

hari
Star Contributor
Star Contributor
Thanks Martin,

Looking at that, I could see that if the expression evaluates to true, the user task is skipped and the execution moves to the next step.
So from which version of Activiti is this available in community version ?
Is it also available in Activiti Enterprise ?  If so, from which version ?

jbarrez
Star Contributor
Star Contributor
"So from which version of Activiti is this available in community version ? "

5.17

"Is it also available in Activiti Enterprise ? If so, from which version ?"

Yes … but not via the editor (yet)

hari
Star Contributor
Star Contributor
My BPMN goes below.

<code>
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlnsSmiley Surprisedmgdc="http://www.omg.org/spec/DD/20100524/DC" xmlnsSmiley Surprisedmgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://activiti.org/bpmn20" id="definitions">
  <process id="test1_called" name="called process" isExecutable="true">
    <startEvent id="start" name="start process">
      <extensionElements>
        <activiti:formProperty id="fname" name="FName" type="string"></activiti:formProperty>
      </extensionElements>
    </startEvent>
    <userTask id="CNV_human1" name="CNV_human1" activiti:assignee="Hari" activiti:skipExpression="${execution.getVariable('fname')==&quot;Hari&quot;}">
      <extensionElements>
        <activiti:formProperty id="name" name="Name" type="string"></activiti:formProperty>
        <activiti:formProperty id="myenum" name="Enum" type="enum">
          <activiti:value id="Hi" name="Hello"></activiti:value>
          <activiti:value id="Bye" name="Tata"></activiti:value>
        </activiti:formProperty>
      </extensionElements>
    </userTask>
    <userTask id="CNV_human11" name="CNV_human11" activiti:assignee="Hari"></userTask>
    <endEvent id="end"></endEvent>
    <sequenceFlow id="flow2" sourceRef="CNV_human1" targetRef="CNV_human11"></sequenceFlow>
    <sequenceFlow id="flow3" sourceRef="CNV_human11" targetRef="end"></sequenceFlow>
    <userTask id="usertask1" name="Not Hari" activiti:assignee="Hari"></userTask>
    <sequenceFlow id="flow5" sourceRef="usertask1" targetRef="end"></sequenceFlow>
    <exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway" default="flow8"></exclusiveGateway>
    <sequenceFlow id="flow6" sourceRef="start" targetRef="exclusivegateway1"></sequenceFlow>
    <sequenceFlow id="flow7" sourceRef="exclusivegateway1" targetRef="CNV_human1">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${fname=="Hari"}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="flow8" sourceRef="exclusivegateway1" targetRef="usertask1"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_test1_called">
    <bpmndi:BPMNPlane bpmnElement="test1_called" id="BPMNPlane_test1_called">
      <bpmndi:BPMNShape bpmnElement="start" id="BPMNShape_start">
        <omgdc:Bounds height="35.0" width="35.0" x="60.0" y="173.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="CNV_human1" id="BPMNShape_CNV_human1">
        <omgdc:Bounds height="60.0" width="100.0" x="310.0" y="59.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="CNV_human11" id="BPMNShape_CNV_human11">
        <omgdc:Bounds height="60.0" width="100.0" x="470.0" y="59.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="end" id="BPMNShape_end">
        <omgdc:Bounds height="35.0" width="35.0" x="790.0" y="153.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
        <omgdc:Bounds height="55.0" width="105.0" x="411.0" y="202.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1">
        <omgdc:Bounds height="40.0" width="40.0" x="190.0" y="170.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="410.0" y="89.0"></omgdi:waypoint>
        <omgdi:waypoint x="470.0" y="89.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="520.0" y="119.0"></omgdi:waypoint>
        <omgdi:waypoint x="807.0" y="153.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
        <omgdi:waypoint x="463.0" y="202.0"></omgdi:waypoint>
        <omgdi:waypoint x="807.0" y="188.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
        <omgdi:waypoint x="95.0" y="190.0"></omgdi:waypoint>
        <omgdi:waypoint x="190.0" y="190.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
        <omgdi:waypoint x="210.0" y="170.0"></omgdi:waypoint>
        <omgdi:waypoint x="210.0" y="89.0"></omgdi:waypoint>
        <omgdi:waypoint x="310.0" y="89.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
        <omgdi:waypoint x="210.0" y="210.0"></omgdi:waypoint>
        <omgdi:waypoint x="210.0" y="229.0"></omgdi:waypoint>
        <omgdi:waypoint x="411.0" y="229.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>
</code>

hari
Star Contributor
Star Contributor
Question # 2
I've seen skip expression on sequence flow also. When I had both condition and skip expression, it just followed the condition and skipped the skip expression. Can someone please tell me whats the difference between condition and skip expression on a sequence flow ?

Question # 3
I was able to use the below code to get the task skipped partially but not how I wanted it to be. With the below scenario, I could see 2 user tasks getting created 1st one is CNV_human1 and CNV_human11. So I could understand that since the skip expression was on CNV_human1 and since it evaluated to true, the execution went ahead to CNV_human11. But my problem is I still see CNV_human1 in my inbox.
<code>
  Map<String,Object> variables = new HashMap<String, Object>();
  variables.put("_ACTIVITI_SKIP_EXPRESSION_ENABLED", true);
  variables.put("fname", "Hari");
 
  tas.startBPM("Hari", "test1_called", variables, "MyTenant");
</code>

Question#4
Now as you read in Question#3, I have 2 user tasks in my inbox but when I try to complete any of them, I see this error "UserTask should not be signalled before complete". What is it that I have done incorrectly here ?

jbarrez
Star Contributor
Star Contributor
Q3) The skip expression on a sequence flow will _take_ it, regardless of the condition:
<code>
Expression skipExpression = outgoingTransition.getSkipExpression();
     
      if (!SkipExpressionUtil.isSkipExpressionEnabled(execution, skipExpression)) {
        if (defaultSequenceFlow == null || !outgoingTransition.getId().equals(defaultSequenceFlow)) {
          Condition condition = (Condition) outgoingTransition.getProperty(BpmnParse.PROPERTYNAME_CONDITION);
          if (condition == null || !checkConditions || condition.evaluate(outgoingTransition.getId(), execution)) {
            transitionsToTake.add(outgoingTransition);
          }
        }
       
      } else if (SkipExpressionUtil.shouldSkipFlowElement(execution, skipExpression)){
        transitionsToTake.add(outgoingTransition);
      }
    }
</code>

Q3) That should not happen. If the skip expression is true, the task is completed immediately after creation:

<code>
task.fireEvent(TaskListener.EVENTNAME_CREATE);

    if (SkipExpressionUtil.isSkipExpressionEnabled(execution, activeSkipExpression) &&
        SkipExpressionUtil.shouldSkipFlowElement(execution, activeSkipExpression)) {
     
      task.complete(null, false);
    }
</code>

Q4) That sounds odd … do you have a simple unit test with this process demonstrating this?

hari
Star Contributor
Star Contributor
Thanks  Barrez,

Please find the Unit Test Case attached here as txt. Please rename it to zip and unzip the content.
One difference (Not sure what caused the difference) which I noticed now is that, even after I have mentioned Skip Expression on Human Task1, earlier I had 2 tasks in my inbox one at Human Task1 and the other at Human Task2 and I wasn't able to complete any of them. Now here I just see one Human Task at Human Task1 which has skip expression but still it got struck there.
Am I doing something wrong here ? 

jbarrez
Star Contributor
Star Contributor
You need to add the special variable to enable it:

<code>
mpvar.put("_ACTIVITI_SKIP_EXPRESSION_ENABLED", true);
</code>


hari
Star Contributor
Star Contributor
Thanks Barrez. I just tried it with your suggestion.
Now I see both the Human Tasks assigned to me. Which should not be the case. The first task should have been completed.  Below is the output that I see.

STARTED PROCESS
=====================================================================================
Human Task 1
Human Task 2
END
=====================================================================================