提交 c58d03bc 编写于 作者: M mproch

ACT-641 - intermediate timer event

上级 97178c35
/* 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.impl.bpmn.behavior;
import org.activiti.engine.impl.pvm.delegate.ActivityExecution;
public class IntermediateCatchEventActivitiBehaviour extends AbstractBpmnActivityBehavior {
public void execute(ActivityExecution execution) throws Exception {
// Do nothing: waitstate behavior
}
@Override
public void signal(ActivityExecution execution, String signalName, Object signalData) throws Exception {
leave(execution);
}
}
......@@ -150,6 +150,14 @@ public class ProcessDiagramGenerator {
activityImpl.getWidth(), activityImpl.getHeight());
}
});
// timer catch event
activityDrawInstructions.put("intermediateTimer", new DrawInstruction() {
public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
processDiagramCreator.drawCatchingTimerEvent(activityImpl.getX(), activityImpl.getY(),
activityImpl.getWidth(), activityImpl.getHeight());
}
});
// subprocess
activityDrawInstructions.put("subProcess", new DrawInstruction() {
......
......@@ -24,28 +24,7 @@ import java.util.logging.Logger;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.impl.Condition;
import org.activiti.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.BoundaryEventActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.BusinessRuleTaskActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.CallActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.ErrorEndEventActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.MailActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.ManualTaskActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.NoneEndEventActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.NoneStartEventActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.ParallelGatewayActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.activiti.engine.impl.bpmn.behavior.ReceiveTaskActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.ScriptTaskActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
import org.activiti.engine.impl.bpmn.behavior.ServiceTaskDelegateExpressionActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.ServiceTaskExpressionActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.SubProcessActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.TaskActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.WebServiceActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.*;
import org.activiti.engine.impl.bpmn.data.AbstractDataAssociation;
import org.activiti.engine.impl.bpmn.data.Assignment;
import org.activiti.engine.impl.bpmn.data.ClassStructureDefinition;
......@@ -77,6 +56,7 @@ import org.activiti.engine.impl.form.DefaultStartFormHandler;
import org.activiti.engine.impl.form.DefaultTaskFormHandler;
import org.activiti.engine.impl.form.StartFormHandler;
import org.activiti.engine.impl.form.TaskFormHandler;
import org.activiti.engine.impl.jobexecutor.TimerCatchIntermediateEventJobHandler;
import org.activiti.engine.impl.jobexecutor.TimerDeclarationImpl;
import org.activiti.engine.impl.jobexecutor.TimerExecuteNestedActivityJobHandler;
import org.activiti.engine.impl.pvm.delegate.ActivityBehavior;
......@@ -659,6 +639,8 @@ public class BpmnParse extends Parse {
activity = parseSubProcess(activityElement, scopeElement);
} else if (activityElement.getTagName().equals("callActivity")) {
activity = parseCallActivity(activityElement, scopeElement);
} else if (activityElement.getTagName().equals("intermediateCatchEvent")) {
activity = parseIntermediateCatchEvent(activityElement, scopeElement);
} else if (activityElement.getTagName().equals("adHocSubProcess")
|| activityElement.getTagName().equals("complexGateway")
|| activityElement.getTagName().equals("eventBasedGateway")
......@@ -672,7 +654,24 @@ public class BpmnParse extends Parse {
}
}
}
private ActivityImpl parseIntermediateCatchEvent(Element intermediateEventElement, ScopeImpl scopeElement) {
ActivityImpl nestedActivity = createActivityOnScope(intermediateEventElement, scopeElement);
// Catch event behavior is the same for all types
nestedActivity.setActivityBehavior(new IntermediateCatchEventActivitiBehaviour());
Element timerEventDefinition = intermediateEventElement.element("timerEventDefinition");
if (timerEventDefinition != null) {
parseIntemediateTimerEventDefinition(timerEventDefinition, nestedActivity);
} else {
addError("Unsupported intermediate event type", intermediateEventElement);
}
return nestedActivity;
}
/**
* Parses loopCharacteristics (standardLoop/Multi-instance) of an activity, if any is defined.
*/
......@@ -1577,7 +1576,30 @@ public class BpmnParse extends Parse {
*/
public void parseBoundaryTimerEventDefinition(Element timerEventDefinition, boolean interrupting, ActivityImpl timerActivity) {
timerActivity.setProperty("type", "boundaryTimer");
TimerDeclarationImpl timerDeclaration = parseTimer(timerEventDefinition, timerActivity, TimerExecuteNestedActivityJobHandler.TYPE);
addTimerDeclaration(timerActivity.getParent(), timerDeclaration);
if (timerActivity.getParent() instanceof ActivityImpl) {
((ActivityImpl)timerActivity.getParent()).setScope(true);
}
for (BpmnParseListener parseListener: parseListeners) {
parseListener.parseBoundaryTimerEventDefinition(timerEventDefinition, interrupting, timerActivity);
}
}
private void parseIntemediateTimerEventDefinition(Element timerEventDefinition, ActivityImpl timerActivity) {
timerActivity.setProperty("type", "intermediateTimer");
TimerDeclarationImpl timerDeclaration = parseTimer(timerEventDefinition, timerActivity, TimerCatchIntermediateEventJobHandler.TYPE);
addTimerDeclaration(timerActivity, timerDeclaration);
timerActivity.setScope(true);
for (BpmnParseListener parseListener : parseListeners) {
parseListener.parseIntermediateTimerEventDefinition(timerEventDefinition, timerActivity);
}
}
private TimerDeclarationImpl parseTimer(Element timerEventDefinition, ScopeImpl timerActivity, String jobHandlerType) {
// TimeDate
// TimeCycle
......@@ -1592,18 +1614,11 @@ public class BpmnParse extends Parse {
// Parse the timer declaration
// TODO move the timer declaration into the bpmn activity or next to the TimerSession
TimerDeclarationImpl timerDeclaration = new TimerDeclarationImpl(timeDurationExpression, TimerExecuteNestedActivityJobHandler.TYPE);
TimerDeclarationImpl timerDeclaration = new TimerDeclarationImpl(timeDurationExpression, jobHandlerType);
timerDeclaration.setJobHandlerConfiguration(timerActivity.getId());
addTimerDeclaration(timerActivity.getParent(), timerDeclaration);
if (timerActivity.getParent() instanceof ActivityImpl) {
((ActivityImpl)timerActivity.getParent()).setScope(true);
}
for (BpmnParseListener parseListener: parseListeners) {
parseListener.parseBoundaryTimerEventDefinition(timerEventDefinition, interrupting, timerActivity);
}
return timerDeclaration;
}
public void parseBoundaryErrorEventDefinition(Element errorEventDefinition, boolean interrupting,
ActivityImpl activity, ActivityImpl nestedErrorEventActivity) {
......
......@@ -47,5 +47,5 @@ public interface BpmnParseListener {
void parseSequenceFlow(Element sequenceFlowElement, ScopeImpl scopeElement, TransitionImpl transition);
void parseSendTask(Element sendTaskElement, ScopeImpl scope, ActivityImpl activity);
void parseMultiInstanceLoopCharacteristics(Element activityElement, Element multiInstanceLoopCharacteristicsElement, ActivityImpl activity);
void parseIntermediateTimerEventDefinition(Element timerEventDefinition, ActivityImpl timerActivity);
}
......@@ -79,11 +79,7 @@ import org.activiti.engine.impl.interceptor.CommandContextFactory;
import org.activiti.engine.impl.interceptor.CommandExecutor;
import org.activiti.engine.impl.interceptor.CommandInterceptor;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.engine.impl.jobexecutor.JobExecutor;
import org.activiti.engine.impl.jobexecutor.JobExecutorMessageSessionFactory;
import org.activiti.engine.impl.jobexecutor.JobExecutorTimerSessionFactory;
import org.activiti.engine.impl.jobexecutor.JobHandler;
import org.activiti.engine.impl.jobexecutor.TimerExecuteNestedActivityJobHandler;
import org.activiti.engine.impl.jobexecutor.*;
import org.activiti.engine.impl.repository.Deployer;
import org.activiti.engine.impl.scripting.BeansResolverFactory;
import org.activiti.engine.impl.scripting.ResolverFactory;
......@@ -550,7 +546,11 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
jobHandlers = new HashMap<String, JobHandler>();
TimerExecuteNestedActivityJobHandler timerExecuteNestedActivityJobHandler = new TimerExecuteNestedActivityJobHandler();
jobHandlers.put(timerExecuteNestedActivityJobHandler.getType(), timerExecuteNestedActivityJobHandler);
TimerCatchIntermediateEventJobHandler timerCatchIntermediateEvent = new TimerCatchIntermediateEventJobHandler();
jobHandlers.put(timerCatchIntermediateEvent.getType(), timerCatchIntermediateEvent);
jobExecutor.setCommandExecutor(commandExecutorTxRequired);
jobExecutor.setAutoActivate(jobExecutorActivate);
}
......
......@@ -118,6 +118,9 @@ public class HistoryParseListener implements BpmnParseListener {
public void parseBoundaryErrorEventDefinition(Element errorEventDefinition, boolean interrupting, ActivityImpl activity, ActivityImpl nestedErrorEventActivity) {
}
public void parseIntermediateTimerEventDefinition(Element timerEventDefinition, ActivityImpl timerActivity) {
}
public void parseProperty(Element propertyElement, VariableDeclaration variableDeclaration, ActivityImpl activity) {
}
......
/* 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.impl.jobexecutor;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.pvm.delegate.SignallableActivityBehavior;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.runtime.ExecutionEntity;
import java.util.logging.Level;
import java.util.logging.Logger;
public class TimerCatchIntermediateEventJobHandler implements JobHandler {
private static Logger log = Logger.getLogger(TimerCatchIntermediateEventJobHandler.class.getName());
public static final String TYPE = "timer-intermediate-transition";
public String getType() {
return TYPE;
}
public void execute(String configuration, ExecutionEntity execution, CommandContext commandContext) {
ActivityImpl intermediateEventActivity = execution.getProcessDefinition().findActivity(configuration);
if (intermediateEventActivity == null) {
throw new ActivitiException("Error while firing timer: intermediate event activity " + configuration + " not found");
}
try {
((SignallableActivityBehavior) intermediateEventActivity.getActivityBehavior()).signal(execution, null, null);
} catch (RuntimeException e) {
log.log(Level.SEVERE, "exception during timer execution", e);
throw e;
} catch (Exception e) {
log.log(Level.SEVERE, "exception during timer execution", e);
throw new ActivitiException("exception during timer execution: " + e.getMessage(), e);
}
}
}
/* 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.timer;
import org.activiti.engine.impl.test.PluggableActivitiTestCase;
import org.activiti.engine.impl.util.ClockUtil;
import org.activiti.engine.runtime.JobQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.test.Deployment;
import java.util.Date;
public class IntermediateTimerEventTest extends PluggableActivitiTestCase {
@Deployment
public void testCatchingTimerEvent() throws Exception {
// Set the clock fixed
Date startTime = new Date();
// After process start, there should be timer created
ProcessInstance pi = runtimeService.startProcessInstanceByKey("intermediateTimerEventExample");
JobQuery jobQuery = managementService.createJobQuery().processInstanceId(pi.getId());
assertEquals(1, jobQuery.count());
// After setting the clock to time '50minutes and 5 seconds', the second timer should fire
ClockUtil.setCurrentTime(new Date(startTime.getTime() + ((50 * 60 * 1000) + 5000)));
waitForJobExecutorToProcessAllJobs(5000L, 25L);
assertEquals(0, jobQuery.count());
assertProcessEnded(pi.getProcessInstanceId());
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<definitions id="definitions" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples">
<process id="intermediateTimerEventExample" name="Timer intermediate event example">
<startEvent id="theStart"/>
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="timer"/>
<intermediateCatchEvent id="timer">
<timerEventDefinition>
<timeDuration>PT5M</timeDuration>
</timerEventDefinition>
</intermediateCatchEvent>
<sequenceFlow id="flow2" sourceRef="timer" targetRef="theEnd"/>
<endEvent id="theEnd"/>
</process>
<bpmndi:BPMNDiagram id="diagram">
<bpmndi:BPMNPlane bpmnElement="intermediateTimerEventExample" id="intermediateTimerEventExample_di">
<bpmndi:BPMNShape bpmnElement="theStart" id="theStart_di">
<omgdc:Bounds height="30.0" width="30.0" x="114.0" y="185.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="timer" id="timer_di">
<omgdc:Bounds height="30.0" width="30.0" x="195.0" y="185.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="theEnd" id="theEnd_di">
<omgdc:Bounds height="28.0" width="28.0" x="270.0" y="186.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="flow1_di">
<omgdi:waypoint x="144.0" y="200.0"/>
<omgdi:waypoint x="195.0" y="200.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="flow2_di">
<omgdi:waypoint x="225.0" y="200.0"/>
<omgdi:waypoint x="270.0" y="200.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册