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