Search code examples
jbpmbpmn

How to set a BPMN process variable from a user task outcome?


I have a simple approval BPMN workflow process. I want to assign the outcome (data output?) from a user task ("Approve") to a process variable that is then used in the exclusive gateway following that user task. The user task outcome is set within Java in a data/variables map when completing the task. Whatever I tried and searched, I could not get it to work. I keep getting the error "XOR split could not find at least one valid outgoing connection for split Approved?". Can someone please help?

I've tried specifying an with and a and much more.

My BPMN source:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:ns2="http://www.omg.org/spec/DD/20100524/DI"
             xmlns:ns3="http://www.omg.org/spec/DD/20100524/DC"
             xmlns:ns4="http://www.omg.org/spec/BPMN/20100524/DI"
             targetNamespace="http://www.omg.org/bpmn20">

  <itemDefinition id="_approval" isCollection="false" structureRef="java.lang.Boolean"/>

  <process id="modelio-approval"
           name="Process"
           isClosed="false"
           processType="None">

    <property id="approval" name="approval" itemSubjectRef="_approval"/>

    <startEvent id="StartId"
                name="Start"
                isInterrupting="true"
                parallelMultiple="false">
      <outgoing>FromStartToApprove</outgoing>
    </startEvent>

    <sequenceFlow id="FromStartToApprove"
                  name="FromStartToApprove"
                  sourceRef="StartId"
                  targetRef="ApproveId"/>

    <userTask id="ApproveId"
              name="Approve"
              isForCompensation="false"
              startQuantity="1"
              completionQuantity="1">
      <incoming>FromStartToApprove</incoming>
      <outgoing>ToApprovedGateway</outgoing>
      <ioSpecification>
        <dataOutput id="approvalOutRef" itemSubjectRef="_approval" name="approvalOut"/>
        <outputSet id="OutputSet_1">
          <dataOutputRefs>approvalOutRef</dataOutputRefs>
        </outputSet>
      </ioSpecification>
      <dataOutputAssociation id="doAssIdApproval">
        <sourceRef>approvalOutRef</sourceRef>
        <targetRef>approval</targetRef>
      </dataOutputAssociation>
    </userTask>

    <sequenceFlow id="ToApprovedGateway"
                  name="ToApprovedGateway"
                  sourceRef="ApproveId"
                  targetRef="ApprovedGateway"/>

    <exclusiveGateway id="ApprovedGateway"
                      name="Approved?"
                      gatewayDirection="Diverging">
      <incoming>ToApprovedGateway</incoming>
      <outgoing>ToFinish</outgoing>
      <outgoing>ToDisapproved</outgoing>
    </exclusiveGateway>

    <sequenceFlow id="ToFinish"
                  name="ToFinish"
                  sourceRef="ApprovedGateway"
                  targetRef="FinishId">
      <conditionExpression>approval == true</conditionExpression>
    </sequenceFlow>

    <sequenceFlow id="ToDisapproved"
                  name="disapproved"
                  sourceRef="ApprovedGateway"
                  targetRef="DisapprovedId">
      <conditionExpression>approval == false</conditionExpression>
    </sequenceFlow>

    <userTask id="FinishId"
              name="Finish"
              isForCompensation="false"
              startQuantity="1"
              completionQuantity="1">
      <incoming>ToFinish</incoming>
      <outgoing>ToEnd</outgoing>
    </userTask>

    <sequenceFlow sourceRef="FinishId"
                  targetRef="EndId"
                  name="ToEnd"
                  id="ToEnd"/>

    <endEvent id="EndId" name="End">
      <incoming>ToEnd</incoming>
    </endEvent>

    <endEvent id="DisapprovedId" name="Disapproved">
      <incoming>ToDisapproved</incoming>
    </endEvent>

  </process>

</definitions>

In the Java code, I try to set the task "approval" data on the "Approval" user task like this:

Map<String, Object> data = new HashMap(1);
data.put("approvalOut", true);
taskService.complete(taskId, userId, data);

But always the error message is:

Error: [modelio-approval:25 - Approved?:6] -- XOR split could not find at least one valid outgoing connection for split Approved?

I expect the flow to go to the "Finish" task (sequenceFlow "ToFinish"), but get the error "XOR split could not find at least one valid outgoing connection for split Approved?".

Should I perhaps use data input instead of output? What does taskService.complete(taskId, userId, data); actually set? Unfortunately there is no Javadoc.


Solution

  • Problem here is your task is not able to output its data to the process and hence to XOR. I think your task output mapping is wrong.

    Quick Solution:

    1. Click on your User Task(Approve) in editor and go to properties window. Find Section named 'Assignments'.
    2. In 'Data Inputs and Assignments' , create variable called 'userAction' of type boolean.
    3. In 'Data Outputs and Assignments' , use same name 'userAction',type boolean and in 'target' , select your process variable 'approval'. in 'target' it should be available in dropdown else consider there is error in your process variable creation.
    4. Save and deploy your bpmn.
    5. Java code for execution will change to
    Map<String, Object> data = new HashMap(1);
    data.put("userAction", true);
    taskService.complete(taskId, userId, data);
    

    Please try this solution and let me know if you face any issue.

    Explanation : You need to understand the scope of different variables for this.

    1. Process Variables - They are accessible across entire process elements.

    2. Task variables- These are created when task is initiated and destroyed when task gets over.

    When we design task, we create task variables. If we need any input to this task, 'input assignment' is used to take process variables data into task variables. Task variables are used for task processing. Once task work is completed and if we need to send output of task then task variables are mapped to process variables with help of 'output assignment'.

    Let me know if you have nay doubts. Happy to help you.