diff --git a/source/java/org/alfresco/repo/workflow/AbstractWorkflowServiceIntegrationTest.java b/source/java/org/alfresco/repo/workflow/AbstractWorkflowServiceIntegrationTest.java index e2812c8e88..31e572b477 100644 --- a/source/java/org/alfresco/repo/workflow/AbstractWorkflowServiceIntegrationTest.java +++ b/source/java/org/alfresco/repo/workflow/AbstractWorkflowServiceIntegrationTest.java @@ -73,6 +73,7 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT protected final static String USER3 = "WFUser3" + GUID.generate(); protected final static String GROUP = "WFGroup" + GUID.generate(); protected final static String SUB_GROUP = "WFSubGroup" + GUID.generate(); + protected final static QName customStringProp = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "customStringProp"); protected WorkflowService workflowService; protected AuthenticationComponent authenticationComponent; @@ -576,26 +577,7 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT WorkflowDefinition workflowDef = deployDefinition(getAdhocDefinitionPath()); assertNotNull(workflowDef); - // Create params - Map params = new HashMap(); - Serializable wfPackage = workflowService.createPackage(null); - params.put(WorkflowModel.ASSOC_PACKAGE, wfPackage); - Date dueDate = new Date(); - params.put(WorkflowModel.PROP_WORKFLOW_DUE_DATE, dueDate); - params.put(WorkflowModel.PROP_WORKFLOW_PRIORITY, 1); - params.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, "Test workflow description"); - QName customStringProp = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "customStringProp"); - params.put(customStringProp, "stringValue"); - - // Assign to USER2 - NodeRef assignee = personManager.get(USER2); - params.put(WorkflowModel.ASSOC_ASSIGNEE, assignee); - - // Start a workflow instance - WorkflowPath path = workflowService.startWorkflow(workflowDef.getId(), params); - assertNotNull(path); - assertTrue(path.isActive()); - String workflowInstanceId = path.getInstance().getId(); + String workflowInstanceId = startAdhocWorkflow(workflowDef, USER2); // End start task to progress workflow WorkflowTask startTask = workflowService.getStartTask(workflowInstanceId); @@ -605,30 +587,54 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT WorkflowTask theTask = getNextTaskForWorkflow(workflowInstanceId); // Set some custom properties on the task - params = new HashMap(); + HashMap params = new HashMap(); params.put(customStringProp, "stringValue"); workflowService.updateTask(theTask.getId(), params, null, null); // Test all query features for running tasks - testTaskQueryInProgress(workflowInstanceId, theTask); + checkTaskQueryInProgress(workflowInstanceId, theTask); // Test all query features for the start-task - testTaskQueryStartTaskCompleted(workflowInstanceId, startTask); + checkTaskQueryStartTaskCompleted(workflowInstanceId, startTask); // Finish the task adhoc-task workflowService.endTask(theTask.getId(), null); // Test all query features for completed tasks - testTaskQueryTaskCompleted(workflowInstanceId, theTask, startTask); + checkTaskQueryTaskCompleted(workflowInstanceId, theTask, startTask); // Finally end the workflow and check the querying isActive == false WorkflowTask lastTask = getNextTaskForWorkflow(workflowInstanceId); workflowService.endTask(lastTask.getId(), null); - testQueryTasksInactiveWorkflow(workflowInstanceId); + checkQueryTasksInactiveWorkflow(workflowInstanceId); } - protected void testQueryTasksInactiveWorkflow(String workflowInstanceId) { + public void testQueryTaskLimit() throws Exception + { + WorkflowDefinition workflowDef = deployDefinition(getAdhocDefinitionPath()); + + // execute 5 instances of the adhoc workflow + for (int x = 0; x < 5; x++) + { + executeAdhocWorkflow(workflowDef); + } + + // ensure there more than 5 tasks returned. + WorkflowTaskQuery query = new WorkflowTaskQuery(); + query.setActive(false); + query.setActorId(USER3); + query.setTaskState(WorkflowTaskState.COMPLETED); + List tasks = workflowService.queryTasks(query); + assertTrue(tasks.size()>5); + + // limit the results and ensure we get the correct number of results back + query.setLimit(5); + tasks = workflowService.queryTasks(query); + assertEquals(5, tasks.size()); + } + + protected void checkQueryTasksInactiveWorkflow(String workflowInstanceId) { WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED); taskQuery.setActive(false); @@ -641,7 +647,7 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT checkNoTasksFoundUsingQuery(taskQuery); } - protected void testTaskQueryTaskCompleted(String workflowInstanceId, + protected void checkTaskQueryTaskCompleted(String workflowInstanceId, WorkflowTask theTask, WorkflowTask startTask) { List expectedTasks = Arrays.asList(theTask.getId(), startTask.getId()); @@ -661,7 +667,7 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT checkTaskPropsQuery(expectedTasks, WorkflowTaskState.COMPLETED, null); } - protected void testTaskQueryInProgress(String workflowInstanceId, WorkflowTask expectedTask) + protected void checkTaskQueryInProgress(String workflowInstanceId, WorkflowTask expectedTask) { List expectedTasks = Arrays.asList(expectedTask.getId()); @@ -676,7 +682,7 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT checkProcessPropsQuery(expectedTasks, WorkflowTaskState.IN_PROGRESS); } - protected void testTaskQueryStartTaskCompleted(String workflowInstanceId, WorkflowTask startTask) { + protected void checkTaskQueryStartTaskCompleted(String workflowInstanceId, WorkflowTask startTask) { List expectedTasks = Arrays.asList(startTask.getId()); checkProcessIdQuery(workflowInstanceId, expectedTasks, WorkflowTaskState.COMPLETED); @@ -928,7 +934,6 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT String optionalProcessId) { WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state); - QName customStringProp = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "customStringProp"); Map taskProps = new HashMap(); taskProps.put(customStringProp, "stringValue"); @@ -1070,6 +1075,52 @@ public abstract class AbstractWorkflowServiceIntegrationTest extends BaseSpringT assertEquals(expDef.getVersion(), actualDef.getVersion()); } + private void executeAdhocWorkflow(WorkflowDefinition workflowDef) + { + personManager.setUser(USER3); + String workflowId = startAdhocWorkflow(workflowDef, USER3); + + // End start task to progress workflow + WorkflowTask startTask = workflowService.getStartTask(workflowId); + String startTaskId = startTask.getId(); + workflowService.endTask(startTaskId, null); + + // finish the adhoc task + WorkflowTask adhocTask = getNextTaskForWorkflow(workflowId); + workflowService.endTask(adhocTask.getId(), null); + + // finish the workflow + WorkflowTask lastTask = getNextTaskForWorkflow(workflowId); + workflowService.endTask(lastTask.getId(), null); + + // ensure the workflow has completed + assertFalse(workflowService.getWorkflowById(workflowId).isActive()); + } + + private String startAdhocWorkflow(WorkflowDefinition workflowDef, String assigneeId) + { + // Create params + Map params = new HashMap(); + Serializable wfPackage = workflowService.createPackage(null); + params.put(WorkflowModel.ASSOC_PACKAGE, wfPackage); + Date dueDate = new Date(); + params.put(WorkflowModel.PROP_WORKFLOW_DUE_DATE, dueDate); + params.put(WorkflowModel.PROP_WORKFLOW_PRIORITY, 1); + params.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, "Test workflow description"); + + params.put(customStringProp, "stringValue"); + + // Assign to USER2 + NodeRef assignee = personManager.get(assigneeId); + params.put(WorkflowModel.ASSOC_ASSIGNEE, assignee); + + // Start a workflow instance + WorkflowPath path = workflowService.startWorkflow(workflowDef.getId(), params); + assertNotNull(path); + assertTrue(path.isActive()); + return path.getInstance().getId(); + } + @SuppressWarnings("deprecation") @Override protected void onSetUpInTransaction() throws Exception diff --git a/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java b/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java index dbdec815c5..6d529798f0 100644 --- a/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java +++ b/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowEngine.java @@ -111,7 +111,6 @@ import org.xml.sax.InputSource; * @since 3.4.e * @author Nick Smith * @author Frederik Heremans - * */ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine { @@ -1002,7 +1001,7 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine throw new WorkflowException(msg, ae); } } - + /** * {@inheritDoc} */ @@ -1419,60 +1418,72 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine private List queryRuntimeTasks(WorkflowTaskQuery query) { - // Runtime-tasks only exist on process-instances that are active - // so no use in querying runtime tasks if not active - if(!Boolean.FALSE.equals(query.isActive())) - { - // Add task name - TaskQuery taskQuery = taskService.createTaskQuery(); - if(query.getTaskName() != null) { - // Task 'key' is stored as variable on task - String formKey = query.getTaskName().toPrefixString(namespaceService); - taskQuery.taskVariableValueEquals(ActivitiConstants.PROP_TASK_FORM_KEY, formKey); - } - - if(query.getProcessId() != null) { - String processInstanceId = createLocalId(query.getProcessId()); - taskQuery.processInstanceId(processInstanceId); - } + // Runtime-tasks only exist on process-instances that are active + // so no use in querying runtime tasks if not active + if (!Boolean.FALSE.equals(query.isActive())) + { + // Add task name + TaskQuery taskQuery = taskService.createTaskQuery(); + if (query.getTaskName() != null) + { + // Task 'key' is stored as variable on task + String formKey = query.getTaskName().toPrefixString(namespaceService); + taskQuery.taskVariableValueEquals(ActivitiConstants.PROP_TASK_FORM_KEY, formKey); + } - if(query.getProcessName() != null) - { - String processName = getProcessNameMTSafe(query.getProcessName()); - taskQuery.processDefinitionKey(processName); - } - - - if(query.getActorId() != null) { - taskQuery.taskAssignee(query.getActorId()); - } - - if(query.getTaskId() != null) { - String taskId = createLocalId(query.getTaskId()); - taskQuery.taskId(taskId); - } - - // Custom task properties - if(query.getTaskCustomProps() != null) - { - addTaskPropertiesToQuery(query.getTaskCustomProps(), taskQuery); - } + if (query.getProcessId() != null) + { + String processInstanceId = createLocalId(query.getProcessId()); + taskQuery.processInstanceId(processInstanceId); + } - if(query.getProcessCustomProps() != null) - { - addProcessPropertiesToQuery(query.getProcessCustomProps(), taskQuery); - } - // Add ordering - if (query.getOrderBy() != null) - { - WorkflowTaskQuery.OrderBy[] orderBy = query.getOrderBy(); - orderQuery(taskQuery, orderBy); - } - - List currentTasks = typeConverter.convert(taskQuery.list()); - return currentTasks; - } - return new ArrayList(); + if (query.getProcessName() != null) + { + String processName = getProcessNameMTSafe(query.getProcessName()); + taskQuery.processDefinitionKey(processName); + } + + if (query.getActorId() != null) + { + taskQuery.taskAssignee(query.getActorId()); + } + + if (query.getTaskId() != null) + { + String taskId = createLocalId(query.getTaskId()); + taskQuery.taskId(taskId); + } + + // Custom task properties + if (query.getTaskCustomProps() != null) + { + addTaskPropertiesToQuery(query.getTaskCustomProps(), taskQuery); + } + + if (query.getProcessCustomProps() != null) + { + addProcessPropertiesToQuery(query.getProcessCustomProps(), taskQuery); + } + // Add ordering + if (query.getOrderBy() != null) + { + WorkflowTaskQuery.OrderBy[] orderBy = query.getOrderBy(); + orderQuery(taskQuery, orderBy); + } + + List results; + int limit = query.getLimit(); + if (limit > 0) + { + results = taskQuery.listPage(0, limit); + } + else + { + results = taskQuery.list(); + } + return typeConverter.convert(results); + } + return new ArrayList(); } private void addProcessPropertiesToQuery( @@ -1611,78 +1622,87 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine private List queryHistoricTasks(WorkflowTaskQuery query) { - HistoricTaskInstanceQuery historicQuery = historyService - .createHistoricTaskInstanceQuery() - .finished(); - - if(query.getTaskId() != null) { - String taskId = createLocalId(query.getTaskId()); - historicQuery.taskId(taskId); - } - - if(query.getProcessId() != null) - { - String processInstanceId = createLocalId(query.getProcessId()); - historicQuery.processInstanceId(processInstanceId); - } - - if(query.getTaskName() != null) - { - historicQuery.taskDefinitionKey(query.getTaskName().toPrefixString()); - } - - if(query.getActorId() != null) - { - historicQuery.taskAssignee(query.getActorId()); - } - - if(query.getProcessName() != null) - { - String processName = getProcessNameMTSafe(query.getProcessName()); - historicQuery.processDefinitionKey(processName); - } - - if(query.getTaskCustomProps() != null) - { - addTaskPropertiesToQuery(query.getTaskCustomProps(), historicQuery); - } - - if(query.getProcessCustomProps() != null) - { - addProcessPropertiesToQuery(query.getProcessCustomProps(), historicQuery); - } - - if(query.isActive() != null) - { - if(query.isActive()) { - historicQuery.processUnfinished(); - } - else - { - historicQuery.processFinished(); - } - } - - // Order query - if(query.getOrderBy() != null) - { - orderQuery(historicQuery, query.getOrderBy()); - } - - List workflowTasks = new ArrayList(); - List historicTasks = historicQuery.list(); - - for(HistoricTaskInstance historicTask : historicTasks) - { - WorkflowTask wfTask = typeConverter.convert(historicTask); - if(wfTask != null) - { - // Converter returns null if the task belongs to deleted/cancelled WF - workflowTasks.add(wfTask); - } - } - return workflowTasks; - + HistoricTaskInstanceQuery historicQuery = historyService.createHistoricTaskInstanceQuery().finished(); + + if (query.getTaskId() != null) + { + String taskId = createLocalId(query.getTaskId()); + historicQuery.taskId(taskId); + } + + if (query.getProcessId() != null) + { + String processInstanceId = createLocalId(query.getProcessId()); + historicQuery.processInstanceId(processInstanceId); + } + + if (query.getTaskName() != null) + { + historicQuery.taskDefinitionKey(query.getTaskName().toPrefixString()); + } + + if (query.getActorId() != null) + { + historicQuery.taskAssignee(query.getActorId()); + } + + if (query.getProcessName() != null) + { + String processName = getProcessNameMTSafe(query.getProcessName()); + historicQuery.processDefinitionKey(processName); + } + + if (query.getTaskCustomProps() != null) + { + addTaskPropertiesToQuery(query.getTaskCustomProps(), historicQuery); + } + + if (query.getProcessCustomProps() != null) + { + addProcessPropertiesToQuery(query.getProcessCustomProps(), historicQuery); + } + + if (query.isActive() != null) + { + if (query.isActive()) + { + historicQuery.processUnfinished(); + } + else + { + historicQuery.processFinished(); + } + } + + // Order query + if (query.getOrderBy() != null) + { + orderQuery(historicQuery, query.getOrderBy()); + } + + List results; + int limit = query.getLimit(); + if (limit > 0) + { + results = historicQuery.listPage(0, limit); + } + else + { + results = historicQuery.list(); + } + + List workflowTasks = new ArrayList(); + for (HistoricTaskInstance historicTask : results) + { + WorkflowTask wfTask = typeConverter.convert(historicTask); + if (wfTask != null) + { + // Converter returns null if the task belongs to + // deleted/cancelled WF + workflowTasks.add(wfTask); + } + } + return workflowTasks; } private void addTaskPropertiesToQuery(Map taskCustomProps, diff --git a/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowServiceIntegrationTest.java b/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowServiceIntegrationTest.java index e06dd2fb9c..0b374b030b 100644 --- a/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowServiceIntegrationTest.java +++ b/source/java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowServiceIntegrationTest.java @@ -82,7 +82,8 @@ public class ActivitiWorkflowServiceIntegrationTest extends AbstractWorkflowServ assertEquals("Approve", outcome); } - protected void testTaskQueryStartTaskCompleted(String workflowInstanceId, WorkflowTask startTask) + @Override + protected void checkTaskQueryStartTaskCompleted(String workflowInstanceId, WorkflowTask startTask) { // In activiti, start-tasks only show up when the workflowInstanceId or taskId is passed List expectedTasks = Arrays.asList(startTask.getId()); @@ -98,7 +99,8 @@ public class ActivitiWorkflowServiceIntegrationTest extends AbstractWorkflowServ checkTaskPropsQuery(expectedTasks, WorkflowTaskState.COMPLETED, workflowInstanceId); } - protected void testTaskQueryTaskCompleted(String workflowInstanceId, + @Override + protected void checkTaskQueryTaskCompleted(String workflowInstanceId, WorkflowTask theTask, WorkflowTask startTask) { List bothTasks = Arrays.asList(theTask.getId(), startTask.getId()); @@ -124,7 +126,8 @@ public class ActivitiWorkflowServiceIntegrationTest extends AbstractWorkflowServ checkProcessPropsQuery(withoutStartTask, WorkflowTaskState.COMPLETED); } - protected void testQueryTasksInactiveWorkflow(String workflowInstanceId) { + @Override + protected void checkQueryTasksInactiveWorkflow(String workflowInstanceId) { WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED); taskQuery.setActive(false); diff --git a/source/java/org/alfresco/service/cmr/workflow/WorkflowTaskQuery.java b/source/java/org/alfresco/service/cmr/workflow/WorkflowTaskQuery.java index 663f89328b..8c1c65504d 100644 --- a/source/java/org/alfresco/service/cmr/workflow/WorkflowTaskQuery.java +++ b/source/java/org/alfresco/service/cmr/workflow/WorkflowTaskQuery.java @@ -176,6 +176,7 @@ public class WorkflowTaskQuery } /** + * Filters ont he {@link WorkflowInstance} Id. * @param processId */ public void setProcessId(String processId) @@ -192,6 +193,7 @@ public class WorkflowTaskQuery } /** + * Filters on the {@link WorkflowDefinition} name. * @param processName */ public void setProcessName(QName processName)