Terry.Li-彬

          虛其心,可解天下之問;專其心,可治天下之學;靜其心,可悟天下之理;恒其心,可成天下之業。

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            143 隨筆 :: 344 文章 :: 130 評論 :: 0 Trackbacks
          這是Jboss 的jBPM3.12框架的用戶指南的中文翻譯。我的翻譯風格是中英文對照,只翻譯部分我認為重要的,不翻譯簡單的英文,以免浪費你我的時間。
          同時,對于其中的部分內容,我會在翻譯中做出解釋和寫上我的理解。



          Chapter 3. Tutorial指南

          This tutorial will show you basic process constructs 過程建造in jpdl and the usage of the API for managing the runtime executions.

          這本指南將告訴你使用jpdl語言構建基本的工作流程,以及管理運行時執行的API的用法。

          The format of this tutorial is explaining a set of examples. The examples focus on a particular topic and contain extensive comments. The examples can also be fond in the jBPM download package in the directory src/java.examples.

          這篇指南解釋一系列的例子。例子聚焦于一個特殊的主題和包含很多的注釋。

          The best way to learn is to create a project and experiment by creating variations on the examples given.

          最好的學習方式是在例子的基礎上創建一個略為不同的項目。

          To get started for eclipse users: download jbpm-3.0-[version].zip and unzip it to your sytem. Then do "File" --> "Import..." --> "Existing Project into Workspace". Click "Next" Then, browse for the jBPM root directory and click "Finish". Now you have a jbpm.3 project in your workspace. You can now find the examples of the tutorial in src/java.examples/.... When you open these examples, you can run them with "Run" --> "Run As..." --> "JUnit Test"

          用Junit運行自帶的例子。



          jBPM includes a graphical designer tool for authoring 創作the XML that is shown in the examples. You can find download instructions指令 for the graphical designer in Section 2.1, “Downloadables Overview”. You don't need the graphical designer tool to complete this tutorial.

          State machines can be

          你不需要圖形設計器就能完成這篇指南。圖形設計器僅僅幫助你制作xml流程定義文件。



          3.1. Hello World example

          A process definition is a directed graph, made up of nodes and transitions. The hello world process has 3 nodes. To see how the pieces fit together, we're going to start with a simple process without the use of the designer tool. The following picture shows the graphical representation of the hello world process:



          一個過程定義是一個直接的圖表,由“節點”和“轉向”組成。Hello world這個例子的過程定義有3個節點。

          下面的圖像顯示了hello world過程定義的圖形化表示。

          V:SHAPE id=_x0000_i1025 style="WIDTH: 63.75pt; HEIGHT: 120pt" type="#_x0000_t75">



          Figure 3.1. The hello world process graph

          Hello world業務處理圖表

          publicvoid testHelloWorldProcess() {

          // This method shows a process definition and one execution

          // of the process definition. The process definition has

          // 3 nodes: an unnamed start-state, a state 's' and an

          // end-state named 'end'.

          //這個方法顯示了一個過程定義和這個過程定義的執行。

          // The next line parses a piece of xml text into a

          // ProcessDefinition. A ProcessDefinition is the formal

          // description of a process represented as a java object.

          /*

          * 下一行把一段xml文本解析進ProcessDefinition對象。ProcessDefinition是

          * 過程作為一個Java對象在內存中的正式的描述

          * */

          ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(

          " " +

          " " +

          " " +

          "
          " +

          " " +

          " " +

          "
          " +

          " " +

          "
          "

          );



          // The next line creates one execution of the process definition.

          // After construction, the process execution has one main path

          // of execution (=the root token) that is positioned in the

          // start-state.

          /**

          *下一行使用代表過程定義的Model對象--ProcessDefinition實例,創建一個業務處理定義的執行

          *構造之后,在開始狀態/節點,業務處理執行對象有一個主要的執行路徑

          *

          */

          ProcessInstance processInstance =

          new ProcessInstance(processDefinition);



          // After construction, the process execution has one main path

          // of execution (=the root token).

          /*記號,得到主要的執行路徑。

          * Token記號類,代表一條過程的執行路徑和在過程定義中維護一個指向節點的指針

          *

          * */

          Token token = processInstance.getRootToken();



          // Also after construction, the main path of execution is positioned

          // in the start-state of the process definition.

          assertSame(processDefinition.getStartState(), token.getNode());



          // Let's start the process execution, leaving the start-state

          // over its default transition.

          /*

          * token.signal();用來執行一步狀態,利用“轉向”跳到下一步狀態。

          *

          * */

          token.signal();

          // The signal method will block until the process execution

          // enters a wait state.



          // The process execution will have entered the first wait state

          // in state 's'. So the main path of execution is not

          // positioned in state 's'

          assertSame(processDefinition.getNode("s"), token.getNode());



          // Let's send another signal. This will resume execution by

          // leaving the state 's' over its default transition.

          /*

          * 讓我們發送另一個信號。這將執行離開狀態s的轉向。

          * */

          token.signal();

          // Now the signal method returned because the process instance

          // has arrived in the end-state.



          assertSame(processDefinition.getNode("end"), token.getNode());

          }

          參考:

          1,記號類,代表一個工作處理定義的一條工作流程。

          public class Token

          extends java.lang.Object

          implements java.io.Serializable

          represents one path of execution and maintains a pointer to a node in the ProcessDefinition. Most common way to get a hold of the token objects is with ProcessInstance.getRootToken() or ProcessInstance.findToken(String).

          這個類代表了一個過程的執行流程。使用

          public void signal()

          provides a signal to the token. this method activates this token and leaves the current state over the default transition.

          方法執行一步。



          2,工作處理實例 類

          public class ProcessInstance

          extends java.lang.Object

          implements java.io.Serializable

          is one execution of a ProcessDefinition. To create a new process execution of a process definition, just use the ProcessInstance(ProcessDefinition).

          這個類根據作為Model數據容器類的ProcessDefinition工作處理定義類的一個實例創建。代表一個工作處理定義的執行。主要關注于工作處理相關的操作。



          getRootToken
          public TokengetRootToken()
          得到工作處理定義的從start狀態開始的一條記號----工作流程。





          findToken
          public TokenfindToken(java.lang.String tokenPath)
          looks up the token in the tree, specified by the slash-separated token path.

          Parameters:

          tokenPath - is a slash-separated name that specifies a token in the tree.

          Returns:

          the specified token or null if the token is not found.

          在工作處理定義的樹中,根據記號路徑/工作流程路徑得到一條工作流程







          3.2. Database example

          數據庫例子

          One of the basic features of jBPM is the ability to persist executions of processes in the database when they are in a wait state. The next example will show you how to store a process instance in the jBPM database. The example also suggests a context in which this might occur. Separate methods are created for different pieces of user code. E.g. an piece of user code in a web application starts a process and persists the execution in the database. Later, a message driven bean loads the process instance from the database and resumes its execution.

          jBPM的一個基本的特性是,它能夠在業務處理處于等待狀態時,把業務處理的執行結果儲存到數據庫中。下一個例子講告訴你怎樣把一個業務處理的實例保存進jBPM數據庫。例子也展示了可能發生這種情況的場景。如,用戶的業務處理代碼由幾個獨立的方法組成,例如,一部分用戶代碼是,在一個Web應用程序中開始一個處理,并且把這個處理保存進數據庫。然后,一個消息驅動的bean從數據庫中引導這個業務處理實例----也就是業務處理定義的一個執行的實例(注意:ProcessDefinition業務處理定義是一個Model,保存xml格式的業務處理圖表,一種DSL特定領域語言;而ProcessInstance業務處理實例,也是一個Model,它是保存業務處理定義的一次執行的信息。具體的操作由從它得到的Token記號類執行。Token類是Action類,真正執行業務處理的流程。Token類應該叫做“工作流程類”,代表了業務處理的一條工作流程),恢復它的執行。

          這樣,jBPM的業務處理具有分段、異步執行的能力。



          More about the jBPM persistence can be found in Chapter 7, Persistence.

          API參考:

          1,Jbpm配置

          public class JbpmConfiguration

          extends java.lang.Object

          implements java.io.Serializable

          configuration of one jBPM instance.一個jBPM實例的配置。也就是說,jBPM可以使用多個jBPM配置。基本上,一個jBPM的業務處理可以使用一個JbpmConfiguration對象的實例。

          During process execution, jBPM might need to use some services. A JbpmConfiguration contains the knowledge on how to create those services.

          在業務處理的執行過程中,jBPM可能需要使用一些服務。一個Jbpm配置類包含了怎樣創建這些服務的知識。

          A JbpmConfiguration is a thread safe object and serves as a factory for JbpmContexts, which means one JbpmConfiguration can be used to create JbpmContexts for all threads. The single JbpmConfiguration can be maintained in a static member or in the JNDI tree if that is available.

          一個JbpmConfiguration能夠被用來為所有的線程創建JbpmContext。JbpmConfiguration.createJbpmContext();方法創建Jbpm上下文環境類的一個實例。

          JbpmConfiguration應該使用單例,如靜態成員,或者JNDI樹,或者IOC容器管理的單例等。

          A JbpmConfiguration can be obtained in following ways:

          from a resource (by default jbpm.cfg.xml is used):
          · JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();



          or

          String myXmlResource = "...";

          JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance(myXmlResource);

          from an XML string:
          · JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString(

          · "" +

          · ...

          · ""

          · );



          By specifying a custom implementation of an object factory. This can be used to specify a JbpmConfiguration in other bean-style notations such as used by JBoss Microcontainer or Spring.
          通過指定一個對象工廠的定制實現。被用在JBoss或者Spring容器中。



          · ObjectFactory of = new MyCustomObjectFactory();

          · JbpmConfiguration.Configs.setDefaultObjectFactory(of);

          · JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();



          JbpmConfigurations can be configured using a spring-like XML notation (in relax ng compact notation):

          datatypes xs = "http://www.w3.org/2001/XMLSchema-datatypes"



          start = element beans { element object* }



          object = {

          jbpm-context |

          bean |

          ref |

          map |

          list |

          string |

          int |

          long |

          float |

          double |

          char |

          bool |

          true |

          false |

          null

          }



          jbpm-context = element jbpm-context {

          ( attribute name {xsd:string},

          service*,

          save-operations?

          )

          }



          service = element service {

          ( attribute name {xsd:string},

          ( attribute factory {xsd:string} ) |

          ( factory )

          )

          }



          factory = element factory {

          ( bean |

          ref

          )

          }



          save-operations = element save-operations {

          ( save-operation* )

          }



          save-operation = element save-operation {

          ( ( attribute class {xsd:string} ) |

          ( bean |

          ref

          )

          )

          }



          bean = element bean {

          ( attribute ref-name {xsd:string} ) |

          ( attribute name {xsd:string}?,

          attribute class {xsd:string}?,

          attribute singleton { "true" | "false" }?,

          constructor*,

          field*,

          property*

          )

          }



          ref = element ref {

          ( attribute bean (xsd:string) )

          }



          constructor = element constructor {

          attribute class {xsd:string}?,

          ( attribute factory {xsd:string},

          attribute method {xsd:string}

          )?,

          parameter*

          }



          parameter = element parameter {

          attribute class {xsd:string},

          object

          }



          field = element field {

          attribute name {xsd:string},

          object

          }



          property = element property {

          ( attribute name {xsd:string} |

          attribute setter {xsd:string}

          ),

          object

          }



          map = element map {

          entry*

          }



          entry = element entry {

          key,

          value

          }



          key = element key {

          object

          }



          value = element value {

          object

          }



          list = element list {

          object*

          }



          string = element string {xsd:string}

          int = element integer {xsd:integer}

          long = element long {xsd:long}

          float = element float {xsd:string}

          double = element string {xsd:double}

          char = element char {xsd:character}

          bool = element bool { "true" | "false" }

          true = element true {}

          false = element false {}

          null = element null {}



          Other configuration properties

          jbpm.msg.wait.timout


          jbpm.files.dir


          jbpm.types







          2,Jbpm上下文環境

          public class JbpmContext

          extends java.lang.Object

          implements java.io.Serializable

          is used to surround persistent operations to processes.

          被用來負責業務處理的持久化操作。它底層使用Hibernate等數據庫持久化技術來與數據庫中的保存業務處理圖表、業務處理的執行等的數據庫表交互。

          Obtain JbpmContext's via JbpmConfiguration.createJbpmContext() and put it in a try-finally block like this:

          作為一個數據庫持久化資源,必須要關閉。

          JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();

          try {

          TaskInstance taskInstance = ...



          ...do your process operations...



          // in case you update a process object that was not fetched

          // with a ...ForUpdate method, you have to save it.

          /*





          */

          jbpmContext.save(processInstance);

          finally {

          jbpmContext.close();

          }



          A JbpmContext separates jBPM from a sprecific environment. For each service that jBPM uses, there is an interface specified in the jBPM codebase. jBPM also includes implementations that implement these services by using services in a specific environment. e.g. a hibernate session, a JMS asynchronous messaging system, ...

          JbpmContext從一個jBPM實例的環境中分離而來。每一個jBPM使用的服務,在jBPM的代碼庫中有指定的借口。jBPM也包括在一個特定環境中使用這些服務的實現類。

          A JbpmContext can demarcate a transaction. When a PersistenceService is fetched from the JbpmContext, the default implementation for the persistence service will create a hibernate session and start a transaction. So that transactions can be configured in the hibernate configuration.

          JbpmContext能夠使用事務。如果一個持久化服務是從JbpmContext中來的,那么默認的持久化實現是Hibernate,那么將會創建一個Hibernate會話和事務。

          A JbpmContext allows the user to overwrite重寫 (or make complete) the configuration by injecting objects programmatically編程注入對象. like e.g. a hibernate session factory or a hibernate session or any other resource that can be fetched or created from the configuration.

          Last but not least, JbpmContext provides convenient方便的 access to the most common operations such as getTaskList(String), newProcessInstance(String)loadTaskInstanceForUpdate(long) and save(ProcessInstance).

          All the ...ForUpdate(...) methods will automatically save the loaded objects at jbpmContext.close();

          所有這些涉及到數據庫更新的操作,都會在jbpmContext.close()調用時被自動保存到數據庫中。



          3,GraphSession類 業務處理圖表會話類,更確切的名字:業務處理定義 會話類







          /*

          * JBoss, Home of Professional Open Source

          * Copyright 2005, JBoss Inc., and individual contributors as indicated

          * by the @authors tag. See the copyright.txt in the distribution for a

          * full listing of individual contributors.

          *

          * This is free software; you can redistribute it and/or modify it

          * under the terms of the GNU Lesser General Public License as

          * published by the Free Software Foundation; either version 2.1 of

          * the License, or (at your option) any later version.

          *

          * This software is distributed in the hope that it will be useful,

          * but WITHOUT ANY WARRANTY; without even the implied warranty of

          * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

          * Lesser General Public License for more details.

          *

          * You should have received a copy of the GNU Lesser General Public

          * License along with this software; if not, write to the Free

          * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA

          * 02110-1301 USA, or see the FSF site: http://www.fsf.org.

          */

          package org.jbpm.tutorial.db;



          import java.util.List;



          import junit.framework.TestCase;



          import org.jbpm.JbpmConfiguration;

          import org.jbpm.JbpmContext;

          import org.jbpm.db.GraphSession;

          import org.jbpm.graph.def.ProcessDefinition;

          import org.jbpm.graph.exe.ProcessInstance;

          import org.jbpm.graph.exe.Token;



          public class HelloWorldDbTest extends TestCase {



          static JbpmConfiguration jbpmConfiguration = null;



          static {

          // An example configuration file such as this can be found in

          // 'src/config.files'. Typically the configuration information is in the

          // resource file 'jbpm.cfg.xml', but here we pass in the configuration

          // information as an XML string.



          // First we create a JbpmConfiguration statically. One JbpmConfiguration

          // can be used for all threads in the system, that is why we can safely

          // make it static.

          /**

          *單例對象。

          *JbpmConfiguration能夠被系統中所有線程所使用。

          *jbpm.cfg.xml這個命名方式和Hibernate配置文件的命名方式一致。

          *

          */



          jbpmConfiguration = JbpmConfiguration.parseXmlString(

          "" +



          // A jbpm-context mechanism separates the jbpm core

          // engine from the services that jbpm uses from

          // the environment.

          /*jbpm-context機制在環境中把jbpm核心引擎和jbpm使用的服務分開。

          * 持久化服務是jbpm核心引擎使用的一個服務。

          *

          * */



          " " +

          " " +

          "
          " +



          // Also all the resource files that are used by jbpm are

          // referenced from the jbpm.cfg.xml

          /*

          *string,配置了所有jbpm使用的資源文件的路徑。

          * */



          " " +

          " " +

          " " +

          " " +

          " " +

          " " +

          " " +

          "
          "

          );

          }



          public void setUp() {

          //創建計劃

          jbpmConfiguration.createSchema();

          }



          public void tearDown() {

          //刪除計劃

          jbpmConfiguration.dropSchema();

          }



          public void testSimplePersistence() {

          // Between the 3 method calls below, all data is passed via the

          // database. Here, in this unit test, these 3 methods are executed

          // right after each other because we want to test a complete process

          // scenario情節. But in reality, these methods represent different

          // requests to a server.



          // Since we start with a clean, empty in-memory database, we have to

          // deploy the process first. In reality, this is done once by the

          // process developer.

          /**

          * 這個方法把業務處理定義通過Hibernate保存到數據庫中。

          */

          deployProcessDefinition();



          // Suppose we want to start a process instance (=process execution)

          // when a user submits a form in a web application...

          /*假設當一個用戶提交一個表單時,我們要開始一個業務處理的實例/執行。

          * 這可以在Action中執行處理。

          */

          processInstanceIsCreatedWhenUserSubmitsWebappForm();



          // Then, later, upon the arrival of an asynchronous message the

          // execution must continue.

          /*

          * 然后,直到異步消息來到,才繼續執行業務處理實例的余下的工作流程。

          * */

          theProcessInstanceContinuesWhenAnAsyncMessageIsReceived();

          }



          public void deployProcessDefinition() {

          // This test shows a process definition and one execution

          // of the process definition. The process definition has

          // 3 nodes: an unnamed start-state, a state 's' and an

          // end-state named 'end'.

          /*

          * 這個方法把業務處理定義通過Hibernate保存到數據庫中。

          *

          * */

          ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(

          " " +

          " " +

          " " +

          "
          " +

          " " +

          " " +

          "
          " +

          " " +

          "
          "

          );



          // Lookup the pojo persistence context-builder that is configured above

          JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();

          try {

          // Deploy the process definition in the database

          jbpmContext.deployProcessDefinition(processDefinition);



          } finally {

          // Tear down the pojo persistence context.

          // This includes flush the SQL for inserting the process definition

          // to the database.

          /*

          * 關閉jbpm上下文。刪除pojo持久化上下文。

          * 這包括刷新SQL來真正的把業務處理定義插入到數據庫中。

          * */

          jbpmContext.close();

          }

          }



          public void processInstanceIsCreatedWhenUserSubmitsWebappForm() {

          // The code in this method could be inside a struts-action

          // or a JSF managed bean.



          // Lookup the pojo persistence context-builder that is configured above

          JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();

          try {

          /*

          * 圖表會話,是圖表定義/業務處理定義 相關的數據庫層面的會話。應該也是一個Hibernate會話。

          * 可以從JBpm上下文這個數據庫----業務處理定義、實例等 得到 業務處理定義會話。

          *

          * */

          GraphSession graphSession = jbpmContext.getGraphSession();

          //從數據庫中根據業務處理定義的名字得到一個業務處理定義。

          ProcessDefinition processDefinition =

          graphSession.findLatestProcessDefinition("hello world");



          // With the processDefinition that we retrieved from the database, we

          // can create an execution of the process definition just like in the

          // hello world example (which was without persistence).

          /*

          * 創建業務處理定義的一個實例。

          *

          * */

          ProcessInstance processInstance =

          new ProcessInstance(processDefinition);



          Token token = processInstance.getRootToken();

          assertEquals("start", token.getNode().getName());

          // Let's start the process execution

          token.signal();

          // Now the process is in the state 's'.

          assertEquals("s", token.getNode().getName());



          // Now the processInstance is saved in the database. So the

          // current state of the execution of the process is stored in the

          // database.

          /*

          * 執行一步工作流程后,使用jbpmContext保存這個業務處理實例進數據庫。

          * 所以現在就把業務處理實例的執行狀態也保存進了數據庫。

          * 因為,業務處理定義的實例 這個類也是一個Model類,用于管理一個業務處理定義的執行的所有信息,

          * 是一個多例模式的Model。

          *

          * */

          jbpmContext.save(processInstance);

          // The method below will get the process instance back out

          // of the database and resume execution by providing another

          // external signal.



          } finally {

          // Tear down the pojo persistence context.

          jbpmContext.close();

          }

          }



          public void theProcessInstanceContinuesWhenAnAsyncMessageIsReceived() {

          // The code in this method could be the content of a message driven bean.

          //這個方法可能在消息驅動Bean這個遠程業務代理類中。

          // Lookup the pojo persistence context-builder that is configured above

          JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();

          try {



          GraphSession graphSession = jbpmContext.getGraphSession();

          // First, we need to get the process instance back out of the database.

          // There are several options to know what process instance we are dealing

          // with here. The easiest in this simple test case is just to look for

          // the full list of process instances. That should give us only one

          // result. So let's look up the process definition.



          ProcessDefinition processDefinition =

          graphSession.findLatestProcessDefinition("hello world");



          // Now, we search for all process instances of this process definition.

          /*

          * 根據業務處理定義的id得到數據庫中所有的業務處理實例。這表明,數據庫中應該存在2張表

          * 它們是 一對多 的關系。

          *

          * */

          List processInstances =

          graphSession.findProcessInstances(processDefinition.getId());



          // Because we know that in the context of this unit test, there is

          // only one execution. In real life, the processInstanceId can be

          // extracted from the content of the message that arrived or from

          // the user making a choice.

          ProcessInstance processInstance =

          (ProcessInstance) processInstances.get(0);



          // Now we can continue the execution. Note that the processInstance

          // delegates signals to the main path of execution (=the root token).

          processInstance.signal();



          // After this signal, we know the process execution should have

          // arrived in the end-state.

          assertTrue(processInstance.hasEnded());



          // Now we can update the state of the execution in the database

          jbpmContext.save(processInstance);



          } finally {

          // Tear down the pojo persistence context.

          jbpmContext.close();

          }

          }

          }



          3.3. Context example: process variables

          上下文例子:處理變量

          The process variables contain the context information during process executions. The process variables are similar to a java.util.Map that maps variable names to values, which are java objects. The process variables are persisted as a part of the process instance. To keep things simple, in this example we only show the API to work with variables, without persistence.

          ContextInstance類的實例保存 在ProcessInstance中。是它的一個成員對象。是一個Map,保存名值對。它們會被保存在數據庫中。 應該是一個獨立的表。和業務處理定義的實例/執行表 是“一對多”的關系!

          可以在這里保存一些必要的信息,用于工作流程處理的交流的需要!

          More information about variables can be found in Chapter 10, Context

          publicclass ContextTest extends TestCase {



          publicvoid testContext() {

          // Also this example starts from the hello world process.

          // This time even without modification.

          ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(

          " " +

          " " +

          " " +

          "
          " +

          " " +

          " " +

          "
          " +

          " " +

          "
          "

          );



          ProcessInstance processInstance =

          new ProcessInstance(processDefinition);



          // Fetch the context instance from the process instance

          // for working with the process variableInstances.

          //得到一個map,業務處理實例的上下文實例Map。包含業務處理實例的一些上下文信息。

          ContextInstance contextInstance =

          processInstance.getContextInstance();



          // Before the process has left the start-state,

          // we are going to set some process variableInstances in the

          // context of the process instance.

          contextInstance.setVariable("amount", new Integer(500));

          contextInstance.setVariable("reason", "i met my deadline");



          // From now on, these variableInstances are associated with the

          // process instance. The process variableInstances are now accessible

          // by user code via the API shown here, but also in the actions

          // and node implementations. The process variableInstances are also

          // stored into the database as a part of the process instance.



          processInstance.signal();



          // The variableInstances are accessible via the contextInstance.



          assertEquals(new Integer(500),

          contextInstance.getVariable("amount"));

          assertEquals("i met my deadline",

          contextInstance.getVariable("reason"));

          }



          }



          3.4. Task assignment example任務委派例子

          In the next example we'll show how you can assign a task to a user. Because of the separation between the jBPM workflow engine and the organisational model, an expression language for calculating actors would always be too limited. Therefore, you have to specify an implementation of AssignmentHandler for including the calculation of actors for tasks.

          在下一個例子中,我們將高叔你怎樣給一個用戶分配任務。因為jBPM工作流引擎和組織的模型時各自獨立的,用一種表達式語言來計算動作執行者總是太受限了。因此,你必須指定一個分派處理器的實現來包括任務執行者的計算工作。

          API參考:

          1,任務實例

          public class TaskInstance

          extends VariableContainer

          implements Assignable

          is one task instance that can be assigned to an actor (read: put in someones task list) and that can trigger the coninuation of execution of the token upon completion.

          是一個任務實例,它能夠被分配給一個用戶,能夠觸發工作流的繼續執行。



          publicclass TaskAssignmentTest extends TestCase {



          publicvoid testTaskAssignment() {

          // The process shown below is based on the hello world process.

          // The state node is replaced by a task-node. The task-node

          // is a node in JPDL that represents a wait state and generates

          // task(s) to be completed before the process can continue to

          // execute.

          /*

          * 任務節點是一個JPDL的節點,它表示一個等待狀態,生成任務被完成之前,業務處理將不能執行。

          *

          * */

          ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(

          " " +

          " " +

          " " +

          "
          " +

          " " +

          " " +

          " " +

          "
          " +

          " " +

          "
          " +

          " " +

          "
          "

          );



          // Create an execution of the process definition.

          ProcessInstance processInstance =

          new ProcessInstance(processDefinition);

          Token token = processInstance.getRootToken();



          // Let's start the process execution, leaving the start-state

          // over its default transition.

          token.signal();

          // The signal method will block until the process execution

          // enters a wait state. In this case, that is the task-node.

          assertSame(processDefinition.getNode("t"), token.getNode());



          // When execution arrived in the task-node, a task 'change nappy'

          // was created and the NappyAssignmentHandler was called to determine

          // to whom the task should be assigned. The NappyAssignmentHandler

          // returned 'papa'.



          // In a real environment, the tasks would be fetched from the

          // database with the methods in the org.jbpm.db.TaskMgmtSession.

          // Since we don't want to include the persistence complexity in

          // this example, we just take the first task-instance of this

          // process instance (we know there is only one in this test

          // scenario.

          /*

          * 執行到任務時,需要執行指定的類。這個類設置了執行者的id。

          * 在真實環境中,應該是從數據庫中返回任務,

          * org.jbpm.db.TaskMgmtSession

          * TaskInstance包含:id,任務名,用戶id。

          * 業務處理實例---任務

          * 1 n

          *

          * 用戶-------====任務

          * 1 n

          *

          * */

          TaskInstance taskInstance = (TaskInstance)

          processInstance

          .getTaskMgmtInstance()

          .getTaskInstances()

          .iterator().next();



          // Now, we check if the taskInstance was actually assigned to 'papa'.

          assertEquals("papa", taskInstance.getActorId() );



          // Now suppose that 'papa' has done his duties and marks the task

          // as done.

          taskInstance.end();

          // Since this was the last (only) task to do, the completion of this

          // task triggered the continuation of the process instance execution.



          assertSame(processDefinition.getNode("end"), token.getNode());

          }



          }

          3.5. Custom action example定制動作例子

          Actions are a mechanism to bind your custom java code into a jBPM process. Actions can be associated with its own nodes (if they are relevant in the graphical representation of the process). Or actions can be placed on events like e.g. taking a transition, leaving a node or entering a node. In that case, the actions are not part of the graphical representation, but they are executed when execution fires the events in a runtime process execution.

          We'll start with a look at the action implementation that we are going to use in our example : MyActionHandler. This action handler implementation does not do really spectacular things不是真的做偉大的事情... it just sets the boolean variable isExecuted to true. The variable isExecuted is static so it can be accessed from within the action handler as well as from the action to verify it's value.

          More information about actions can be found in Section 9.5, “Actions”

          // MyActionHandler represents a class that could execute

          // some user code during the execution of a jBPM process.

          publicclass ActionTest extends TestCase {



          // Each test will start with setting the static isExecuted

          // member of MyActionHandler to false.

          publicvoid setUp() {

          MyActionHandler.isExecuted = false;

          }



          publicvoid 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(

          " " +

          " " +

          " " +

          "
          " +

          " " +

          //轉向執行時,執行該動作

          " " +

          " " +

          "
          " +

          "
          " +

          " " +

          "
          "

          );



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

          }

          The next example shows the same action, but now the actions are placed on the enter-node進入節點事件 and leave-node events 離開節點事件respectively. Note that a node has more then one event type in contrast to a transition, which has only one event. Therefore actions placed on a node should be put in an event element.

          Transition轉向只有一個節點。



          publicvoid testNodeActions() {

          ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(

          " " +

          " " +

          " " +

          "
          " +

          " " +

          //節點進入事件,進入節點時,事件激活。執行該動作。

          " " +

          " " +

          "
          " +

          //節點離開事件,離開節點時,事件激活。執行該動作。

          " " +

          " " +

          "
          " +

          " " +

          "
          " +

          " " +

          "
          "

          );



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

          }

          }





          動作類

          publicclass MyActionHandler implements ActionHandler {



          privatestaticfinallongserialVersionUID = 1L;



          // Before each test (in the setUp), the isExecuted member

          // will be set to false.

          publicstaticbooleanisExecuted = false;



          // The action will set the isExecuted to true so the

          // unit test will be able to show when the action

          // is being executed.

          publicvoid execute(ExecutionContext executionContext) {

          isExecuted = true;

          }

          }



          API參考:

          1,

          ExecutionContext 執行上下文類。

          作為參數回調模式的參數,用于得到業務處理實例的東西。

          JbpmContext
          getJbpmContext()


          Node
          getNode()


          ProcessDefinition
          getProcessDefinition()


          ProcessInstance
          getProcessInstance()



          可以通過它得到所有“業務處理”相關的對象。

          posted on 2007-09-06 12:29 禮物 閱讀(752) 評論(0)  編輯  收藏 所屬分類: Jbpm
          主站蜘蛛池模板: 旬阳县| 武威市| 衡南县| 贺州市| 上蔡县| 乐平市| 施秉县| 澎湖县| 巢湖市| 平潭县| 方城县| 洞口县| 林周县| 平罗县| 友谊县| 平泉县| 青州市| 柘荣县| 禹州市| 侯马市| 汤原县| 西贡区| 陕西省| 汕尾市| 彰武县| 台南县| 西林县| 阜宁县| 宣威市| 苏尼特右旗| 正镶白旗| 清苑县| 巫溪县| 饶阳县| 安陆市| 阿克陶县| 远安县| 四川省| 柳江县| 县级市| 三江|