Question

I have created a 3 levels activiti workflow in alfresco where initiator initiates the tack & it goes to level1 approver. If level1 approves the task, it goes to level2 approver. If level2 approves the task, it goes to level 2 & soon. It also has timers which assigns the task to next level after expiration.

enter image description here

Similarly, if level 3 rejects the task, it goes to level2. If level 2 rejects, it goes to level1 but if level1 rejects the task, it is not going back to initiator.Except, it is working fine. XML is as below.

 <?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:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
  <process id="alfrescoThreeLevelFullWF" name="Alfresco Three Level Full Workflow">
   <startEvent id="alfrescoStartevent1" name="Alfresco start" activiti:formKey="wf:submitGroupReviewTask" activiti:initiator="${initiator.properties.userName}"></startEvent>
<userTask id="level1ApprovalTask" name="Level 1 Approval" activiti:candidateGroups="GROUP_Group1" activiti:formKey="wf:activitiReviewTask">
  <extensionElements>
    <activiti:taskListener event="complete" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
      <activiti:field name="script">
        <activiti:string>execution.setVariable('wf_reviewOutcome', task.getVariable('wf_reviewOutcome'));</activiti:string>
      </activiti:field>
    </activiti:taskListener>
  </extensionElements>
</userTask>
<boundaryEvent id="level1ApprovalTimer" name="Level 1 Approval Timer" cancelActivity="true" attachedToRef="level1ApprovalTask">
  <timerEventDefinition>
    <timeDuration>PT1M</timeDuration>
  </timerEventDefinition>
</boundaryEvent>
<exclusiveGateway id="gotLevel1Approval" name="Level 1 Approval Check"></exclusiveGateway>
<userTask id="level2ApprovalTask" name="Level 2 Approval" activiti:candidateGroups="GROUP_Group2" activiti:formKey="wf:activitiReviewTask">
  <extensionElements>
    <activiti:taskListener event="complete" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
      <activiti:field name="script">
        <activiti:string>execution.setVariable('wf_reviewOutcome', task.getVariable('wf_reviewOutcome'));</activiti:string>
      </activiti:field>
    </activiti:taskListener>
  </extensionElements>
</userTask>
<boundaryEvent id="level2ApprovalTimer" name="Level 2 Approval Timer" cancelActivity="true" attachedToRef="level2ApprovalTask">
  <timerEventDefinition>
    <timeDuration>PT1M</timeDuration>
  </timerEventDefinition>
</boundaryEvent>
<exclusiveGateway id="gotLevel2Approval" name="Level 2 Approval Check"></exclusiveGateway>
<userTask id="level3ApprovalTask" name="Level 3 Approval" activiti:candidateGroups="GROUP_Group3" activiti:formKey="wf:activitiReviewTask">
  <extensionElements>
    <activiti:taskListener event="complete" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
      <activiti:field name="script">
        <activiti:string>execution.setVariable('wf_reviewOutcome', task.getVariable('wf_reviewOutcome'));</activiti:string>
      </activiti:field>
    </activiti:taskListener>
  </extensionElements>
