diff --git a/config/alfresco/public-rest-context.xml b/config/alfresco/public-rest-context.xml index 4ffbb8cd97..45461da251 100644 --- a/config/alfresco/public-rest-context.xml +++ b/config/alfresco/public-rest-context.xml @@ -778,6 +778,7 @@ + diff --git a/source/java/org/alfresco/rest/workflow/api/impl/RestVariableHelper.java b/source/java/org/alfresco/rest/workflow/api/impl/RestVariableHelper.java index eccaa52e05..a10aa6ccad 100644 --- a/source/java/org/alfresco/rest/workflow/api/impl/RestVariableHelper.java +++ b/source/java/org/alfresco/rest/workflow/api/impl/RestVariableHelper.java @@ -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 INTERNAL_PROPERTIES = new HashSet(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) @@ -165,7 +173,7 @@ public class RestVariableHelper protected void setVariableValueAndType(Variable variable, Object value, TypeDefinitionContext context) { PropertyDefinition propDef = context.getPropertyDefinition(variable.getName()); - if(propDef != null) + if (propDef != null) { variable.setValue(getSafePropertyValue(value)); variable.setType(propDef.getDataType().getName().toPrefixString(namespaceService)); @@ -174,7 +182,18 @@ public class RestVariableHelper { // Not defined as a property, check if it's an association AssociationDefinition assocDef = context.getAssociationDefinition(variable.getName()); - if(assocDef != null) + 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 variable.setType(assocDef.getTargetClass().getName().toPrefixString(namespaceService)); @@ -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)); } diff --git a/source/test-java/org/alfresco/rest/workflow/api/tests/TaskWorkflowApiTest.java b/source/test-java/org/alfresco/rest/workflow/api/tests/TaskWorkflowApiTest.java index b7b88acc04..8a0c7f0878 100644 --- a/source/test-java/org/alfresco/rest/workflow/api/tests/TaskWorkflowApiTest.java +++ b/source/test-java/org/alfresco/rest/workflow/api/tests/TaskWorkflowApiTest.java @@ -485,7 +485,110 @@ public class TaskWorkflowApiTest extends EnterpriseWorkflowTestApi cleanupProcessInstance(processInfo.getId()); } } - + + /* + * 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() + { + @Override + public ActivitiScriptNode doWork() throws Exception + { + return getPersonNodeRef(user); + } + }, user, networkId); + + // Start custom process instance + ProcessInstance processInstance = TenantUtil.runAsUserTenant(new TenantRunAsWork() + { + @Override + public ProcessInstance doWork() throws Exception + { + deployProcessDefinition("workflow/testCustomDelegatee.bpmn20.xml"); + String processDefinitionKey = "@" + networkId + "@myProcess"; + Map variables = new HashMap(); + 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 diff --git a/source/test-resources/models/bpmDelegateeModel.xml b/source/test-resources/models/bpmDelegateeModel.xml new file mode 100755 index 0000000000..8c59791319 --- /dev/null +++ b/source/test-resources/models/bpmDelegateeModel.xml @@ -0,0 +1,96 @@ + + + + BPM Assignee Test Model + Workdesk + 1.0 + + + + + + + + + + + + + Expression + OnCreate + Other + + + + + + + Delegation Task (Assignee) + bpm:workflowTask + + + Next Step + d:text + false + false + false + Expression + + + + + + + + Responsible person + + false + false + + + cm:person + true + false + + + + + + Expression Task (Assignee) + bpm:workflowTask + + wbpm:CommentAspect + + + + On Create (Assignee) + bpm:workflowTask + + wbpm:CommentAspect + + + + Other Task (Assignee) + bpm:workflowTask + + wbpm:CommentAspect + + + + + + Step Comment + + + Comment + d:text + false + false + true + + + + + diff --git a/source/test-resources/rest-api-test-context.xml b/source/test-resources/rest-api-test-context.xml index 9180cf9f00..ec5e4c56fa 100644 --- a/source/test-resources/rest-api-test-context.xml +++ b/source/test-resources/rest-api-test-context.xml @@ -18,6 +18,7 @@ models/custom-model.xml + models/bpmDelegateeModel.xml diff --git a/source/test-resources/workflow/testCustomDelegatee.bpmn20.xml b/source/test-resources/workflow/testCustomDelegatee.bpmn20.xml new file mode 100755 index 0000000000..63e023eb65 --- /dev/null +++ b/source/test-resources/workflow/testCustomDelegatee.bpmn20.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file