/* 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.bpmn.event.message;
import java.util.List;
import org.activiti.engine.impl.test.PluggableActivitiTestCase;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.Deployment;
/**
* @author Daniel Meyer (camunda)
* @author Kristin Polenz (camunda)
* @author Christian Lipphardt (camunda)
*/
public class MessageBoundaryEventTest extends PluggableActivitiTestCase {
@Deployment
public void testSingleBoundaryMessageEvent() {
runtimeService.startProcessInstanceByKey("process");
assertEquals(2, runtimeService.createExecutionQuery().count());
Task userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
Execution execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName")
.singleResult();
assertNotNull(execution);
// 1. case: message received cancels the task
runtimeService.messageEventReceived("messageName", execution.getId());
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterMessage", userTask.getTaskDefinitionKey());
taskService.complete(userTask.getId());
assertEquals(0, runtimeService.createProcessInstanceQuery().count());
// 2nd. case: complete the user task cancels the message subscription
runtimeService.startProcessInstanceByKey("process");
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
taskService.complete(userTask.getId());
execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName")
.singleResult();
assertNull(execution);
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterTask", userTask.getTaskDefinitionKey());
taskService.complete(userTask.getId());
assertEquals(0, runtimeService.createProcessInstanceQuery().count());
}
public void testDoubleBoundaryMessageEventSameMessageId() {
// deployment fails when two boundary message events have the same messageId
try {
repositoryService
.createDeployment()
.addClasspathResource("org/activiti/engine/test/bpmn/event/message/MessageBoundaryEventTest.testDoubleBoundaryMessageEventSameMessageId.bpmn20.xml")
.deploy();
fail("Deployment should fail because Activiti cannot handle two boundary message events with same messageId.");
} catch (Exception e) {
assertTextPresent("Cannot have more than one message event subscription with name 'messageName' for scope 'task'", e.getMessage());
assertEquals(0, repositoryService.createDeploymentQuery().count());
}
}
@Deployment
public void testDoubleBoundaryMessageEvent() {
runtimeService.startProcessInstanceByKey("process");
assertEquals(2, runtimeService.createExecutionQuery().count());
Task userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
// the executions for both messageEventSubscriptionNames are the same
Execution execution1 = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName_1")
.singleResult();
assertNotNull(execution1);
Execution execution2 = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName_2")
.singleResult();
assertNotNull(execution2);
assertEquals(execution1.getId(), execution2.getId());
///////////////////////////////////////////////////////////////////////////////////
// 1. first message received cancels the task and the execution and both subscriptions
runtimeService.messageEventReceived("messageName_1", execution1.getId());
// this should then throw an exception because execution2 no longer exists
try {
runtimeService.messageEventReceived("messageName_2", execution2.getId());
fail();
} catch (Exception e) {
// This is good
}
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterMessage_1", userTask.getTaskDefinitionKey());
taskService.complete(userTask.getId());
assertEquals(0, runtimeService.createProcessInstanceQuery().count());
/////////////////////////////////////////////////////////////////////
// 2. complete the user task cancels the message subscriptions
runtimeService.startProcessInstanceByKey("process");
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
taskService.complete(userTask.getId());
execution1 = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName_1")
.singleResult();
assertNull(execution1);
execution2 = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName_2")
.singleResult();
assertNull(execution2);
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterTask", userTask.getTaskDefinitionKey());
taskService.complete(userTask.getId());
assertEquals(0, runtimeService.createProcessInstanceQuery().count());
}
@Deployment
public void testDoubleBoundaryMessageEventMultiInstance() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("process");
// assume we have 7 executions
// one process instance
// one execution for scope created for boundary message event
// five execution because we have loop cardinality 5
assertEquals(7, runtimeService.createExecutionQuery().count());
assertEquals(5, taskService.createTaskQuery().count());
Execution execution1 = runtimeService.createExecutionQuery().messageEventSubscriptionName("messageName_1").singleResult();
Execution execution2 = runtimeService.createExecutionQuery().messageEventSubscriptionName("messageName_2").singleResult();
// both executions are the same
assertEquals(execution1.getId(), execution2.getId());
///////////////////////////////////////////////////////////////////////////////////
// 1. first message received cancels all tasks and the executions and both subscriptions
runtimeService.messageEventReceived("messageName_1", execution1.getId());
// this should then throw an exception because execution2 no longer exists
try {
runtimeService.messageEventReceived("messageName_2", execution2.getId());
fail();
} catch (Exception e) {
// This is good
}
// only process instance left
assertEquals(1, runtimeService.createExecutionQuery().count());
Task userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterMessage_1", userTask.getTaskDefinitionKey());
taskService.complete(userTask.getId());
assertProcessEnded(processInstance.getId());
///////////////////////////////////////////////////////////////////////////////////
// 2. complete the user task cancels the message subscriptions
processInstance = runtimeService.startProcessInstanceByKey("process");
// assume we have 7 executions
// one process instance
// one execution for scope created for boundary message event
// five execution because we have loop cardinality 5
assertEquals(7, runtimeService.createExecutionQuery().count());
assertEquals(5, taskService.createTaskQuery().count());
execution1 = runtimeService.createExecutionQuery().messageEventSubscriptionName("messageName_1").singleResult();
execution2 = runtimeService.createExecutionQuery().messageEventSubscriptionName("messageName_2").singleResult();
// both executions are the same
assertEquals(execution1.getId(), execution2.getId());
List<Task> userTasks = taskService.createTaskQuery().list();
assertNotNull(userTasks);
assertEquals(5, userTasks.size());
// as long as tasks exists, the message subscriptions exist
for (int i = 0; i < userTasks.size()-1; i++) {
Task task = userTasks.get(i);
taskService.complete(task.getId());
execution1 = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName_1")
.singleResult();
assertNotNull(execution1);
execution2 = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName_2")
.singleResult();
assertNotNull(execution2);
}
// only one task left
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
taskService.complete(userTask.getId());
// after last task is completed, no message subscriptions left
execution1 = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName_1")
.singleResult();
assertNull(execution1);
execution2 = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName_2")
.singleResult();
assertNull(execution2);
// complete last task to end process
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterTask", userTask.getTaskDefinitionKey());
taskService.complete(userTask.getId());
assertProcessEnded(processInstance.getId());
}
@Deployment
public void testBoundaryMessageEventInsideSubprocess() {
// this time the boundary events are placed on a user task that is contained inside a sub process
runtimeService.startProcessInstanceByKey("process");
assertEquals(3, runtimeService.createExecutionQuery().count());
Task userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
Execution execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName")
.singleResult();
assertNotNull(execution);
///////////////////////////////////////////////////
// 1. case: message received cancels the task
runtimeService.messageEventReceived("messageName", execution.getId());
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterMessage", userTask.getTaskDefinitionKey());
taskService.complete(userTask.getId());
assertEquals(0, runtimeService.createProcessInstanceQuery().count());
///////////////////////////////////////////////////
// 2nd. case: complete the user task cancels the message subscription
runtimeService.startProcessInstanceByKey("process");
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
taskService.complete(userTask.getId());
execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName")
.singleResult();
assertNull(execution);
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterTask", userTask.getTaskDefinitionKey());
taskService.complete(userTask.getId());
assertEquals(0, runtimeService.createProcessInstanceQuery().count());
}
@Deployment
public void testBoundaryMessageEventOnSubprocessAndInsideSubprocess() {
// this time the boundary events are placed on a user task that is contained inside a sub process
// and on the subprocess itself
runtimeService.startProcessInstanceByKey("process");
assertEquals(3, runtimeService.createExecutionQuery().count());
Task userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
Execution execution1 = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName")
.singleResult();
assertNotNull(execution1);
Execution execution2 = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName2")
.singleResult();
assertNotNull(execution2);
assertNotSame(execution1.getId(), execution2.getId());
/////////////////////////////////////////////////////////////
// first case: we complete the inner usertask.
taskService.complete(userTask.getId());
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterTask", userTask.getTaskDefinitionKey());
// the inner subscription is cancelled
Execution execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName")
.singleResult();
assertNull(execution);
// the outer subscription still exists
execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName2")
.singleResult();
assertNotNull(execution);
// now complete the second usertask
taskService.complete(userTask.getId());
// now the outer event subscription is cancelled as well
execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName2")
.singleResult();
assertNull(execution);
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterSubprocess", userTask.getTaskDefinitionKey());
// now complete the outer usertask
taskService.complete(userTask.getId());
/////////////////////////////////////////////////////////////
// second case: we signal the inner message event
runtimeService.startProcessInstanceByKey("process");
execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName")
.singleResult();
runtimeService.messageEventReceived("messageName", execution.getId());
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterMessage", userTask.getTaskDefinitionKey());
// the inner subscription is removes
execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName")
.singleResult();
assertNull(execution);
// the outer subscription still exists
execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName2")
.singleResult();
assertNotNull(execution);
// now complete the second usertask
taskService.complete(userTask.getId());
// now the outer event subscription is cancelled as well
execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName2")
.singleResult();
assertNull(execution);
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterSubprocess", userTask.getTaskDefinitionKey());
// now complete the outer usertask
taskService.complete(userTask.getId());
/////////////////////////////////////////////////////////////
// third case: we signal the outer message event
runtimeService.startProcessInstanceByKey("process");
execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName2")
.singleResult();
runtimeService.messageEventReceived("messageName2", execution.getId());
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterOuterMessageBoundary", userTask.getTaskDefinitionKey());
// the inner subscription is removed
execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName")
.singleResult();
assertNull(execution);
// the outer subscription is removed
execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName2")
.singleResult();
assertNull(execution);
// now complete the second usertask
taskService.complete(userTask.getId());
// and we are done
}
@Deployment
public void testBoundaryMessageEventOnSubprocess() {
runtimeService.startProcessInstanceByKey("process");
assertEquals(2, runtimeService.createExecutionQuery().count());
Task userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
// 1. case: message one received cancels the task
Execution executionMessageOne = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName_one")
.singleResult();
assertNotNull(executionMessageOne);
runtimeService.messageEventReceived("messageName_one", executionMessageOne.getId());
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterMessage_one", userTask.getTaskDefinitionKey());
taskService.complete(userTask.getId());
assertEquals(0, runtimeService.createProcessInstanceQuery().count());
// 2nd. case: message two received cancels the task
runtimeService.startProcessInstanceByKey("process");
Execution executionMessageTwo = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName_two")
.singleResult();
assertNotNull(executionMessageTwo);
runtimeService.messageEventReceived("messageName_two", executionMessageTwo.getId());
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterMessage_two", userTask.getTaskDefinitionKey());
taskService.complete(userTask.getId());
assertEquals(0, runtimeService.createProcessInstanceQuery().count());
// 3rd. case: complete the user task cancels the message subscription
runtimeService.startProcessInstanceByKey("process");
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
taskService.complete(userTask.getId());
executionMessageOne = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName_one")
.singleResult();
assertNull(executionMessageOne);
executionMessageTwo = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName_two")
.singleResult();
assertNull(executionMessageTwo);
userTask = taskService.createTaskQuery().singleResult();
assertNotNull(userTask);
assertEquals("taskAfterSubProcess", userTask.getTaskDefinitionKey());
taskService.complete(userTask.getId());
assertEquals(0, runtimeService.createProcessInstanceQuery().count());
}
@Deployment
public void testBoundaryMessageEventOnSubprocessAndInsideSubprocessMultiInstance() {
// this time the boundary events are placed on a user task that is contained inside a sub process
// and on the subprocess itself
runtimeService.startProcessInstanceByKey("process");
assertEquals(17, runtimeService.createExecutionQuery().count());
// 5 user tasks
List<Task> userTasks = taskService.createTaskQuery().list();
assertNotNull(userTasks);
assertEquals(5, userTasks.size());
// there are 5 event subscriptions to the event on the inner user task
List<Execution> executions = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName")
.list();
assertNotNull(executions);
assertEquals(5, executions.size());
// there is a single event subscription for the event on the subprocess
executions = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName2")
.list();
assertNotNull(executions);
assertEquals(1, executions.size());
// if we complete the outer message event, all inner executions are removed
Execution outerScopeExecution = executions.get(0);
runtimeService.messageEventReceived("messageName2", outerScopeExecution.getId());
executions = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("messageName")
.list();
assertEquals(0, executions.size());
Task userTask = taskService.createTaskQuery()
.singleResult();
assertNotNull(userTask);
assertEquals("taskAfterOuterMessageBoundary", userTask.getTaskDefinitionKey());
taskService.complete(userTask.getId());
// and we are done
}
}