3.5 自定义动作示例
动作(action)是一种机制,它将你自定义的Java代码绑定到jbpm流程中去。动作能够与持有它的节点相关联(如果它们在流程的图形表示中相应地关联),或者也可以被置于事件中,如选择一个迁移、离开或进入一个节点。对于后一种情形,动作不作为图形表示的一部分,但会在流程执行的过程中于事件触发时执行。
我们先看一个动作实现:MyActionHandler,它在下面的例子中会用到。这个动作处理器实现的确没有做什么惊天动地的事。。。它只是设置的布尔变量isExecuted为true。这个变量是静态的,因此即可以在动作处理器内部访问,在可以直接通过动作类访问来验证它的值。
更多关于动作的信息,参见10.5 动作。
// MyActionHandler represents a class that could execute // some user code during the execution of a jBPM process. public class MyActionHandler implements ActionHandler {
// Before each test (in the setUp), the isExecuted member // will be set to false. public static boolean isExecuted = false;
// The action will set the isExecuted to true so the // unit test will be able to show when the action // is being executed. public void execute(ExecutionContext executionContext) { isExecuted = true; } } |
就像前面提到的,在测试前,我们设置了静态字段MyActionHandler.isExecuted为false:
// Each test will start with setting the static isExecuted // member of MyActionHandler to false. public void setUp() { MyActionHandler.isExecuted = false; } |
我们将在一个迁移上启动这个动作:
public void testTransitionAction() { // The next process is a variant of the hello world process. // We have added an action on the transition from state 's' // to the end-state. The purpose of this test is to show // how easy it is to integrate java code in a jBPM process. ProcessDefinition processDefinition = ProcessDefinition.parseXmlString( "<process-definition>" + " <start-state>" + " <transition to='s' />" + " </start-state>" + " <state name='s'>" + " <transition to='end'>" + " <action class='org.jbpm.tutorial.action.MyActionHandler' />" + " </transition>" + " </state>" + " <end-state name='end' />" + "</process-definition>" );
// Let's start a new execution for the process definition. ProcessInstance processInstance = new ProcessInstance(processDefinition);
// The next signal will cause the execution to leave the start // state and enter the state 's' processInstance.signal();
// Here we show that MyActionHandler was not yet executed. assertFalse(MyActionHandler.isExecuted); // ... and that the main path of execution is positioned in // the state 's' assertSame(processDefinition.getNode("s"), processInstance.getRootToken().getNode());
// The next signal will trigger the execution of the root // token. The token will take the transition with the // action and the action will be executed during the // call to the signal method. processInstance.signal();
// Here we can see that MyActionHandler was executed during // the call to the signal method. assertTrue(MyActionHandler.isExecuted); }
|
下面这个例子,使用了相同的动作,但现在是分别放在了“进入节点”和“离开节点”事件上。注意,与只有一种事件类型的迁移相比,节点的事件类型有多种,因此在节点上事件动作,需要放到一个事件元素中去。
ProcessDefinition processDefinition = ProcessDefinition.parseXmlString( "<process-definition>" + " <start-state>" + " <transition to='s' />" + " </start-state>" + " <state name='s'>" + " <event type='node-enter'>" + " <action class='org.jbpm.tutorial.action.MyActionHandler' />" + " </event>" + " <event type='node-leave'>" + " <action class='org.jbpm.tutorial.action.MyActionHandler' />" + " </event>" + " <transition to='end'/>" + " </state>" + " <end-state name='end' />" + "</process-definition>" );
ProcessInstance processInstance = new ProcessInstance(processDefinition);
assertFalse(MyActionHandler.isExecuted); // The next signal will cause the execution to leave the start // state and enter the state 's'. So the state 's' is entered // and hence the action is executed. processInstance.signal(); assertTrue(MyActionHandler.isExecuted);
// Let's reset the MyActionHandler.isExecuted MyActionHandler.isExecuted = false;
// The next signal will trigger execution to leave the // state 's'. So the action will be executed again. processInstance.signal(); // Voila. assertTrue(MyActionHandler.isExecuted);
|