I have a workflow in Alfresco Share where I need 4 parallel reviews / approval tasks. I am currently able to create 4 tasks but they all go to the same candidate group. Members of that group are able to approve, but they have all 4 tasks in their "My Tasks". Each of these tasks is unassigned. The remaining 3 groups receive no tasks.
Do I need to include code in the multiInstanceLoopCharacteristics that assigns the tasks to the pooled actors? I have read the documentation Activiti User Guide and see that a list of users can be created. Where would I set that variable and would that be with execution.setVariable()? Any help would be greatly appreciated.
<userTask id="miTasks" name="My Task ${loopCounter}" activiti:assignee="${assignee}">
<multiInstanceLoopCharacteristics isSequential="false">
<loopDataInputRef>assigneeList</loopDataInputRef>
<inputDataItem name="assignee" />
</multiInstanceLoopCharacteristics>
</userTask>
Here is my code:
<userTask id="userTask10" name="Approvers Review" activiti:candidateGroups="GROUP_accountsManager,GROUP_manfacturingManager,GROUP_engineeringManager,GROUP_qualityManager" activiti:formKey="lec:appoversreview">
<documentation>Review task
Note: When a reject occurs, workflow is routed back to Originator assign, bypassing other approvers.
</documentation>
<extensionElements>
<activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
<activiti:field name="script">
<activiti:string>
<![CDATA[if (typeof bpm_workflowDueDate != 'undefined') task.dueDate = bpm_workflowDueDate;
if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;;]]>
</activiti:string>
</activiti:field>
</activiti:taskListener>
<activiti:taskListener event="complete" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
<activiti:field name="script">
<activiti:string>
<![CDATA[execution.setVariable('lec_appoversreviewtransitions',task.getVariableLocal('lec_appoversreviewtransitions') );
if(task.getVariableLocal('lec_appoversreviewtransitions') == 'Approve') {
execution.setVariable('lec_appoversreviewapprovalcount', lec_appoversreviewapprovalcount + 1);
}
if(task.getVariableLocal('lec_appoversreviewtransitions') == 'Reject') {
execution.setVariable('lec_appoversreviewapprovalcount',5);
execution.setVariable('lec_appoversreviewtransitions', task.getVariableLocal('lec_appoversreviewtransitions'));
}
logger.info("Count: " + execution.getVariable('lec_appoversreviewapprovalcount') )]]>
</activiti:string>
</activiti:field>
</activiti:taskListener>
</extensionElements>
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>4</loopCardinality>
<completionCondition>${lec_appoversreviewapprovalcount >= lec_appoversreviewrequiredapprovalcount}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
<exclusiveGateway id="exclusiveGateway1"></exclusiveGateway>
<sequenceFlow id="sequenceFlow22" sourceRef="userTask10" targetRef="exclusiveGateway1"></sequenceFlow>
<sequenceFlow id="sequenceFlow23" name="Rejected" sourceRef="exclusiveGateway1" targetRef="userTask9">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${lec_appoversreviewtransitions == 'Rejected'}]]>
</conditionExpression>
</sequenceFlow>
<sequenceFlow id="sequenceFlow24" name="Approved" sourceRef="exclusiveGateway1" targetRef="exclusiveGateway2"></sequenceFlow>
<exclusiveGateway id="exclusiveGateway2"></exclusiveGateway>
David,
One slightly more simple way around the multi-instance loop situation would be to just create a parallel gateway that splits into those 4 tasks and rejoins after they're completed; each task could use the same form and be directly assigned to those individual candidate groups that you're assigning. The functionality of rerouting after a rejection that you've shown above is entirely still plausible with this configuration as well.
There are a couple of other posts, particularly this one, where people have discussed the multi-instance functionality before and highlighted a couple points in getting it working. But yes, you are correct - the multi-instance is probably a solid route to go here and has the potential capabilities you're looking for.
The Activiti Modeler has assign functionality or you can establish the list of users as a variable.
Hope this helps,
-JEarles
bp3
Thanks for your reply. I am testing now ..
I am still a bit confused. I have assigned bpm_GroupAssignees to the activiti:collection and created and activiti:elementVariable "reviewGroup", my assumption being that the foreach loop would use bpm_groupAssignees as the source collection and reviewGroup at the variable. When I start the review step the workflow throws an exception "java.lang.NullPointerException: null".
I've seen other code that uses but I thought that the activiti:elementVariable would achieve the same thing.
<resourceAssignmentExpression>
<formalExpression>${groupAssignee.properties.authorityName}</formalExpression>
</resourceAssignmentExpression>
Any insight would be greatly appreciated.
My updated code:
<userTask id="userTask1" name="Review step" activiti:candidateGroups="GROUP_approver_accounts,GROUP_approver_engineering,GROUP_approver_document" activiti:formKey="agsystemselect:reviewstep">
<documentation>Review task</documentation>
<extensionElements>
<activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
<activiti:field name="script">
<activiti:string><![CDATA[if (typeof bpm_workflowDueDate != 'undefined') task.dueDate = bpm_workflowDueDate;
if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;;]]></activiti:string>
</activiti:field>
</activiti:taskListener>
<activiti:taskListener event="complete" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
<activiti:field name="script">
<activiti:string><![CDATA[if(task.getVariableLocal('agsystemselect_reviewsteptransitions') == 'Approve') {
execution.setVariable('agsystemselect_reviewstepapprovalcount', agsystemselect_reviewstepapprovalcount + 1);
}
if(task.getVariableLocal('agsystemselect_reviewsteptransitions') == 'Reject'){
execution.setVariable('agsystemselect_reviewstepapprovalcount', 4);
}]]></activiti:string>
</activiti:field>
</activiti:taskListener>
</extensionElements>
<multiInstanceLoopCharacteristics isSequential="false" activiti:collection="bpm_groupAssignees" activiti:elementVariable="reviewGroup">
<loopCardinality>3</loopCardinality>
<completionCondition>${agsystemselect_reviewstepapprovalcount >= agsystemselect_reviewsteprequiredapprovalcount}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
Ask for and offer help to other Alfresco Process Services and Activiti Users and members of the Alfresco team.
By using this site, you are agreeing to allow us to collect and use cookies as outlined in Alfresco’s Cookie Statement and Terms of Use (and you have a legitimate interest in Alfresco and our products, authorizing us to contact you in such methods). If you are not ok with these terms, please do not use this website.