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);
|