/* 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.engine.test.api.event; import org.activiti.engine.delegate.event.ActivitiEntityEvent; import org.activiti.engine.delegate.event.ActivitiEvent; import org.activiti.engine.delegate.event.ActivitiEventType; import org.activiti.engine.impl.persistence.entity.TaskEntity; import org.activiti.engine.impl.test.PluggableActivitiTestCase; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.activiti.engine.test.Deployment; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * Test case for all {@link ActivitiEvent}s related to tasks. * * @author Frederik Heremans */ public class TaskEventsTest extends PluggableActivitiTestCase { private TestActivitiEntityEventListener listener; /** * Check create, update and delete events for a task. */ @Deployment(resources= {"org/activiti/engine/test/api/runtime/oneTaskProcess.bpmn20.xml"}) public void testTaskEventsInProcess() throws Exception { ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess"); assertNotNull(processInstance); Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()) .singleResult(); assertNotNull(task); // Check create event assertEquals(3, listener.getEventsReceived().size()); ActivitiEntityEvent event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertEquals(ActivitiEventType.ENTITY_CREATED, event.getType()); assertTrue(event.getEntity() instanceof Task); Task taskFromEvent = (Task) event.getEntity(); assertEquals(task.getId(), taskFromEvent.getId()); assertExecutionDetails(event, processInstance); event = (ActivitiEntityEvent) listener.getEventsReceived().get(1); assertEquals(ActivitiEventType.ENTITY_INITIALIZED, event.getType()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(2); assertEquals(ActivitiEventType.TASK_CREATED, event.getType()); assertTrue(event.getEntity() instanceof Task); taskFromEvent = (Task) event.getEntity(); assertEquals(task.getId(), taskFromEvent.getId()); assertExecutionDetails(event, processInstance); listener.clearEventsReceived(); // Update duedate, owner and priority should trigger update-event taskService.setDueDate(task.getId(), new Date()); assertEquals(1, listener.getEventsReceived().size()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertExecutionDetails(event, processInstance); assertEquals(ActivitiEventType.ENTITY_UPDATED, event.getType()); listener.clearEventsReceived(); taskService.setPriority(task.getId(), 12); assertEquals(1, listener.getEventsReceived().size()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertEquals(ActivitiEventType.ENTITY_UPDATED, event.getType()); assertExecutionDetails(event, processInstance); listener.clearEventsReceived(); taskService.setOwner(task.getId(), "kermit"); assertEquals(1, listener.getEventsReceived().size()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertEquals(ActivitiEventType.ENTITY_UPDATED, event.getType()); assertExecutionDetails(event, processInstance); listener.clearEventsReceived(); // Updating detached task and calling saveTask should trigger a single update-event task = taskService.createTaskQuery().processInstanceId(processInstance.getId()) .singleResult(); task.setDueDate(new Date()); task.setOwner("john"); taskService.saveTask(task); assertEquals(1, listener.getEventsReceived().size()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertEquals(ActivitiEventType.ENTITY_UPDATED, event.getType()); assertExecutionDetails(event, processInstance); listener.clearEventsReceived(); // Check delete-event on complete taskService.complete(task.getId()); assertEquals(2, listener.getEventsReceived().size()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertEquals(ActivitiEventType.TASK_COMPLETED, event.getType()); assertExecutionDetails(event, processInstance); TaskEntity taskEntity = (TaskEntity) event.getEntity(); assertNotNull(taskEntity.getDueDate()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(1); assertEquals(ActivitiEventType.ENTITY_DELETED, event.getType()); assertExecutionDetails(event, processInstance); } @Deployment(resources= {"org/activiti/engine/test/api/runtime/oneTaskProcess.bpmn20.xml"}) public void testTaskAssignmentEventInProcess() throws Exception { ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess"); assertNotNull(processInstance); listener.clearEventsReceived(); Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()) .singleResult(); assertNotNull(task); // Set assignee through API taskService.setAssignee(task.getId(), "kermit"); assertEquals(2, listener.getEventsReceived().size()); ActivitiEntityEvent event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertEquals(ActivitiEventType.TASK_ASSIGNED, event.getType()); assertTrue(event.getEntity() instanceof Task); Task taskFromEvent = (Task) event.getEntity(); assertEquals(task.getId(), taskFromEvent.getId()); assertEquals("kermit", taskFromEvent.getAssignee()); assertExecutionDetails(event, processInstance); event = (ActivitiEntityEvent) listener.getEventsReceived().get(1); assertEquals(ActivitiEventType.ENTITY_UPDATED, event.getType()); assertTrue(event.getEntity() instanceof Task); assertExecutionDetails(event, processInstance); listener.clearEventsReceived(); // Set assignee through updateTask task = taskService.createTaskQuery().processInstanceId(processInstance.getId()) .singleResult(); task.setAssignee("newAssignee"); taskService.saveTask(task); assertEquals(2, listener.getEventsReceived().size()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertEquals(ActivitiEventType.TASK_ASSIGNED, event.getType()); assertTrue(event.getEntity() instanceof Task); taskFromEvent = (Task) event.getEntity(); assertEquals(task.getId(), taskFromEvent.getId()); assertEquals("newAssignee", taskFromEvent.getAssignee()); assertExecutionDetails(event, processInstance); event = (ActivitiEntityEvent) listener.getEventsReceived().get(1); assertEquals(ActivitiEventType.ENTITY_UPDATED, event.getType()); assertTrue(event.getEntity() instanceof Task); assertExecutionDetails(event, processInstance); listener.clearEventsReceived(); // Unclaim taskService.unclaim(task.getId()); assertEquals(2, listener.getEventsReceived().size()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertEquals(ActivitiEventType.TASK_ASSIGNED, event.getType()); assertTrue(event.getEntity() instanceof Task); taskFromEvent = (Task) event.getEntity(); assertEquals(task.getId(), taskFromEvent.getId()); assertEquals(null, taskFromEvent.getAssignee()); assertExecutionDetails(event, processInstance); event = (ActivitiEntityEvent) listener.getEventsReceived().get(1); assertEquals(ActivitiEventType.ENTITY_UPDATED, event.getType()); assertTrue(event.getEntity() instanceof Task); assertExecutionDetails(event, processInstance); listener.clearEventsReceived(); } /** * Check events related to process instance delete and standalone task delete. */ @Deployment(resources= {"org/activiti/engine/test/api/runtime/oneTaskProcess.bpmn20.xml"}) public void testDeleteEventDoesNotDispathComplete() throws Exception { ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess"); assertNotNull(processInstance); listener.clearEventsReceived(); Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()) .singleResult(); assertNotNull(task); // Delete process, should delete task as well, but not complete runtimeService.deleteProcessInstance(processInstance.getId(), "testing task delete events"); assertEquals(1, listener.getEventsReceived().size()); ActivitiEntityEvent event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertEquals(ActivitiEventType.ENTITY_DELETED, event.getType()); assertTrue(event.getEntity() instanceof Task); Task taskFromEvent = (Task) event.getEntity(); assertEquals(task.getId(), taskFromEvent.getId()); assertExecutionDetails(event, processInstance); try { task = taskService.newTask(); task.setCategory("123"); task.setDescription("Description"); taskService.saveTask(task); listener.clearEventsReceived(); // Delete standalone task, only a delete-event should be dispatched taskService.deleteTask(task.getId()); assertEquals(1, listener.getEventsReceived().size()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertEquals(ActivitiEventType.ENTITY_DELETED, event.getType()); assertTrue(event.getEntity() instanceof Task); taskFromEvent = (Task) event.getEntity(); assertEquals(task.getId(), taskFromEvent.getId()); assertNull(event.getProcessDefinitionId()); assertNull(event.getProcessInstanceId()); assertNull(event.getExecutionId()); } finally { if(task != null) { String taskId = task.getId(); task = taskService.createTaskQuery().taskId(taskId).singleResult(); if(task != null) { // If task still exists, delete it to have a clean DB after test taskService.deleteTask(taskId); } historyService.deleteHistoricTaskInstance(taskId); } } } /** * This method checks to ensure that the task.fireEvent(TaskListener.EVENTNAME_CREATE), fires before * the dispatchEvent ActivitiEventType.TASK_CREATED. A ScriptTaskListener updates the priority and * assignee before the dispatchEvent() takes place. */ @Deployment(resources= {"org/activiti/engine/test/api/event/TaskEventsTest.testEventFiring.bpmn20.xml"}) public void testEventFiringOrdering() { //We need to add a special listener that copies the Task values - to record its state when the event fires, //otherwise the in-memory task instances is changed after the event fires. TestActivitiEntityEventTaskListener tlistener = new TestActivitiEntityEventTaskListener(Task.class); processEngineConfiguration.getEventDispatcher().addEventListener(tlistener); try { ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("testTaskLocalVars"); // Fetch first task Task task = taskService.createTaskQuery().singleResult(); // Complete first task Map<String, Object> taskParams = new HashMap<String, Object>(); taskService.complete(task.getId(), taskParams, true); ActivitiEntityEvent event = (ActivitiEntityEvent) tlistener.getEventsReceived().get(0); assertEquals(ActivitiEventType.ENTITY_CREATED, event.getType()); assertTrue(event.getEntity() instanceof Task); event = (ActivitiEntityEvent) tlistener.getEventsReceived().get(1); assertEquals(ActivitiEventType.ENTITY_INITIALIZED, event.getType()); assertTrue(event.getEntity() instanceof Task); event = (ActivitiEntityEvent) tlistener.getEventsReceived().get(2); assertEquals(ActivitiEventType.TASK_CREATED, event.getType()); assertTrue(event.getEntity() instanceof Task); Task taskFromEvent = tlistener.getTasks().get(2); assertEquals(task.getId(), taskFromEvent.getId()); // verify script listener has done its job, on create before ActivitiEntityEvent was fired assertEquals("The ScriptTaskListener must set this value before the dispatchEvent fires.","scriptedAssignee", taskFromEvent.getAssignee()); assertEquals("The ScriptTaskListener must set this value before the dispatchEvent fires.",877, taskFromEvent.getPriority()); // Fetch second task taskService.createTaskQuery().singleResult(); } finally { processEngineConfiguration.getEventDispatcher().removeEventListener(tlistener); } } /** * Check all events for tasks not related to a process-instance */ public void testStandaloneTaskEvents() throws Exception { Task task = null; try { task = taskService.newTask(); task.setCategory("123"); task.setDescription("Description"); taskService.saveTask(task); assertEquals(3, listener.getEventsReceived().size()); ActivitiEntityEvent event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertEquals(ActivitiEventType.ENTITY_CREATED, event.getType()); assertTrue(event.getEntity() instanceof Task); Task taskFromEvent = (Task) event.getEntity(); assertEquals(task.getId(), taskFromEvent.getId()); assertNull(event.getProcessDefinitionId()); assertNull(event.getProcessInstanceId()); assertNull(event.getExecutionId()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(1); assertEquals(ActivitiEventType.ENTITY_INITIALIZED, event.getType()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(2); assertEquals(ActivitiEventType.TASK_CREATED, event.getType()); listener.clearEventsReceived(); // Update task taskService.setOwner(task.getId(), "owner"); assertEquals(1, listener.getEventsReceived().size()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertEquals(ActivitiEventType.ENTITY_UPDATED, event.getType()); assertTrue(event.getEntity() instanceof Task); taskFromEvent = (Task) event.getEntity(); assertEquals(task.getId(), taskFromEvent.getId()); assertEquals("owner", taskFromEvent.getOwner()); assertNull(event.getProcessDefinitionId()); assertNull(event.getProcessInstanceId()); assertNull(event.getExecutionId()); listener.clearEventsReceived(); // Assign task taskService.setAssignee(task.getId(), "kermit"); assertEquals(2, listener.getEventsReceived().size()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertEquals(ActivitiEventType.TASK_ASSIGNED, event.getType()); assertTrue(event.getEntity() instanceof Task); taskFromEvent = (Task) event.getEntity(); assertEquals(task.getId(), taskFromEvent.getId()); assertEquals("kermit", taskFromEvent.getAssignee()); assertNull(event.getProcessDefinitionId()); assertNull(event.getProcessInstanceId()); assertNull(event.getExecutionId()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(1); assertEquals(ActivitiEventType.ENTITY_UPDATED, event.getType()); assertTrue(event.getEntity() instanceof Task); taskFromEvent = (Task) event.getEntity(); assertEquals(task.getId(), taskFromEvent.getId()); assertNull(event.getProcessDefinitionId()); assertNull(event.getProcessInstanceId()); assertNull(event.getExecutionId()); listener.clearEventsReceived(); // Complete task taskService.complete(task.getId()); assertEquals(2, listener.getEventsReceived().size()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(0); assertEquals(ActivitiEventType.TASK_COMPLETED, event.getType()); assertTrue(event.getEntity() instanceof Task); taskFromEvent = (Task) event.getEntity(); assertEquals(task.getId(), taskFromEvent.getId()); assertNull(event.getProcessDefinitionId()); assertNull(event.getProcessInstanceId()); assertNull(event.getExecutionId()); event = (ActivitiEntityEvent) listener.getEventsReceived().get(1); assertEquals(ActivitiEventType.ENTITY_DELETED, event.getType()); assertTrue(event.getEntity() instanceof Task); taskFromEvent = (Task) event.getEntity(); assertEquals(task.getId(), taskFromEvent.getId()); assertNull(event.getProcessDefinitionId()); assertNull(event.getProcessInstanceId()); assertNull(event.getExecutionId()); } finally { if(task != null) { String taskId = task.getId(); task = taskService.createTaskQuery().taskId(taskId).singleResult(); if(task != null) { // If task still exists, delete it to have a clean DB after test taskService.deleteTask(taskId); } historyService.deleteHistoricTaskInstance(taskId); } } } protected void assertExecutionDetails(ActivitiEvent event, ProcessInstance processInstance) { assertEquals(processInstance.getId(), event.getProcessInstanceId()); assertEquals(processInstance.getId(), event.getExecutionId()); assertEquals(processInstance.getProcessDefinitionId(), event.getProcessDefinitionId()); } @Override protected void setUp() throws Exception { super.setUp(); listener = new TestActivitiEntityEventListener(Task.class); processEngineConfiguration.getEventDispatcher().addEventListener(listener); } @Override protected void tearDown() throws Exception { super.tearDown(); if(listener != null) { processEngineConfiguration.getEventDispatcher().removeEventListener(listener); } } }