/* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.activiti.workflow.simple; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.impl.util.CollectionUtil; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.activiti.engine.test.ActivitiRule; import org.activiti.workflow.simple.converter.WorkflowDefinitionConversion; import org.activiti.workflow.simple.converter.WorkflowDefinitionConversionFactory; import org.activiti.workflow.simple.converter.step.FeedbackStepDefinitionConverter; import org.activiti.workflow.simple.definition.WorkflowDefinition; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Joram Barrez */ public class WorkflowConversionTest { private static Logger log = LoggerFactory.getLogger(WorkflowConversionTest.class); @Rule public ActivitiRule activitiRule = new ActivitiRule(); protected RuntimeService runtimeService; protected TaskService taskService; protected WorkflowDefinitionConversionFactory conversionFactory; @Before public void initialiseTest() { // Alternatively, the following setup could be done using a dependency injection container conversionFactory = new WorkflowDefinitionConversionFactory(); runtimeService = activitiRule.getRuntimeService(); taskService = activitiRule.getTaskService(); } @After public void cleanup() { for (Deployment deployment : activitiRule.getRepositoryService().createDeploymentQuery().list()) { activitiRule.getRepositoryService().deleteDeployment(deployment.getId(), true); } } @Test public void testSimplestProcess() { WorkflowDefinition workflowDefinition = new WorkflowDefinition() .name("testWorkflow") .description("This is a test workflow"); // Validate ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey(convertAndDeploy(workflowDefinition)); assertTrue(processInstance.isEnded()); } @Test public void testUserTasksWithOnlyAssignees() { String[] assignees = new String[] {"kermit", "gonzo", "mispiggy"}; WorkflowDefinition workflowDefinition = new WorkflowDefinition() .name("testWorkflow") .description("This is a test workflow") .addHumanStep("first task", assignees[0]) .addHumanStep("second step", assignees[1]) .addHumanStep("third step", assignees[2]); // Validate activitiRule.getRuntimeService().startProcessInstanceByKey(convertAndDeploy(workflowDefinition)); for (String assignee : assignees) { Task task = activitiRule.getTaskService().createTaskQuery().singleResult(); assertEquals(assignee, task.getAssignee()); activitiRule.getTaskService().complete(task.getId()); } assertEquals(0, activitiRule.getRuntimeService().createProcessInstanceQuery().count()); } @Test public void testThreeUserTasksInParallel() throws Exception { TaskService taskService = activitiRule.getTaskService(); WorkflowDefinition workflowDefinition = new WorkflowDefinition() .name("testWorkflow") .description("This is a test workflow") .inParallel() .inList() .addHumanStep("first task", "kermit") .endList() .inList() .addHumanStep("second step", "gonzo") .endList() .inList() .addHumanStep("third task", "mispiggy") .endList() .endParallel() .addHumanStep("Task in between", "kermit") .inParallel() .inList() .addHumanStep("fourth task", "gonzo") .endList() .inList() .addHumanStep("fifth step", "gonzo") .endList() .endParallel(); // Validate activitiRule.getRuntimeService().startProcessInstanceByKey(convertAndDeploy(workflowDefinition)); assertEquals(1, taskService.createTaskQuery().taskAssignee("kermit").count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("gonzo").count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("mispiggy").count()); // Complete tasks for (Task task : taskService.createTaskQuery().list()) { activitiRule.getTaskService().complete(task.getId()); } // In between task should be active Task task = taskService.createTaskQuery().singleResult(); assertEquals("Task in between", task.getName()); taskService.complete(task.getId()); // There should be two task open now for gonzo assertEquals(2, taskService.createTaskQuery().taskAssignee("gonzo").count()); } @Test public void testUserTasksInChoice() throws Exception { TaskService taskService = activitiRule.getTaskService(); WorkflowDefinition workflowDefinition = new WorkflowDefinition() .name("testWorkflow") .description("This is a test workflow") .inChoice() .inList() .addCondition("test", "==", "'hello'") .addHumanStep("first task", "kermit") .addHumanStep("second task", "kermit") .endList() .inList() .addHumanStep("gonzo task", "gonzo") .endList() .endChoice() .addHumanStep("last task", "kermit"); // Validate Map<String, Object> varMap = new HashMap<String, Object>(); varMap.put("test", "hello"); String definitionKey = convertAndDeploy(workflowDefinition); ProcessInstance instance = activitiRule.getRuntimeService().startProcessInstanceByKey(definitionKey, varMap); assertEquals(1, taskService.createTaskQuery().taskAssignee("kermit").count()); assertEquals(0, taskService.createTaskQuery().taskAssignee("gonzo").count()); Task task = taskService.createTaskQuery().singleResult(); assertEquals("first task", task.getName()); taskService.complete(task.getId()); task = taskService.createTaskQuery().singleResult(); assertEquals("second task", task.getName()); taskService.complete(task.getId()); task = taskService.createTaskQuery().singleResult(); assertEquals("last task", task.getName()); taskService.complete(task.getId()); assertEquals(0, activitiRule.getRuntimeService().createProcessInstanceQuery().processInstanceId(instance.getId()).count()); varMap = new HashMap<String, Object>(); varMap.put("test", "world"); instance = activitiRule.getRuntimeService().startProcessInstanceByKey(definitionKey, varMap); assertEquals(0, taskService.createTaskQuery().taskAssignee("kermit").count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("gonzo").count()); task = taskService.createTaskQuery().singleResult(); assertEquals("gonzo task", task.getName()); taskService.complete(task.getId()); task = taskService.createTaskQuery().singleResult(); assertEquals("last task", task.getName()); taskService.complete(task.getId()); assertEquals(0, activitiRule.getRuntimeService().createProcessInstanceQuery().processInstanceId(instance.getId()).count()); } @Test public void testMultipleConditionsInChoice() throws Exception { TaskService taskService = activitiRule.getTaskService(); WorkflowDefinition workflowDefinition = new WorkflowDefinition() .name("testWorkflow") .description("This is a test workflow") .inChoice() .inList() .addCondition("test", "==", "'hello'") .addCondition("test2", "==", "'world'") .addHumanStep("first task", "kermit") .endList() .inList() .addHumanStep("gonzo task", "gonzo") .endList() .endChoice(); // Validate Map<String, Object> varMap = new HashMap<String, Object>(); varMap.put("test", "hello"); varMap.put("test2", "world"); String definitionKey = convertAndDeploy(workflowDefinition); ProcessInstance instance = activitiRule.getRuntimeService().startProcessInstanceByKey(definitionKey, varMap); assertEquals(1, taskService.createTaskQuery().taskAssignee("kermit").count()); assertEquals(0, taskService.createTaskQuery().taskAssignee("gonzo").count()); Task task = taskService.createTaskQuery().singleResult(); assertEquals("first task", task.getName()); taskService.complete(task.getId()); assertEquals(0, activitiRule.getRuntimeService().createProcessInstanceQuery().processInstanceId(instance.getId()).count()); varMap = new HashMap<String, Object>(); varMap.put("test", "world"); varMap.put("test2", "world"); instance = activitiRule.getRuntimeService().startProcessInstanceByKey(definitionKey, varMap); assertEquals(0, taskService.createTaskQuery().taskAssignee("kermit").count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("gonzo").count()); task = taskService.createTaskQuery().singleResult(); assertEquals("gonzo task", task.getName()); taskService.complete(task.getId()); assertEquals(0, activitiRule.getRuntimeService().createProcessInstanceQuery().processInstanceId(instance.getId()).count()); } @Test public void testInitiatorOnHumanStep() { WorkflowDefinition workflowDefinition = new WorkflowDefinition() .name("testWorkflow") .description("This is a test workflow") .addHumanStep("step1", "kermit") .addHumanStepForWorkflowInitiator("step2"); activitiRule.getIdentityService().setAuthenticatedUserId("MrPink"); activitiRule.getRuntimeService().startProcessInstanceByKey(convertAndDeploy(workflowDefinition)); activitiRule.getIdentityService().setAuthenticatedUserId("null"); // Complete first task TaskService taskService = activitiRule.getTaskService(); assertEquals(1, taskService.createTaskQuery().taskAssignee("kermit").count()); taskService.complete(taskService.createTaskQuery().singleResult().getId()); // Second task should be done by initiator of workflow assertEquals(1, taskService.createTaskQuery().taskAssignee("MrPink").count()); assertEquals(0, taskService.createTaskQuery().taskAssignee("kermit").count()); } @Test public void testGroupsForHumanStep() { WorkflowDefinition workflowDefinition = new WorkflowDefinition() .name("testWorkflow") .description("This is a test workflow") .addHumanStepForGroup("step1", "management", "sales") .addHumanStepForGroup("step1", "sales"); activitiRule.getRuntimeService().startProcessInstanceByKey(convertAndDeploy(workflowDefinition)); // Complete first task TaskService taskService = activitiRule.getTaskService(); assertEquals(1, taskService.createTaskQuery().taskCandidateGroup("management").count()); assertEquals(1, taskService.createTaskQuery().taskCandidateGroup("sales").count()); assertEquals(1, taskService.createTaskQuery().taskCandidateGroupIn(Arrays.asList("management")).count()); assertEquals(1, taskService.createTaskQuery().taskCandidateGroupIn(Arrays.asList("management", "sales")).count()); taskService.complete(taskService.createTaskQuery().singleResult().getId()); // Second task is only done by sales assertEquals(0, taskService.createTaskQuery().taskCandidateGroup("management").count()); assertEquals(1, taskService.createTaskQuery().taskCandidateGroup("sales").count()); assertEquals(0, taskService.createTaskQuery().taskCandidateGroupIn(Arrays.asList("management")).count()); assertEquals(1, taskService.createTaskQuery().taskCandidateGroupIn(Arrays.asList("sales")).count()); assertEquals(1, taskService.createTaskQuery().taskCandidateGroupIn(Arrays.asList("management", "sales")).count()); } @Test public void testFeedbackStepWithFixedUsersAllFeedbackProvided() { WorkflowDefinition workflowDefinition = new WorkflowDefinition() .name("testWorkflow") .description("This is a test workflow") .addFeedbackStep("Test feedback", "kermit", Arrays.asList("gonzo", "mispiggy", "fozzie")); activitiRule.getRuntimeService().startProcessInstanceByKey(convertAndDeploy(workflowDefinition)); // First, a task should be assigned to kermit to select the people assertEquals(1, taskService.createTaskQuery().count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("kermit").count()); Task task = taskService.createTaskQuery().singleResult(); taskService.complete(task.getId()); // Four tasks should be available now assertEquals(4, taskService.createTaskQuery().count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("kermit").count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("gonzo").count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("mispiggy").count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("fozzie").count()); // Completing the feedback tasks first should only leave the 'gather feedback' task for kermit open for (Task feedbackTask : taskService.createTaskQuery().list()) { if (!feedbackTask.getAssignee().equals("kermit")) { activitiRule.getTaskService().complete(feedbackTask.getId()); } } assertEquals(1, taskService.createTaskQuery().count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("kermit").count()); // Completing this last task should finish the process activitiRule.getTaskService().complete(activitiRule.getTaskService().createTaskQuery().singleResult().getId()); assertEquals(0, activitiRule.getRuntimeService().createProcessInstanceQuery().count()); } @Test public void testFeedbackStepWithFixedUsersFeedbackHaltedByInitiator() { WorkflowDefinition workflowDefinition = new WorkflowDefinition() .name("testWorkflow") .description("This is a test workflow") .addFeedbackStep("Test feedback", "kermit", Arrays.asList("gonzo", "mispiggy", "fozzie")); activitiRule.getRuntimeService().startProcessInstanceByKey(convertAndDeploy(workflowDefinition)); // First, a task should be assigned to kermit to select the people assertEquals(1, taskService.createTaskQuery().count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("kermit").count()); Task task = taskService.createTaskQuery().singleResult(); taskService.complete(task.getId()); // Four tasks should be available now assertEquals(4, taskService.createTaskQuery().count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("kermit").count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("gonzo").count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("mispiggy").count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("fozzie").count()); // Completing only one feedback task for (Task feedbackTask : taskService.createTaskQuery().list()) { if (!feedbackTask.getAssignee().equals("kermit")) { activitiRule.getTaskService().complete(feedbackTask.getId()); break; } } assertEquals(3, taskService.createTaskQuery().count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("kermit").count()); // Completing the 'gather feedback' task by kermit should cancel the remaining feedback tasks activitiRule.getTaskService().complete(activitiRule.getTaskService().createTaskQuery().taskAssignee("kermit").singleResult().getId()); assertEquals(0, taskService.createTaskQuery().count()); assertEquals(0, activitiRule.getRuntimeService().createProcessInstanceQuery().count()); } @Test public void testFeedbackStepWithUserSelectionAtRuntimeAllFeedbackProvided() { WorkflowDefinition workflowDefinition = new WorkflowDefinition() .name("testWorkflow") .description("This is a test workflow") .addFeedbackStep("Test feedback", "kermit"); activitiRule.getRuntimeService().startProcessInstanceByKey(convertAndDeploy(workflowDefinition)); // First, a task should be assigned to kermit to select the people assertEquals(1, taskService.createTaskQuery().count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("kermit").count()); Task task = taskService.createTaskQuery().singleResult(); // Completing the task using the predefined process variable (normally done through the form) TaskService taskService = activitiRule.getTaskService(); taskService.complete(task.getId(), CollectionUtil.singletonMap(FeedbackStepDefinitionConverter.VARIABLE_FEEDBACK_PROVIDERS, Arrays.asList("gonzo", "fozzie"))); // Three tasks should be available now assertEquals(3, taskService.createTaskQuery().count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("kermit").count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("gonzo").count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("fozzie").count()); // Completing the feedback tasks first should only leave the 'gather feedback' task for kermit open for (Task feedbackTask : taskService.createTaskQuery().list()) { if (!feedbackTask.getAssignee().equals("kermit")) { activitiRule.getTaskService().complete(feedbackTask.getId()); } } assertEquals(1, taskService.createTaskQuery().count()); assertEquals(1, taskService.createTaskQuery().taskAssignee("kermit").count()); // Completing this last task should finish the process activitiRule.getTaskService().complete(activitiRule.getTaskService().createTaskQuery().singleResult().getId()); assertEquals(0, activitiRule.getRuntimeService().createProcessInstanceQuery().count()); } // Helper methods ----------------------------------------------------------------------------- protected String convertAndDeploy(WorkflowDefinition workflowDefinition) { // Convert WorkflowDefinitionConversion conversion = conversionFactory.createWorkflowDefinitionConversion(workflowDefinition); conversion.convert(); log.info("Converted process : " + conversion.getBpmn20Xml()); // InputStream is = conversion.getWorkflowDiagramImage(); // try { // write(is, new FileOutputStream("temp" + UUID.randomUUID().toString() + ".png"), new byte[1024]); // } catch (FileNotFoundException e) { // e.printStackTrace(); // } catch (IOException e) { // e.printStackTrace(); // } // Deploy long processDefinitionCount = activitiRule.getRepositoryService().createProcessDefinitionQuery().count(); deployProcessDefinition(conversion); assertEquals(processDefinitionCount + 1, activitiRule.getRepositoryService().createProcessDefinitionQuery().count()); return getDeployedProcessKey(); } public static void write(InputStream is, OutputStream os, byte[] buf) throws IOException { int numRead; while ((numRead = is.read(buf)) >= 0) { os.write(buf, 0, numRead); } } protected String getDeployedProcessKey() { ProcessDefinition processDefinition = activitiRule.getRepositoryService().createProcessDefinitionQuery().singleResult(); assertNotNull(processDefinition); return processDefinition.getKey(); } protected void deployProcessDefinition(WorkflowDefinitionConversion conversion) { long nrOfDeployments = countNrOfDeployments(); activitiRule.getRepositoryService().createDeployment() .addString(conversion.getProcess().getId() + ".bpmn20.xml", conversion.getBpmn20Xml()) .deploy(); assertEquals(nrOfDeployments + 1, countNrOfDeployments()); } protected long countNrOfDeployments() { return activitiRule.getRepositoryService().createDeploymentQuery().count(); } }