mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
Merged 5.0.N (5.0.3) to HEAD (5.1)
109441: Merged V4.2-BUG-FIX (4.2.6) to 5.0.N (5.0.3) 109381: Merged DEV to V4.2-BUG-FIX (4.2.5) MNT-11472: [PUBLIC-WORKFLOW-API] Processing of Association Properties in Tasks convert incorrect - Dictionary service will be used to find association definition, when assoc def is absent for RestVariableHelper. Also, unit test was added. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@109501 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -778,6 +778,7 @@
|
||||
<bean id="restVariableHelper" class="org.alfresco.rest.workflow.api.impl.RestVariableHelper">
|
||||
<property name="nodeService" ref="nodeService" />
|
||||
<property name="namespaceService" ref="namespaceService" />
|
||||
<property name="dictionaryService" ref="DictionaryService" />
|
||||
</bean>
|
||||
|
||||
<bean id="baseWorkflowRest" class="org.alfresco.rest.workflow.api.impl.WorkflowRestImpl" abstract="true">
|
||||
|
@@ -39,6 +39,7 @@ import org.alfresco.rest.workflow.api.model.VariableScope;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -60,6 +61,8 @@ public class RestVariableHelper
|
||||
|
||||
private WorkflowQNameConverter qNameConverter;
|
||||
|
||||
private DictionaryService dictionaryService;
|
||||
|
||||
public static final Set<String> INTERNAL_PROPERTIES = new HashSet<String>(Arrays.asList(ActivitiConstants.VAR_TENANT_DOMAIN));
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
@@ -72,6 +75,11 @@ public class RestVariableHelper
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
protected WorkflowQNameConverter getQNameConverter()
|
||||
{
|
||||
if (qNameConverter == null)
|
||||
@@ -174,6 +182,17 @@ public class RestVariableHelper
|
||||
{
|
||||
// Not defined as a property, check if it's an association
|
||||
AssociationDefinition assocDef = context.getAssociationDefinition(variable.getName());
|
||||
if (assocDef == null)
|
||||
{
|
||||
// Try to get an association definition through dictionary
|
||||
String[] prefixLocalName = variable.getName().split("_");
|
||||
if (prefixLocalName.length == 2)
|
||||
{
|
||||
QName qName = QName.createQName(prefixLocalName[0], prefixLocalName[1], namespaceService);
|
||||
assocDef = dictionaryService.getAssociation(qName);
|
||||
}
|
||||
}
|
||||
|
||||
if (assocDef != null)
|
||||
{
|
||||
// Type of variable is the target class-name
|
||||
@@ -182,8 +201,7 @@ public class RestVariableHelper
|
||||
}
|
||||
else
|
||||
{
|
||||
// Variable is not a declared property not association on the type-definition. Revert to using the actual raw value
|
||||
// as base for conversion.
|
||||
// Variable is not declared as property or association type-def. Use actual raw value as base for conversion.
|
||||
variable.setValue(getSafePropertyValue(value));
|
||||
variable.setType(extractTypeStringFromValue(value));
|
||||
}
|
||||
|
@@ -486,6 +486,109 @@ public class TaskWorkflowApiTest extends EnterpriseWorkflowTestApi
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test association definition extraction from the dictionary as per MNT-11472.
|
||||
*
|
||||
* We are going to test association definition extraction through dictionary, when one is not retrieved in context.
|
||||
* Context doesn't contains all type definitions, because it requires entire history extraction of a process that causes performance implications.
|
||||
* Type definition extraction from the dictionary is quite fast and it doesn't affect performance.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testAssociationDefinitionExtraction() throws Exception
|
||||
{
|
||||
RequestContext requestContext = initApiClientWithTestUser();
|
||||
|
||||
// The "wbpm:delegatee" custom association is defined in bpmDelegateeModel.xml. This association has "cm:person" target type.
|
||||
final String delegatee = "wbpm_delegatee";
|
||||
final String user = requestContext.getRunAsUser();
|
||||
final String networkId = requestContext.getNetworkId();
|
||||
|
||||
// Get person
|
||||
final ActivitiScriptNode person = TenantUtil.runAsUserTenant(new TenantRunAsWork<ActivitiScriptNode>()
|
||||
{
|
||||
@Override
|
||||
public ActivitiScriptNode doWork() throws Exception
|
||||
{
|
||||
return getPersonNodeRef(user);
|
||||
}
|
||||
}, user, networkId);
|
||||
|
||||
// Start custom process instance
|
||||
ProcessInstance processInstance = TenantUtil.runAsUserTenant(new TenantRunAsWork<ProcessInstance>()
|
||||
{
|
||||
@Override
|
||||
public ProcessInstance doWork() throws Exception
|
||||
{
|
||||
deployProcessDefinition("workflow/testCustomDelegatee.bpmn20.xml");
|
||||
String processDefinitionKey = "@" + networkId + "@myProcess";
|
||||
Map<String, Object> variables = new HashMap<String, Object>();
|
||||
variables.put("bpm_assignee", person);
|
||||
variables.put("wf_notifyMe", Boolean.FALSE);
|
||||
variables.put(WorkflowConstants.PROP_INITIATOR, person);
|
||||
return activitiProcessEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey, "myProcessKey", variables);
|
||||
}
|
||||
}, user, networkId);
|
||||
|
||||
// Get task
|
||||
Task activeTask = activitiProcessEngine.getTaskService().createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
|
||||
assertNotNull(activeTask);
|
||||
try
|
||||
{
|
||||
TasksClient tasksClient = publicApiClient.tasksClient();
|
||||
|
||||
// Define the "wbpm_delegatee" variable for the taskDefine delegatee user name. POST request will be executed.
|
||||
JSONArray variablesArray = new JSONArray();
|
||||
JSONObject variableBody = new JSONObject();
|
||||
variableBody.put("name", delegatee);
|
||||
variableBody.put("value", user);
|
||||
variableBody.put("scope", "local");
|
||||
variablesArray.add(variableBody);
|
||||
|
||||
try
|
||||
{
|
||||
// Set variable for the task.
|
||||
JSONObject response = tasksClient.createTaskVariables(activeTask.getId(), variablesArray);
|
||||
assertNotNull(response);
|
||||
JSONObject variable = (JSONObject) response.get("entry");
|
||||
assertEquals(delegatee, variable.get("name"));
|
||||
|
||||
// Check that d:noderef type was returned with appropriate nodeRef Id value.
|
||||
assertEquals("d:noderef", variable.get("type"));
|
||||
assertEquals(person.getNodeRef().getId(), variable.get("value"));
|
||||
|
||||
// Get process variables. GET request will be executed.
|
||||
response = publicApiClient.processesClient().getProcessvariables(processInstance.getId());
|
||||
assertNotNull(response);
|
||||
assertTrue(delegatee + " variable was not set", response.toJSONString().contains(delegatee));
|
||||
JSONArray entries = (JSONArray) response.get("entries");
|
||||
|
||||
// Find "wbpm_delegatee" variable.
|
||||
for (Object entry : entries)
|
||||
{
|
||||
variable = (JSONObject) ((JSONObject) entry).get("entry");
|
||||
if (variable.get("name").equals(delegatee))
|
||||
{
|
||||
// Check that type corresponds to the target class.
|
||||
// It means that assoc type def was retrieved successfully from the dictionary.
|
||||
assertEquals("cm:person", variable.get("type"));
|
||||
// Value should be an actual user name.
|
||||
assertEquals(user, variable.get("value"));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (PublicApiException ex)
|
||||
{
|
||||
fail("Unexpected result " + ex);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
cleanupProcessInstance(processInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testUpdateTaskAuthorization() throws Exception
|
||||
|
96
source/test-resources/models/bpmDelegateeModel.xml
Executable file
96
source/test-resources/models/bpmDelegateeModel.xml
Executable file
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<model xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.alfresco.org/model/dictionary/1.0 ../../../../webapps/alfresco/WEB-INF/classes/alfresco/model/modelSchema.xsd"
|
||||
xmlns="http://www.alfresco.org/model/dictionary/1.0" name="wbpm:AssigneeTest">
|
||||
|
||||
<description>BPM Assignee Test Model</description>
|
||||
<author>Workdesk</author>
|
||||
<version>1.0</version>
|
||||
<imports>
|
||||
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
|
||||
<import uri="http://www.alfresco.org/model/bpm/1.0" prefix="bpm"/>
|
||||
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
|
||||
</imports>
|
||||
<namespaces>
|
||||
<namespace uri="workdesk.alf.bpm" prefix="wbpm"/>
|
||||
</namespaces>
|
||||
<constraints>
|
||||
<constraint name="wbpm:listDelegation" type="LIST">
|
||||
<parameter name="allowedValues">
|
||||
<list>
|
||||
<value>Expression</value>
|
||||
<value>OnCreate</value>
|
||||
<value>Other</value>
|
||||
</list>
|
||||
</parameter>
|
||||
</constraint>
|
||||
</constraints>
|
||||
<types>
|
||||
<type name="wbpm:DelegateTask">
|
||||
<title>Delegation Task (Assignee)</title>
|
||||
<parent>bpm:workflowTask</parent>
|
||||
<properties>
|
||||
<property name="wbpm:nextStep">
|
||||
<title>Next Step</title>
|
||||
<type>d:text</type>
|
||||
<protected>false</protected>
|
||||
<mandatory>false</mandatory>
|
||||
<multiple>false</multiple>
|
||||
<default>Expression</default>
|
||||
<constraints>
|
||||
<constraint ref="wbpm:listDelegation" />
|
||||
</constraints>
|
||||
</property>
|
||||
</properties>
|
||||
<associations>
|
||||
<association name="wbpm:delegatee">
|
||||
<title>Responsible person</title>
|
||||
<source>
|
||||
<mandatory>false</mandatory>
|
||||
<many>false</many>
|
||||
</source>
|
||||
<target>
|
||||
<class>cm:person</class>
|
||||
<mandatory>true</mandatory>
|
||||
<many>false</many>
|
||||
</target>
|
||||
</association>
|
||||
</associations>
|
||||
</type>
|
||||
<type name="wbpm:expressionTask">
|
||||
<title>Expression Task (Assignee)</title>
|
||||
<parent>bpm:workflowTask</parent>
|
||||
<mandatory-aspects>
|
||||
<aspect>wbpm:CommentAspect</aspect>
|
||||
</mandatory-aspects>
|
||||
</type>
|
||||
<type name="wbpm:onCreateTask">
|
||||
<title>On Create (Assignee)</title>
|
||||
<parent>bpm:workflowTask</parent>
|
||||
<mandatory-aspects>
|
||||
<aspect>wbpm:CommentAspect</aspect>
|
||||
</mandatory-aspects>
|
||||
</type>
|
||||
<type name="wbpm:otherTask">
|
||||
<title>Other Task (Assignee)</title>
|
||||
<parent>bpm:workflowTask</parent>
|
||||
<mandatory-aspects>
|
||||
<aspect>wbpm:CommentAspect</aspect>
|
||||
</mandatory-aspects>
|
||||
</type>
|
||||
</types>
|
||||
<aspects>
|
||||
<aspect name="wbpm:CommentAspect">
|
||||
<title>Step Comment</title>
|
||||
<properties>
|
||||
<property name="wbpm:comment">
|
||||
<title>Comment</title>
|
||||
<type>d:text</type>
|
||||
<protected>false</protected>
|
||||
<mandatory>false</mandatory>
|
||||
<multiple>true</multiple>
|
||||
</property>
|
||||
</properties>
|
||||
</aspect>
|
||||
</aspects>
|
||||
</model>
|
@@ -18,6 +18,7 @@
|
||||
<property name="models">
|
||||
<list>
|
||||
<value>models/custom-model.xml</value>
|
||||
<value>models/bpmDelegateeModel.xml</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
100
source/test-resources/workflow/testCustomDelegatee.bpmn20.xml
Executable file
100
source/test-resources/workflow/testCustomDelegatee.bpmn20.xml
Executable file
@@ -0,0 +1,100 @@
|
||||
<?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="myProcess" name="My process" isExecutable="true">
|
||||
<startEvent id="alfrescoStartEv" name="Start Assignee Process" activiti:formKey="wf:submitAdhocTask"></startEvent>
|
||||
<userTask id="delegateToAssignee" name="Delegate Task" activiti:candidateGroups="GROUP_ALFRESCO_ADMINISTRATORS" activiti:formKey="wbpm:DelegateTask">
|
||||
<extensionElements>
|
||||
<activiti:taskListener event="complete" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
|
||||
<activiti:field name="script">
|
||||
<activiti:string><![CDATA[execution.setVariable('wbpm_nextStep', task.getVariable('wbpm_nextStep'));
|
||||
execution.setVariable('wbpm_delegatee', task.getVariable('wbpm_delegatee'));]]></activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
</userTask>
|
||||
<sequenceFlow id="flow1" sourceRef="alfrescoStartEv" targetRef="delegateToAssignee"></sequenceFlow>
|
||||
<exclusiveGateway id="DelegateeGateway" name="Exclusive Gateway" default="otherFlow"></exclusiveGateway>
|
||||
<sequenceFlow id="flow2" sourceRef="delegateToAssignee" targetRef="DelegateeGateway"></sequenceFlow>
|
||||
<userTask id="oncreateUT" name="On Create Assignee" activiti:formKey="wbpm:onCreateTask">
|
||||
<extensionElements>
|
||||
<activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
|
||||
<activiti:field name="script">
|
||||
<activiti:string><![CDATA[task.assignee = execution.getVariable("wbpm_delegatee");]]></activiti:string>
|
||||
</activiti:field>
|
||||
</activiti:taskListener>
|
||||
</extensionElements>
|
||||
</userTask>
|
||||
<sequenceFlow id="OnCreateFlow" sourceRef="DelegateeGateway" targetRef="oncreateUT">
|
||||
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${wbpm_nextStep == 'OnCreate'}]]></conditionExpression>
|
||||
</sequenceFlow>
|
||||
<userTask id="expressionUT" name="Expression Assignee" activiti:assignee="${wbpm_delegatee.properties.userName}" activiti:formKey="wbpm:expressionTask"></userTask>
|
||||
<sequenceFlow id="ExpressionFlow" sourceRef="DelegateeGateway" targetRef="expressionUT">
|
||||
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${wbpm_nextStep == 'Expression'}]]></conditionExpression>
|
||||
</sequenceFlow>
|
||||
<userTask id="otherUT" name="Default Assgnee Task" activiti:candidateGroups="GROUP_ALFRESCO_ADMINISTRATORS" activiti:formKey="wbpm:otherTask"></userTask>
|
||||
<sequenceFlow id="otherFlow" sourceRef="DelegateeGateway" targetRef="otherUT"></sequenceFlow>
|
||||
<endEvent id="endevent1" name="End"></endEvent>
|
||||
<sequenceFlow id="flow3" sourceRef="expressionUT" targetRef="endevent1"></sequenceFlow>
|
||||
<sequenceFlow id="flow4" sourceRef="oncreateUT" targetRef="endevent1"></sequenceFlow>
|
||||
<sequenceFlow id="flow5" sourceRef="otherUT" targetRef="endevent1"></sequenceFlow>
|
||||
</process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_myProcess">
|
||||
<bpmndi:BPMNPlane bpmnElement="myProcess" id="BPMNPlane_myProcess">
|
||||
<bpmndi:BPMNShape bpmnElement="alfrescoStartEv" id="BPMNShape_alfrescoStartEv">
|
||||
<omgdc:Bounds height="35.0" width="35.0" x="170.0" y="190.0"></omgdc:Bounds>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="delegateToAssignee" id="BPMNShape_delegateToAssignee">
|
||||
<omgdc:Bounds height="55.0" width="105.0" x="250.0" y="180.0"></omgdc:Bounds>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="DelegateeGateway" id="BPMNShape_DelegateeGateway">
|
||||
<omgdc:Bounds height="40.0" width="40.0" x="400.0" y="188.0"></omgdc:Bounds>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="oncreateUT" id="BPMNShape_oncreateUT">
|
||||
<omgdc:Bounds height="55.0" width="105.0" x="485.0" y="181.0"></omgdc:Bounds>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="expressionUT" id="BPMNShape_expressionUT">
|
||||
<omgdc:Bounds height="55.0" width="105.0" x="485.0" y="90.0"></omgdc:Bounds>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="otherUT" id="BPMNShape_otherUT">
|
||||
<omgdc:Bounds height="55.0" width="105.0" x="485.0" y="270.0"></omgdc:Bounds>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
|
||||
<omgdc:Bounds height="35.0" width="35.0" x="660.0" y="197.0"></omgdc:Bounds>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
|
||||
<omgdi:waypoint x="205.0" y="207.0"></omgdi:waypoint>
|
||||
<omgdi:waypoint x="250.0" y="207.0"></omgdi:waypoint>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
|
||||
<omgdi:waypoint x="355.0" y="207.0"></omgdi:waypoint>
|
||||
<omgdi:waypoint x="400.0" y="208.0"></omgdi:waypoint>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="OnCreateFlow" id="BPMNEdge_OnCreateFlow">
|
||||
<omgdi:waypoint x="440.0" y="208.0"></omgdi:waypoint>
|
||||
<omgdi:waypoint x="485.0" y="208.0"></omgdi:waypoint>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="ExpressionFlow" id="BPMNEdge_ExpressionFlow">
|
||||
<omgdi:waypoint x="420.0" y="188.0"></omgdi:waypoint>
|
||||
<omgdi:waypoint x="419.0" y="117.0"></omgdi:waypoint>
|
||||
<omgdi:waypoint x="485.0" y="117.0"></omgdi:waypoint>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="otherFlow" id="BPMNEdge_otherFlow">
|
||||
<omgdi:waypoint x="420.0" y="228.0"></omgdi:waypoint>
|
||||
<omgdi:waypoint x="420.0" y="297.0"></omgdi:waypoint>
|
||||
<omgdi:waypoint x="485.0" y="297.0"></omgdi:waypoint>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
|
||||
<omgdi:waypoint x="537.0" y="145.0"></omgdi:waypoint>
|
||||
<omgdi:waypoint x="677.0" y="197.0"></omgdi:waypoint>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
|
||||
<omgdi:waypoint x="590.0" y="208.0"></omgdi:waypoint>
|
||||
<omgdi:waypoint x="660.0" y="214.0"></omgdi:waypoint>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
|
||||
<omgdi:waypoint x="537.0" y="270.0"></omgdi:waypoint>
|
||||
<omgdi:waypoint x="677.0" y="232.0"></omgdi:waypoint>
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</definitions>
|
Reference in New Issue
Block a user