提交 0e354873 编写于 作者: F fheremans

Added events for signals, messages, compensation and identity-links

上级 e016958b
......@@ -87,10 +87,25 @@ public enum ActivitiEventType {
*/
ENGINE_CLOSED,
ACTIVITY_COMPLETE,
/**
* An activity has received a signal. Dispatched after the activity has responded to the signal.
*/
ACTIVITY_SIGNALLED;
ACTIVITY_SIGNALLED,
/**
* An activity is about to be executed as a compensation for another activity. The event targets the
* activity that is about to be executed for compensation.
*/
ACTIVITY_COMPENSATE,
/**
* An activity has received a message event. Dispatched before the actual message has been received by
* the activity. This event will be either followed by a {@link #ACTIVITY_SIGNALLED} event or {@link #ACTIVITY_COMPLETE}
* for the involved activity, if the message was delivered successfully.
*/
ACTIVITY_MESSAGE_RECEIVED;
public static final ActivitiEventType[] EMPTY_ARRAY = new ActivitiEventType[] {};
......
/* 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.delegate.event;
/**
* An {@link ActivitiEvent} related to an message being sent to an activity.
*
* @author Frederik Heremans
*/
public interface ActivitiMessageEvent extends ActivitiActivityEvent {
/**
* @return the name of the message.
*/
public String getMessageName();
/**
* @return the payload that was passed when sending the message. Returns null, if no payload was passed.
*/
public Object getMessageData();
}
......@@ -14,7 +14,7 @@ package org.activiti.engine.delegate.event;
/**
* An {@link ActivitiEvent} related to an activity within an execution;
* An {@link ActivitiEvent} related to a signal being sent to an activity.
*
* @author Frederik Heremans
*/
......
......@@ -12,15 +12,17 @@
*/
package org.activiti.engine.delegate.event.impl;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.event.ActivitiActivityEvent;
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.delegate.event.ActivitiExceptionEvent;
import org.activiti.engine.delegate.event.ActivitiEntityEvent;
import org.activiti.engine.delegate.event.ActivitiMessageEvent;
import org.activiti.engine.delegate.event.ActivitiSignalEvent;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.context.ExecutionContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.IdentityLinkEntity;
import org.activiti.engine.runtime.Job;
/**
......@@ -121,26 +123,55 @@ public class ActivitiEventBuilder {
return newEvent;
}
public static ActivitiMessageEvent createMessageEvent(ActivitiEventType type, String activityId, String messageName, Object payload,
String executionId, String processInstanceId, String processDefinitionId) {
ActivitiMessageEventImpl newEvent = new ActivitiMessageEventImpl(type);
newEvent.setActivityId(activityId);
newEvent.setExecutionId(executionId);
newEvent.setProcessDefinitionId(processDefinitionId);
newEvent.setProcessInstanceId(processInstanceId);
newEvent.setMessageName(messageName);
newEvent.setMessageData(payload);
return newEvent;
}
protected static void populateEventWithCurrentContext(ActivitiEventImpl event) {
boolean extractedFromContext = false;
if(Context.isExecutionContextActive()) {
ExecutionContext executionContext = Context.getExecutionContext();
if(executionContext != null) {
extractedFromContext = true;
event.setExecutionId(executionContext.getExecution().getId());
event.setProcessInstanceId(executionContext.getExecution().getProcessInstanceId());
event.setProcessDefinitionId(executionContext.getExecution().getProcessDefinitionId());
}
} else {
// Fallback to fetching context from the object itself
}
// Fallback to fetching context from the object itself
if(!extractedFromContext){
if(event instanceof ActivitiEntityEvent) {
Object persistendObject = ((ActivitiEntityEvent) event).getEntity();
if(persistendObject instanceof Job) {
event.setExecutionId(((Job) persistendObject).getExecutionId());
event.setProcessInstanceId(((Job) persistendObject).getProcessInstanceId());
event.setProcessDefinitionId(((Job) persistendObject).getProcessDefinitionId());
} else if(persistendObject instanceof ExecutionEntity) {
event.setExecutionId(((ExecutionEntity) persistendObject).getId());
event.setProcessInstanceId(((ExecutionEntity) persistendObject).getProcessInstanceId());
event.setProcessDefinitionId(((ExecutionEntity) persistendObject).getProcessDefinitionId());
} else if(persistendObject instanceof DelegateExecution) {
event.setExecutionId(((DelegateExecution) persistendObject).getId());
event.setProcessInstanceId(((DelegateExecution) persistendObject).getProcessInstanceId());
event.setProcessDefinitionId(((DelegateExecution) persistendObject).getProcessDefinitionId());
} else if(persistendObject instanceof IdentityLinkEntity) {
IdentityLinkEntity idLink = (IdentityLinkEntity) persistendObject;
if(idLink.getProcessDefinitionId() != null) {
event.setProcessDefinitionId(idLink.getProcessDefId());
} else if(idLink.getProcessInstance() != null) {
event.setProcessDefinitionId(idLink.getProcessInstance().getProcessDefinitionId());
event.setProcessInstanceId(idLink.getProcessInstanceId());
event.setExecutionId(idLink.getProcessInstanceId());
} else if(idLink.getTask() != null) {
event.setProcessDefinitionId(idLink.getTask().getProcessDefinitionId());
event.setProcessInstanceId(idLink.getTask().getProcessInstanceId());
event.setExecutionId(idLink.getTask().getExecutionId());
}
}
}
}
......
/* 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.delegate.event.impl;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.ActivitiMessageEvent;
import org.activiti.engine.delegate.event.ActivitiSignalEvent;
/**
* An {@link ActivitiSignalEvent} implementation.
*
* @author Frederik Heremans
*/
public class ActivitiMessageEventImpl extends ActivitiActivityEventImpl implements ActivitiMessageEvent {
protected String messageName;
protected Object messageData;
public ActivitiMessageEventImpl(ActivitiEventType type) {
super(type);
}
public void setMessageName(String messageName) {
this.messageName = messageName;
}
public String getMessageName() {
return messageName;
}
public void setMessageData(Object messageData) {
this.messageData = messageData;
}
public Object getMessageData() {
return messageData;
}
}
......@@ -16,6 +16,8 @@ package org.activiti.engine.impl.event;
import java.util.List;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.impl.ActivitiEventBuilder;
import org.activiti.engine.impl.bpmn.helper.ScopeUtil;
import org.activiti.engine.impl.bpmn.parser.BpmnParse;
import org.activiti.engine.impl.interceptor.CommandContext;
......@@ -60,6 +62,11 @@ public class CompensationEventHandler implements EventHandler {
} else {
try {
if(commandContext.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
commandContext.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createActivityEvent(ActivitiEventType.ACTIVITY_COMPENSATE, compensationHandler.getId(), compensatingExecution.getId(),
compensatingExecution.getProcessInstanceId(), compensatingExecution.getProcessDefinitionId()));
}
compensatingExecution.setActivity(compensationHandler);
// executing the atomic operation makes sure activity start events are fired
......
......@@ -13,6 +13,11 @@
package org.activiti.engine.impl.event;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.impl.ActivitiEventBuilder;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.EventSubscriptionEntity;
/**
......@@ -25,5 +30,17 @@ public class MessageEventHandler extends AbstractEventHandler {
public String getEventHandlerType() {
return EVENT_HANDLER_TYPE;
}
@Override
public void handleEvent(EventSubscriptionEntity eventSubscription, Object payload, CommandContext commandContext) {
// As stated in the ActivitiEventType java-doc, the message-event is thrown before the actual message has been sent
if(commandContext.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
commandContext.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createMessageEvent(ActivitiEventType.ACTIVITY_MESSAGE_RECEIVED, eventSubscription.getActivityId(), eventSubscription.getEventName(),
payload, eventSubscription.getExecutionId(), eventSubscription.getProcessInstanceId(), eventSubscription.getExecution().getProcessDefinitionId()));
}
super.handleEvent(eventSubscription, payload, commandContext);
}
}
......@@ -24,7 +24,6 @@ public class CompensateEventSubscriptionEntity extends EventSubscriptionEntity {
private static final long serialVersionUID = 1L;
@SuppressWarnings("unused") // used by mybatis
private CompensateEventSubscriptionEntity() {
}
......
......@@ -96,11 +96,22 @@ public class IdentityLinkEntityManager extends AbstractManager {
deleteIdentityLink(identityLink, false);
}
// Identity links from cache
// Identity links from cache, if not already deleted
List<IdentityLinkEntity> identityLinksFromCache = Context.getCommandContext().getDbSqlSession().findInCache(IdentityLinkEntity.class);
boolean alreadyDeleted = false;
for (IdentityLinkEntity identityLinkEntity : identityLinksFromCache) {
if (processInstanceId.equals(identityLinkEntity.getProcessInstanceId())) {
deleteIdentityLink(identityLinkEntity, false);
alreadyDeleted = false;
for(IdentityLinkEntity deleted : identityLinks) {
if(deleted.getId() != null && deleted.getId().equals(identityLinkEntity.getId())) {
alreadyDeleted = true;
break;
}
}
if(!alreadyDeleted) {
deleteIdentityLink(identityLinkEntity, false);
}
}
}
}
......
......@@ -14,12 +14,15 @@ package org.activiti.engine.test.api.event;
import java.util.Collections;
import org.activiti.engine.delegate.event.ActivitiActivityEvent;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.ActivitiMessageEvent;
import org.activiti.engine.delegate.event.ActivitiSignalEvent;
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;
/**
......@@ -30,67 +33,200 @@ import org.activiti.engine.test.Deployment;
public class ActivityEventsTest extends PluggableActivitiTestCase {
private TestActivitiActivityEventListener listener;
/**
* Test events related to signalling
*/
@Deployment
public void testActivitySignalEvents() throws Exception {
// Two paths are active in the process, one receive-task and one intermediate catching signal-event
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("signalProcess");
assertNotNull(processInstance);
// Check regular signal through API
Execution executionWithSignal = runtimeService.createExecutionQuery()
.activityId("receivePayment").singleResult();
assertNotNull(executionWithSignal);
runtimeService.signal(executionWithSignal.getId());
assertEquals(1, listener.getEventsReceived().size());
assertTrue(listener.getEventsReceived().get(0) instanceof ActivitiSignalEvent);
ActivitiSignalEvent signalEvent = (ActivitiSignalEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ACTIVITY_SIGNALLED, signalEvent.getType());
assertEquals("receivePayment", signalEvent.getActivityId());
assertEquals(executionWithSignal.getId(), signalEvent.getExecutionId());
assertEquals(executionWithSignal.getProcessInstanceId(), signalEvent.getProcessInstanceId());
assertEquals(processInstance.getProcessDefinitionId(), signalEvent.getProcessDefinitionId());
assertNull(signalEvent.getSignalName());
assertNull(signalEvent.getSignalData());
listener.clearEventsReceived();
// Check signal using event, and pass in additional payload
Execution executionWithSignalEvent = runtimeService.createExecutionQuery()
.activityId("shipOrder").singleResult();
runtimeService.signalEventReceived("alert", executionWithSignalEvent.getId(), Collections.singletonMap("test", (Object)"test"));
assertEquals(1, listener.getEventsReceived().size());
assertTrue(listener.getEventsReceived().get(0) instanceof ActivitiSignalEvent);
signalEvent = (ActivitiSignalEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ACTIVITY_SIGNALLED, signalEvent.getType());
assertEquals("shipOrder", signalEvent.getActivityId());
assertEquals(executionWithSignalEvent.getId(), signalEvent.getExecutionId());
assertEquals(executionWithSignalEvent.getProcessInstanceId(), signalEvent.getProcessInstanceId());
assertEquals(processInstance.getProcessDefinitionId(), signalEvent.getProcessDefinitionId());
assertEquals("alert", signalEvent.getSignalName());
assertNotNull(signalEvent.getSignalData());
listener.clearEventsReceived();
// Two paths are active in the process, one receive-task and one
// intermediate catching signal-event
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("signalProcess");
assertNotNull(processInstance);
// Check regular signal through API
Execution executionWithSignal = runtimeService.createExecutionQuery().activityId("receivePayment").singleResult();
assertNotNull(executionWithSignal);
runtimeService.signal(executionWithSignal.getId());
assertEquals(1, listener.getEventsReceived().size());
assertTrue(listener.getEventsReceived().get(0) instanceof ActivitiSignalEvent);
ActivitiSignalEvent signalEvent = (ActivitiSignalEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ACTIVITY_SIGNALLED, signalEvent.getType());
assertEquals("receivePayment", signalEvent.getActivityId());
assertEquals(executionWithSignal.getId(), signalEvent.getExecutionId());
assertEquals(executionWithSignal.getProcessInstanceId(), signalEvent.getProcessInstanceId());
assertEquals(processInstance.getProcessDefinitionId(), signalEvent.getProcessDefinitionId());
assertNull(signalEvent.getSignalName());
assertNull(signalEvent.getSignalData());
listener.clearEventsReceived();
// Check signal using event, and pass in additional payload
Execution executionWithSignalEvent = runtimeService.createExecutionQuery().activityId("shipOrder").singleResult();
runtimeService.signalEventReceived("alert", executionWithSignalEvent.getId(),
Collections.singletonMap("test", (Object) "test"));
assertEquals(1, listener.getEventsReceived().size());
assertTrue(listener.getEventsReceived().get(0) instanceof ActivitiSignalEvent);
signalEvent = (ActivitiSignalEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ACTIVITY_SIGNALLED, signalEvent.getType());
assertEquals("shipOrder", signalEvent.getActivityId());
assertEquals(executionWithSignalEvent.getId(), signalEvent.getExecutionId());
assertEquals(executionWithSignalEvent.getProcessInstanceId(), signalEvent.getProcessInstanceId());
assertEquals(processInstance.getProcessDefinitionId(), signalEvent.getProcessDefinitionId());
assertEquals("alert", signalEvent.getSignalName());
assertNotNull(signalEvent.getSignalData());
listener.clearEventsReceived();
}
/**
* Test to verify if signals coming from an intermediate throw-event trigger
* the right events to be dispatched.
*/
@Deployment
public void testActivitySignalEventsWithinProcess() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("signalProcess");
assertNotNull(processInstance);
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertNotNull(task);
Execution executionWithSignalEvent = runtimeService.createExecutionQuery().activityId("shipOrder").singleResult();
taskService.complete(task.getId());
assertEquals(1L, listener.getEventsReceived().size());
assertTrue(listener.getEventsReceived().get(0) instanceof ActivitiSignalEvent);
ActivitiSignalEvent signalEvent = (ActivitiSignalEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ACTIVITY_SIGNALLED, signalEvent.getType());
assertEquals("shipOrder", signalEvent.getActivityId());
assertEquals(executionWithSignalEvent.getId(), signalEvent.getExecutionId());
assertEquals(executionWithSignalEvent.getProcessInstanceId(), signalEvent.getProcessInstanceId());
assertEquals(processInstance.getProcessDefinitionId(), signalEvent.getProcessDefinitionId());
assertEquals("alert", signalEvent.getSignalName());
assertNull(signalEvent.getSignalData());
}
/**
* Test events related to message events, called from the API.
*/
@Deployment
public void testActivityMessageEvents() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("messageProcess");
assertNotNull(processInstance);
Execution executionWithMessage = runtimeService.createExecutionQuery().activityId("shipOrder").singleResult();
assertNotNull(executionWithMessage);
runtimeService.messageEventReceived("messageName", executionWithMessage.getId());
assertEquals(2, listener.getEventsReceived().size());
// First, a message-event is expected
assertTrue(listener.getEventsReceived().get(0) instanceof ActivitiMessageEvent);
ActivitiMessageEvent messageEvent = (ActivitiMessageEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ACTIVITY_MESSAGE_RECEIVED, messageEvent.getType());
assertEquals("shipOrder", messageEvent.getActivityId());
assertEquals(executionWithMessage.getId(), messageEvent.getExecutionId());
assertEquals(executionWithMessage.getProcessInstanceId(), messageEvent.getProcessInstanceId());
assertEquals(processInstance.getProcessDefinitionId(), messageEvent.getProcessDefinitionId());
assertEquals("messageName", messageEvent.getMessageName());
assertNull(messageEvent.getMessageData());
// Next, an signal-event is expected, as a result of the message
assertTrue(listener.getEventsReceived().get(1) instanceof ActivitiSignalEvent);
ActivitiSignalEvent signalEvent = (ActivitiSignalEvent) listener.getEventsReceived().get(1);
assertEquals(ActivitiEventType.ACTIVITY_SIGNALLED, signalEvent.getType());
assertEquals("shipOrder", signalEvent.getActivityId());
assertEquals(executionWithMessage.getId(), signalEvent.getExecutionId());
assertEquals(executionWithMessage.getProcessInstanceId(), signalEvent.getProcessInstanceId());
assertEquals(processInstance.getProcessDefinitionId(), signalEvent.getProcessDefinitionId());
assertEquals("messageName", signalEvent.getSignalName());
assertNull(signalEvent.getSignalData());
}
/**
* Test events related to message events, called from the API, targeting an event-subprocess.
*/
@Deployment
public void testActivityMessageEventsInEventSubprocess() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("messageProcess");
assertNotNull(processInstance);
Execution executionWithMessage = runtimeService.createExecutionQuery().activityId("shipOrder").singleResult();
assertNotNull(executionWithMessage);
runtimeService.messageEventReceived("messageName", executionWithMessage.getId());
// Only a message-event should be present, no signal-event, since the
// event-subprocess is
// not signaled, but executed instead
assertEquals(1, listener.getEventsReceived().size());
// A message-event is expected
assertTrue(listener.getEventsReceived().get(0) instanceof ActivitiMessageEvent);
ActivitiMessageEvent messageEvent = (ActivitiMessageEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ACTIVITY_MESSAGE_RECEIVED, messageEvent.getType());
assertEquals("catchMessage", messageEvent.getActivityId());
assertEquals(executionWithMessage.getId(), messageEvent.getExecutionId());
assertEquals(executionWithMessage.getProcessInstanceId(), messageEvent.getProcessInstanceId());
assertEquals(processInstance.getProcessDefinitionId(), messageEvent.getProcessDefinitionId());
assertEquals("messageName", messageEvent.getMessageName());
assertNull(messageEvent.getMessageData());
}
/**
* Test events related to compensation events.
*/
@Deployment
public void testActivityCompensationEvents() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("compensationProcess");
assertNotNull(processInstance);
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId())
.singleResult();
assertNotNull(task);
// Complete task, next a compensation event will be thrown
taskService.complete(task.getId());
assertEquals(2, listener.getEventsReceived().size());
// A compensate-event is expected
assertTrue(listener.getEventsReceived().get(0) instanceof ActivitiActivityEvent);
ActivitiActivityEvent activityEvent = (ActivitiActivityEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ACTIVITY_COMPENSATE, activityEvent.getType());
assertEquals("compensate", activityEvent.getActivityId());
// A new execution is created for the compensation-event, this should be visible in the event
assertFalse(processInstance.getId().equals(activityEvent.getExecutionId()));
assertEquals(processInstance.getProcessInstanceId(), activityEvent.getProcessInstanceId());
assertEquals(processInstance.getProcessDefinitionId(), activityEvent.getProcessDefinitionId());
// Also, a signal-event is received, representing the boundary-event being executed.
assertTrue(listener.getEventsReceived().get(1) instanceof ActivitiSignalEvent);
ActivitiSignalEvent signalEvent = (ActivitiSignalEvent) listener.getEventsReceived().get(1);
assertEquals(ActivitiEventType.ACTIVITY_SIGNALLED, signalEvent.getType());
assertEquals("throwCompensation", signalEvent.getActivityId());
assertEquals(processInstance.getId(), signalEvent.getExecutionId());
assertEquals(processInstance.getProcessInstanceId(), signalEvent.getProcessInstanceId());
assertEquals(processInstance.getProcessDefinitionId(), signalEvent.getProcessDefinitionId());
assertEquals("compensationDone", signalEvent.getSignalName());
assertNull(signalEvent.getSignalData());
}
@Override
protected void initializeServices() {
super.initializeServices();
listener = new TestActivitiActivityEventListener();
processEngineConfiguration.getEventDispatcher().addEventListener(listener);
super.initializeServices();
listener = new TestActivitiActivityEventListener();
processEngineConfiguration.getEventDispatcher().addEventListener(listener);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
if(listener != null) {
listener.clearEventsReceived();
processEngineConfiguration.getEventDispatcher().removeEventListener(listener);
}
super.tearDown();
if (listener != null) {
listener.clearEventsReceived();
processEngineConfiguration.getEventDispatcher().removeEventListener(listener);
}
}
}
/* 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.test.PluggableActivitiTestCase;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.Deployment;
/**
* Test case for all {@link ActivitiEvent}s related to process definitions.
*
* @author Frederik Heremans
*/
public class IdentityLinkEventsTest extends PluggableActivitiTestCase {
private TestActivitiEntityEventListener listener;
/**
* Check identity links on process definitions.
*/
@Deployment(resources = { "org/activiti/engine/test/api/runtime/oneTaskProcess.bpmn20.xml" })
public void testProcessDefinitionIdentityLinkEvents() throws Exception {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("oneTaskProcess").singleResult();
assertNotNull(processDefinition);
// Add candidate user and group
repositoryService.addCandidateStarterUser(processDefinition.getId(), "kermit");
repositoryService.addCandidateStarterGroup(processDefinition.getId(), "sales");
assertEquals(2, listener.getEventsReceived().size());
ActivitiEntityEvent event = (ActivitiEntityEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ENTITY_CREATED, event.getType());
assertTrue(event.getEntity() instanceof IdentityLink);
assertEquals(processDefinition.getId(), event.getProcessDefinitionId());
assertNull(event.getProcessInstanceId());
assertNull(event.getExecutionId());
event = (ActivitiEntityEvent) listener.getEventsReceived().get(1);
assertEquals(ActivitiEventType.ENTITY_CREATED, event.getType());
assertTrue(event.getEntity() instanceof IdentityLink);
assertEquals(processDefinition.getId(), event.getProcessDefinitionId());
assertNull(event.getProcessInstanceId());
assertNull(event.getExecutionId());
listener.clearEventsReceived();
// Delete identity links
repositoryService.deleteCandidateStarterUser(processDefinition.getId(), "kermit");
repositoryService.deleteCandidateStarterGroup(processDefinition.getId(), "sales");
assertEquals(2, listener.getEventsReceived().size());
event = (ActivitiEntityEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ENTITY_DELETED, event.getType());
assertTrue(event.getEntity() instanceof IdentityLink);
assertEquals(processDefinition.getId(), event.getProcessDefinitionId());
assertNull(event.getProcessInstanceId());
assertNull(event.getExecutionId());
event = (ActivitiEntityEvent) listener.getEventsReceived().get(1);
assertEquals(ActivitiEventType.ENTITY_DELETED, event.getType());
assertTrue(event.getEntity() instanceof IdentityLink);
assertEquals(processDefinition.getId(), event.getProcessDefinitionId());
assertNull(event.getProcessInstanceId());
assertNull(event.getExecutionId());
}
/**
* Check identity links on process instances.
*/
@Deployment(resources = { "org/activiti/engine/test/api/runtime/oneTaskProcess.bpmn20.xml" })
public void testProcessInstanceIdentityLinkEvents() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess");
// Add identity link
runtimeService.addUserIdentityLink(processInstance.getId(), "kermit", "test");
assertEquals(1, listener.getEventsReceived().size());
ActivitiEntityEvent event = (ActivitiEntityEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ENTITY_CREATED, event.getType());
assertTrue(event.getEntity() instanceof IdentityLink);
assertEquals(processInstance.getId(), event.getProcessInstanceId());
assertEquals(processInstance.getId(), event.getExecutionId());
assertEquals(processInstance.getProcessDefinitionId(), event.getProcessDefinitionId());
IdentityLink link = (IdentityLink) event.getEntity();
assertEquals("kermit", link.getUserId());
assertEquals("test", link.getType());
listener.clearEventsReceived();
// Deleting process should delete identity link
runtimeService.deleteProcessInstance(processInstance.getId(), "test");
assertEquals(1, listener.getEventsReceived().size());
event = (ActivitiEntityEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ENTITY_DELETED, event.getType());
assertTrue(event.getEntity() instanceof IdentityLink);
link = (IdentityLink) event.getEntity();
assertEquals("kermit", link.getUserId());
assertEquals("test", link.getType());
}
/**
* Check identity links on process instances.
*/
@Deployment(resources = { "org/activiti/engine/test/api/runtime/oneTaskProcess.bpmn20.xml" })
public void testTaskIdentityLinks() throws Exception {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess");
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId())
.singleResult();
assertNotNull(task);
// Add identity link
taskService.addCandidateUser(task.getId(), "kermit");
taskService.addCandidateGroup(task.getId(), "sales");
// Three events are received, since the user link on the task also creates an involvment in the process
assertEquals(3, listener.getEventsReceived().size());
ActivitiEntityEvent event = (ActivitiEntityEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ENTITY_CREATED, event.getType());
assertTrue(event.getEntity() instanceof IdentityLink);
IdentityLink link = (IdentityLink) event.getEntity();
assertEquals("kermit", link.getUserId());
assertEquals("candidate", link.getType());
assertEquals(task.getId(), link.getTaskId());
assertEquals(task.getExecutionId(), event.getExecutionId());
assertEquals(task.getProcessDefinitionId(), event.getProcessDefinitionId());
assertEquals(task.getProcessInstanceId(), event.getProcessInstanceId());
event = (ActivitiEntityEvent) listener.getEventsReceived().get(2);
assertEquals(ActivitiEventType.ENTITY_CREATED, event.getType());
assertTrue(event.getEntity() instanceof IdentityLink);
link = (IdentityLink) event.getEntity();
assertEquals("sales", link.getGroupId());
assertEquals("candidate", link.getType());
assertEquals(task.getId(), link.getTaskId());
assertEquals(task.getExecutionId(), event.getExecutionId());
assertEquals(task.getProcessDefinitionId(), event.getProcessDefinitionId());
assertEquals(task.getProcessInstanceId(), event.getProcessInstanceId());
listener.clearEventsReceived();
// Deleting process should delete identity link
runtimeService.deleteProcessInstance(processInstance.getId(), "test");
assertEquals(3, listener.getEventsReceived().size());
event = (ActivitiEntityEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ENTITY_DELETED, event.getType());
assertTrue(event.getEntity() instanceof IdentityLink);
link = (IdentityLink) event.getEntity();
assertEquals("kermit", link.getUserId());
assertEquals("candidate", link.getType());
assertEquals(task.getExecutionId(), event.getExecutionId());
assertEquals(task.getProcessDefinitionId(), event.getProcessDefinitionId());
assertEquals(task.getProcessInstanceId(), event.getProcessInstanceId());
}
@Override
protected void initializeServices() {
super.initializeServices();
listener = new TestActivitiEntityEventListener(IdentityLink.class);
processEngineConfiguration.getEventDispatcher().addEventListener(listener);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
if (listener != null) {
listener.clearEventsReceived();
processEngineConfiguration.getEventDispatcher().removeEventListener(listener);
}
}
}
......@@ -12,12 +12,11 @@
*/
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.delegate.event.ActivitiEntityEvent;
import org.activiti.engine.impl.test.PluggableActivitiTestCase;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.test.Deployment;
/**
......@@ -28,7 +27,6 @@ import org.activiti.engine.test.Deployment;
public class ProcessDefinitionEventsTest extends PluggableActivitiTestCase {
private TestActivitiEntityEventListener listener;
private TestActivitiEntityEventListener identityLinkListener;
/**
* Test create, update and delete events of process definitions.
......@@ -87,47 +85,12 @@ public class ProcessDefinitionEventsTest extends PluggableActivitiTestCase {
listener.clearEventsReceived();
}
@Deployment(resources= {"org/activiti/engine/test/api/runtime/oneTaskProcess.bpmn20.xml"})
public void testProcessDefinitionIdentityLinkEvents() throws Exception {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("oneTaskProcess")
.singleResult();
assertNotNull(processDefinition);
// Add candidate user and group
repositoryService.addCandidateStarterUser(processDefinition.getId(), "kermit");
repositoryService.addCandidateStarterGroup(processDefinition.getId(), "sales");
assertEquals(2, identityLinkListener.getEventsReceived().size());
ActivitiEntityEvent event = (ActivitiEntityEvent) identityLinkListener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ENTITY_CREATED, event.getType());
assertTrue(event.getEntity() instanceof IdentityLink);
event = (ActivitiEntityEvent) identityLinkListener.getEventsReceived().get(1);
assertEquals(ActivitiEventType.ENTITY_CREATED, event.getType());
assertTrue(event.getEntity() instanceof IdentityLink);
identityLinkListener.clearEventsReceived();
// Delete identity links
repositoryService.deleteCandidateStarterUser(processDefinition.getId(), "kermit");
repositoryService.deleteCandidateStarterGroup(processDefinition.getId(), "sales");
assertEquals(2, identityLinkListener.getEventsReceived().size());
event = (ActivitiEntityEvent) identityLinkListener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ENTITY_DELETED, event.getType());
assertTrue(event.getEntity() instanceof IdentityLink);
event = (ActivitiEntityEvent) identityLinkListener.getEventsReceived().get(1);
assertEquals(ActivitiEventType.ENTITY_DELETED, event.getType());
assertTrue(event.getEntity() instanceof IdentityLink);
}
@Override
protected void initializeServices() {
super.initializeServices();
listener = new TestActivitiEntityEventListener(ProcessDefinition.class);
identityLinkListener = new TestActivitiEntityEventListener(IdentityLink.class);
processEngineConfiguration.getEventDispatcher().addEventListener(listener);
processEngineConfiguration.getEventDispatcher().addEventListener(identityLinkListener);
}
@Override
......@@ -135,10 +98,8 @@ public class ProcessDefinitionEventsTest extends PluggableActivitiTestCase {
super.tearDown();
if(listener != null) {
identityLinkListener.clearEventsReceived();
listener.clearEventsReceived();
processEngineConfiguration.getEventDispatcher().removeEventListener(listener);
processEngineConfiguration.getEventDispatcher().removeEventListener(identityLinkListener);
}
}
}
......@@ -44,6 +44,9 @@ public class ProcessInstanceEventsTest extends PluggableActivitiTestCase {
ActivitiEntityEvent event = (ActivitiEntityEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ENTITY_CREATED, event.getType());
assertEquals(processInstance.getId(), ((ProcessInstance) event.getEntity()).getId());
assertEquals(processInstance.getId(), event.getProcessInstanceId());
assertEquals(processInstance.getId(), event.getExecutionId());
assertEquals(processInstance.getProcessDefinitionId(), event.getProcessDefinitionId());
listener.clearEventsReceived();
// Check update event when suspended/activated
......@@ -54,9 +57,15 @@ public class ProcessInstanceEventsTest extends PluggableActivitiTestCase {
event = (ActivitiEntityEvent) listener.getEventsReceived().get(0);
assertEquals(processInstance.getId(), ((ProcessInstance) event.getEntity()).getId());
assertEquals(ActivitiEventType.ENTITY_SUSPENDED, event.getType());
assertEquals(processInstance.getId(), event.getProcessInstanceId());
assertEquals(processInstance.getId(), event.getExecutionId());
assertEquals(processInstance.getProcessDefinitionId(), event.getProcessDefinitionId());
event = (ActivitiEntityEvent) listener.getEventsReceived().get(1);
assertEquals(ActivitiEventType.ENTITY_ACTIVATED, event.getType());
assertEquals(processInstance.getId(), ((ProcessInstance) event.getEntity()).getId());
assertEquals(processInstance.getId(), event.getProcessInstanceId());
assertEquals(processInstance.getId(), event.getExecutionId());
assertEquals(processInstance.getProcessDefinitionId(), event.getProcessDefinitionId());
listener.clearEventsReceived();
// Check update event when process-definition is supended (should cascade suspend/activate all process instances)
......@@ -67,9 +76,15 @@ public class ProcessInstanceEventsTest extends PluggableActivitiTestCase {
event = (ActivitiEntityEvent) listener.getEventsReceived().get(0);
assertEquals(processInstance.getId(), ((ProcessInstance) event.getEntity()).getId());
assertEquals(ActivitiEventType.ENTITY_SUSPENDED, event.getType());
assertEquals(processInstance.getId(), event.getProcessInstanceId());
assertEquals(processInstance.getId(), event.getExecutionId());
assertEquals(processInstance.getProcessDefinitionId(), event.getProcessDefinitionId());
event = (ActivitiEntityEvent) listener.getEventsReceived().get(1);
assertEquals(ActivitiEventType.ENTITY_ACTIVATED, event.getType());
assertEquals(processInstance.getId(), ((ProcessInstance) event.getEntity()).getId());
assertEquals(processInstance.getId(), event.getProcessInstanceId());
assertEquals(processInstance.getId(), event.getExecutionId());
assertEquals(processInstance.getProcessDefinitionId(), event.getProcessDefinitionId());
listener.clearEventsReceived();
// Check update-event when business-key is updated
......@@ -78,6 +93,9 @@ public class ProcessInstanceEventsTest extends PluggableActivitiTestCase {
event = (ActivitiEntityEvent) listener.getEventsReceived().get(0);
assertEquals(processInstance.getId(), ((ProcessInstance) event.getEntity()).getId());
assertEquals(ActivitiEventType.ENTITY_UPDATED, event.getType());
assertEquals(processInstance.getId(), event.getProcessInstanceId());
assertEquals(processInstance.getId(), event.getExecutionId());
assertEquals(processInstance.getProcessDefinitionId(), event.getProcessDefinitionId());
listener.clearEventsReceived();
runtimeService.deleteProcessInstance(processInstance.getId(), "Testing events");
......@@ -85,6 +103,9 @@ public class ProcessInstanceEventsTest extends PluggableActivitiTestCase {
event = (ActivitiEntityEvent) listener.getEventsReceived().get(0);
assertEquals(ActivitiEventType.ENTITY_DELETED, event.getType());
assertEquals(processInstance.getId(), ((ProcessInstance) event.getEntity()).getId());
assertEquals(processInstance.getId(), event.getProcessInstanceId());
assertEquals(processInstance.getId(), event.getExecutionId());
assertEquals(processInstance.getProcessDefinitionId(), event.getProcessDefinitionId());
listener.clearEventsReceived();
}
......
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn" targetNamespace="Examples">
<signal id="shipOrderSignal" name="alert" />
<process id="compensationProcess">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart"
targetRef="usertask" />
<userTask id="usertask" />
<boundaryEvent id="compensateUserTask" attachedToRef="usertask">
<compensateEventDefinition />
</boundaryEvent>
<manualTask id="compensate" isForCompensation="true" />
<sequenceFlow sourceRef="usertask" targetRef="throwCompensation" />
<intermediateThrowEvent id="throwCompensation">
<compensateEventDefinition />
</intermediateThrowEvent>
<sequenceFlow sourceRef="throwCompensation" targetRef="secondUserTask" />
<userTask id="secondUserTask" />
<sequenceFlow sourceRef="secondUserTask" targetRef="theEnd" />
<endEvent id="theEnd" />
<association associationDirection="One" sourceRef="compensateUserTask"
targetRef="compensate" id="as1" />
</process>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn" targetNamespace="Examples">
<message id="myMessage" name="messageName" />
<process id="messageProcess">
<startEvent id="theStart" />
<sequenceFlow sourceRef="theStart" targetRef="shipOrder" />
<intermediateCatchEvent id="shipOrder" name="On Message">
<messageEventDefinition messageRef="myMessage" />
</intermediateCatchEvent>
<sequenceFlow sourceRef="shipOrder" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn" targetNamespace="Examples">
<message id="myMessage" name="messageName" />
<process id="messageProcess">
<startEvent id="theStart" />
<sequenceFlow sourceRef="theStart" targetRef="shipOrder" />
<userTask id="shipOrder" name="Wait" />
<sequenceFlow sourceRef="shipOrder" targetRef="theEnd" />
<endEvent id="theEnd" />
<subProcess id="eventSubProcess" triggeredByEvent="true">
<startEvent id="catchMessage">
<messageEventDefinition messageRef="myMessage" />
</startEvent>
<sequenceFlow id="flow2" sourceRef="catchMessage"
targetRef="endSubProcess" />
<endEvent id="endSubProcess" />
</subProcess>
</process>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn" targetNamespace="Examples">
<signal id="shipOrderSignal" name="alert" />
<process id="signalProcess">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart"
targetRef="fork" />
<parallelGateway id="fork" />
<sequenceFlow sourceRef="fork" targetRef="usertask" />
<sequenceFlow sourceRef="fork" targetRef="shipOrder" />
<userTask id="usertask" />
<sequenceFlow sourceRef="usertask" targetRef="signal" />
<intermediateThrowEvent id="signal">
<signalEventDefinition signalRef="shipOrderSignal" />
</intermediateThrowEvent>
<sequenceFlow sourceRef="signal" targetRef="join" />
<intermediateCatchEvent id="shipOrder" name="On Alert">
<!-- signal event definition -->
<signalEventDefinition signalRef="shipOrderSignal" />
</intermediateCatchEvent>
<sequenceFlow sourceRef="shipOrder" targetRef="join" />
<parallelGateway id="join" />
<sequenceFlow sourceRef="join" targetRef="archiveOrder" />
<userTask id="archiveOrder" name="Archive Order" />
<sequenceFlow sourceRef="archiveOrder" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册