</userTask>
<exclusiveGateway id="gotLevel3Approval" name="Level3 Approval Check"></exclusiveGateway>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow1" name="" sourceRef="alfrescoStartevent1" targetRef="level1ApprovalTask"></sequenceFlow>
<sequenceFlow id="flow2" name="" sourceRef="level1ApprovalTask" targetRef="gotLevel1Approval"></sequenceFlow>
<sequenceFlow id="level1Approved" name="Level 1 Approved" sourceRef="gotLevel1Approval" targetRef="level2ApprovalTask">
  <conditionExpression xsi:type="tFormalExpression"><![CDATA[${wf_reviewOutcome == 'Approve'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow4" name="" sourceRef="level2ApprovalTask" targetRef="gotLevel2Approval"></sequenceFlow>
<sequenceFlow id="level2Approved" name="Level2 Approved" sourceRef="gotLevel2Approval" targetRef="level3ApprovalTask">
  <conditionExpression xsi:type="tFormalExpression"><![CDATA[${wf_reviewOutcome == 'Approve'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow6" name="" sourceRef="level3ApprovalTask" targetRef="gotLevel3Approval"></sequenceFlow>
<sequenceFlow id="level3Approved" name="Level 3 Approved" sourceRef="gotLevel3Approval" targetRef="endevent1">
  <conditionExpression xsi:type="tFormalExpression"><![CDATA[${wf_reviewOutcome == 'Approve'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="level1Unapproved" name="Level 1 Unapproved" sourceRef="gotLevel1Approval" targetRef="alfrescoStartevent1">
  <conditionExpression xsi:type="tFormalExpression"><![CDATA[${wf_reviewOutcome == 'Reject'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="level2Unapproved" name="Level 2 Unapproved" sourceRef="gotLevel2Approval" targetRef="level1ApprovalTask">
  <conditionExpression xsi:type="tFormalExpression"><![CDATA[${wf_reviewOutcome == 'Reject'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="level3Unapproved" name="Level 3 unapproved" sourceRef="gotLevel3Approval" targetRef="level2ApprovalTask">
  <conditionExpression xsi:type="tFormalExpression"><![CDATA[${wf_reviewOutcome == 'Reject'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow8" name="" sourceRef="level1ApprovalTimer" targetRef="level2ApprovalTask"></sequenceFlow>
<sequenceFlow id="flow9" name="" sourceRef="level2ApprovalTimer" targetRef="level3ApprovalTask"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_alfrescoThreeLevelFullWF">
    <bpmndi:BPMNPlane bpmnElement="alfrescoThreeLevelFullWF" id="BPMNPlane_alfrescoThreeLevelFullWF">
  <bpmndi:BPMNShape bpmnElement="alfrescoStartevent1" id="BPMNShape_alfrescoStartevent1">
    <omgdc:Bounds height="35" width="35" x="20" y="200"></omgdc:Bounds>
  </bpmndi:BPMNShape>
  <bpmndi:BPMNShape bpmnElement="level1ApprovalTask" id="BPMNShape_level1ApprovalTask">
    <omgdc:Bounds height="55" width="105" x="110" y="190"></omgdc:Bounds>
  </bpmndi:BPMNShape>
  <bpmndi:BPMNShape bpmnElement="level1ApprovalTimer" id="BPMNShape_level1ApprovalTimer">
    <omgdc:Bounds height="30" width="30" x="150" y="230"></omgdc:Bounds>
  </bpmndi:BPMNShape>
  <bpmndi:BPMNShape bpmnElement="gotLevel1Approval" id="BPMNShape_gotLevel1Approval">
    <omgdc:Bounds height="40" width="40" x="252" y="197"></omgdc:Bounds>
  </bpmndi:BPMNShape>
  <bpmndi:BPMNShape bpmnElement="level2ApprovalTask" id="BPMNShape_level2ApprovalTask">
    <omgdc:Bounds height="55" width="105" x="370" y="190"></omgdc:Bounds>
  </bpmndi:BPMNShape>
  <bpmndi:BPMNShape bpmnElement="level2ApprovalTimer" id="BPMNShape_level2ApprovalTimer">
    <omgdc:Bounds height="30" width="30" x="440" y="230"></omgdc:Bounds>
  </bpmndi:BPMNShape>
  <bpmndi:BPMNShape bpmnElement="gotLevel2Approval" id="BPMNShape_gotLevel2Approval">
    <omgdc:Bounds height="40" width="40" x="540" y="197"></omgdc:Bounds>
  </bpmndi:BPMNShape>
  <bpmndi:BPMNShape bpmnElement="level3ApprovalTask" id="BPMNShape_level3ApprovalTask">
    <omgdc:Bounds height="55" width="105" x="640" y="190"></omgdc:Bounds>
  </bpmndi:BPMNShape>
  <bpmndi:BPMNShape bpmnElement="gotLevel3Approval" id="BPMNShape_gotLevel3Approval">
    <omgdc:Bounds height="40" width="40" x="810" y="197"></omgdc:Bounds>
  </bpmndi:BPMNShape>
  <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
    <omgdc:Bounds height="35" width="35" x="920" y="200"></omgdc:Bounds>
  </bpmndi:BPMNShape>
  <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
    <omgdi:waypoint x="55" y="217"></omgdi:waypoint>
    <omgdi:waypoint x="110" y="217"></omgdi:waypoint>
  </bpmndi:BPMNEdge>
  <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
    <omgdi:waypoint x="215" y="217"></omgdi:waypoint>
    <omgdi:waypoint x="252" y="217"></omgdi:waypoint>
  </bpmndi:BPMNEdge>
  <bpmndi:BPMNEdge bpmnElement="level1Approved" id="BPMNEdge_level1Approved">
    <omgdi:waypoint x="292" y="217"></omgdi:waypoint>
    <omgdi:waypoint x="370" y="217"></omgdi:waypoint>
    <bpmndi:BPMNLabel>
      <omgdc:Bounds height="14" width="100" x="-40" y="7"></omgdc:Bounds>
    </bpmndi:BPMNLabel>
  </bpmndi:BPMNEdge>
  <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
    <omgdi:waypoint x="475" y="217"></omgdi:waypoint>
    <omgdi:waypoint x="540" y="217"></omgdi:waypoint>
  </bpmndi:BPMNEdge>
  <bpmndi:BPMNEdge bpmnElement="level2Approved" id="BPMNEdge_level2Approved">
    <omgdi:waypoint x="580" y="217"></omgdi:waypoint>
    <omgdi:waypoint x="640" y="217"></omgdi:waypoint>
    <bpmndi:BPMNLabel>
      <omgdc:Bounds height="14" width="100" x="-40" y="7"></omgdc:Bounds>
    </bpmndi:BPMNLabel>
  </bpmndi:BPMNEdge>
  <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
    <omgdi:waypoint x="745" y="217"></omgdi:waypoint>
    <omgdi:waypoint x="810" y="217"></omgdi:waypoint>
  </bpmndi:BPMNEdge>
  <bpmndi:BPMNEdge bpmnElement="level3Approved" id="BPMNEdge_level3Approved">
    <omgdi:waypoint x="850" y="217"></omgdi:waypoint>
    <omgdi:waypoint x="920" y="217"></omgdi:waypoint>
    <bpmndi:BPMNLabel>
      <omgdc:Bounds height="14" width="100" x="-45" y="7"></omgdc:Bounds>
    </bpmndi:BPMNLabel>
  </bpmndi:BPMNEdge>
  <bpmndi:BPMNEdge bpmnElement="level1Unapproved" id="BPMNEdge_level1Unapproved">
    <omgdi:waypoint x="272" y="237"></omgdi:waypoint>
    <omgdi:waypoint x="272" y="339"></omgdi:waypoint>
    <omgdi:waypoint x="155" y="339"></omgdi:waypoint>
    <omgdi:waypoint x="37" y="339"></omgdi:waypoint>
    <omgdi:waypoint x="37" y="235"></omgdi:waypoint>
    <bpmndi:BPMNLabel>
      <omgdc:Bounds height="42" width="100" x="-335" y="-94"></omgdc:Bounds>
    </bpmndi:BPMNLabel>
  </bpmndi:BPMNEdge>
  <bpmndi:BPMNEdge bpmnElement="level2Unapproved" id="BPMNEdge_level2Unapproved">
    <omgdi:waypoint x="560" y="197"></omgdi:waypoint>
    <omgdi:waypoint x="559" y="102"></omgdi:waypoint>
    <omgdi:waypoint x="422" y="102"></omgdi:waypoint>
    <omgdi:waypoint x="162" y="102"></omgdi:waypoint>
    <omgdi:waypoint x="162" y="190"></omgdi:waypoint>
    <bpmndi:BPMNLabel>
      <omgdc:Bounds height="42" width="100" x="-53" y="-12"></omgdc:Bounds>
    </bpmndi:BPMNLabel>
  </bpmndi:BPMNEdge>
  <bpmndi:BPMNEdge bpmnElement="level3Unapproved" id="BPMNEdge_level3Unapproved">
    <omgdi:waypoint x="830" y="237"></omgdi:waypoint>
    <omgdi:waypoint x="830" y="342"></omgdi:waypoint>
    <omgdi:waypoint x="692" y="342"></omgdi:waypoint>
    <omgdi:waypoint x="422" y="342"></omgdi:waypoint>
    <omgdi:waypoint x="422" y="245"></omgdi:waypoint>
    <bpmndi:BPMNLabel>
      <omgdc:Bounds height="42" width="100" x="-54" y="-32"></omgdc:Bounds>
    </bpmndi:BPMNLabel>
  </bpmndi:BPMNEdge>
  <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
    <omgdi:waypoint x="165" y="260"></omgdi:waypoint>
    <omgdi:waypoint x="164" y="278"></omgdi:waypoint>
    <omgdi:waypoint x="422" y="278"></omgdi:waypoint>
    <omgdi:waypoint x="422" y="245"></omgdi:waypoint>
  </bpmndi:BPMNEdge>
  <bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">
    <omgdi:waypoint x="455" y="260"></omgdi:waypoint>
    <omgdi:waypoint x="454" y="299"></omgdi:waypoint>
    <omgdi:waypoint x="692" y="299"></omgdi:waypoint>
    <omgdi:waypoint x="692" y="245"></omgdi:waypoint>
  </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
    </definitions>

Do anyone has any idea on how can i reassign this task back to initiator?

Was it helpful?

Solution

You need to have the approval process setup as a sub process. If level 1 rejects the task you set a process variable (i.e. approved = false) and simply exit. Now, setup a simple conditional on exit of the approval sub process to check if the activity was approved or not. If not, handle (i.e. back to initiator) otherwise, move on with the process.

There are other ways of handling, i.e. throw an exception which sends you back to the initiator, but the above will be the easiest to read and hence maintain in the future.

The other nice thing about setting this up as a sub process is that you can reuse the logic in other processes that need this style of approval.

Hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top