jeffy

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            70 Posts :: 1 Stories :: 14 Comments :: 0 Trackbacks

          osworkflow中最最核心的東西就是工作流定義的xml文件。盡管它并不是一定要定義成xml文件。但是xml格式是一種標(biāo)準(zhǔn)的通用的格式。OSWorkflow引擎只負(fù)責(zé)了“流程的運(yùn)轉(zhuǎn)”,當(dāng)然這個運(yùn)轉(zhuǎn)會根據(jù)你所定義的Action和condtion來判斷。

          這個xml文件為某一個給定的工作流進(jìn)行描述stepsstatestransitions,和functionality。下面闡述一下此xml的一般規(guī)則:

          1、  一個工作流由多個steps組成

          2、  對于每個step,可以包括多個actions。一個action可以被設(shè)置成自動運(yùn)行或者需要通過人工交互才可以運(yùn)行。

          3、  每個action都要包括至少一個unconditional result0或多個conditional results

          4、  如果設(shè)定了多個concitioanl results,所有當(dāng)中的第一個將被執(zhí)行,如果沒有設(shè)定conditional results或者沒有conditions滿足,那么執(zhí)行unconditional result

          5、  一個result過后可能依舊停留在當(dāng)前的step中,一個新的step,一個split,一個join。在所有的情形中,工作流的state跟著變化(例子工作流中的states分別為:Underway,Queued,finished

          6、  如果一個result引起一個split,這個result會指定split的屬性,以指向一個split元素。

          7、  一個split可以有一個或者多個unconditional results,但是沒有conditional resultsUnconditional resultsUnconditional results需要指定steps

          8、  一個propertyset是一個持久層數(shù)據(jù)的map,在全局應(yīng)用中都是可用的。

          9、  還有一種叫做transientVarsmap,它只存活于一個工作流調(diào)用過程中的一定的生命周期,它將會對所有functionsconditions,包括所有的registersuser input,以及工作流上下文狀態(tài)等起作用。

          工作流概念:

          下面開始理解osworkflow的核心概念:

          對于stepstatusactions部分就不多說明了,其實(shí)我覺得理解概念的最快方法應(yīng)該是參照實(shí)例,即使我們不能用高高大大的詞匯描繪出來,能自己理解是什么意思就可以了。

          Unconditional result conditional results

          這里做以簡單介紹,對于每個action,要求至少存在一個Unconditional  result,一個result也就是通過一系列指示來告訴osworkflow下一步的任務(wù)是干什么。這種調(diào)用使得產(chǎn)生變遷進(jìn)而從一個state到另外一個state。這種概念是在UML的狀態(tài)機(jī)里有講,希望了解狀態(tài)機(jī)相關(guān)概念的可以到UML相關(guān)書籍中查看。

          Conditional resultunconditional result的一種擴(kuò)展。不同的地方在于他需要一些子元素:condition。用and or來標(biāo)志各個condition之間的關(guān)系。

          Conditional unconditional 的最終result可以產(chǎn)生三種效應(yīng)或者說是結(jié)果:

          1、  一個新的step/status

          2、  一個split,出現(xiàn)一或多個step/status

          3、  一個join,一個新的step/status

          普遍的,一個split或者join不能result出另外一個splitjoin

          一個step/status result可以按下面方式簡單的設(shè)定:

          <unconditional-result old-status="Finished" step="2"

                                status="Underway" owner="${someOwner}"/>

          從一個state split 到多個 states可以按以下方式達(dá)到:

          <unconditional-result split="1"/>
          ...
          <splits>
            <split id="1">
              <unconditional-result old-status="Finished" step="2" 
                                    status="Underway" owner="${someOwner}"/>
              <unconditional-result old-status="Finished" step="2" 
                                    status="Underway" owner="${someOtherOwner}"/>
            </split>
          </splits>

          Joins是比較復(fù)雜的用例。一個典型的join看起來大致如下:

          <!-- for step id 6 ->
          <unconditional-result join="1"/>
          ...
          <!- for step id 8 ->
          <unconditional-result join="1"/>
          ...
          <joins>
            <join id="1">
              <join id="1">
              <conditions type="AND">
                <condition type="beanshell">
                  <arg name="script">
                    "Finished".equals(jn.getStep(6).getStatus() 
                    && "Finished".equals(jn.getStep(8).getStatus())
                  </arg>
                </condition>
              </conditions>
            </join>
            <unconditional-result old-status="Finished" status="Underway" 
                                           owner="test" step="2"/>
            </join>
          </joins>

          上面這段代碼中最需要關(guān)心的就應(yīng)該是jn。當(dāng)join實(shí)際發(fā)生的時候,這個特殊的變量jn可以被用來建立表達(dá)式。本質(zhì)上,可以很容易理解出這個段xml的意思就是:當(dāng)step68finish時候在此處進(jìn)行join

          api-查詢:
           
          §目的:希望了解流程當(dāng)前的運(yùn)行狀況à查詢
          §WorkflowQuery及其相關(guān)類(query包)
          § WorkflowQuery queryLeft = new WorkflowQuery(
            WorkflowQuery.OWNER, WorkflowQuery.CURRENT, WorkflowQuery.EQUALS, “test");
          WorkflowQuery queryRight = new WorkflowQuery(
            WorkflowQuery.STATUS, WorkflowQuery.CURRENT, WorkflowQuery.EQUALS, “Underway");
          WorkflowQuery query = new WorkflowQuery(
            queryLeft, WorkflowQuery.AND, queryRight);
          List workflows = wf.query(query);
          for (Iterator iterator = workflows.iterator(); iterator.hasNext();)
            Long wfId = (Long) iterator.next();
          }
          §AbstractWorkflow導(dǎo)向workflowstore進(jìn)行實(shí)際查詢,最后將查詢結(jié)果存儲與arraylist中
          §目的:希望了解流程當(dāng)前的運(yùn)行狀況à查詢
          §WorkflowQuery及其相關(guān)類(query包)
          § WorkflowQuery queryLeft = new WorkflowQuery(
            WorkflowQuery.OWNER, WorkflowQuery.CURRENT, WorkflowQuery.EQUALS, “test");
          WorkflowQuery queryRight = new WorkflowQuery(
            WorkflowQuery.STATUS, WorkflowQuery.CURRENT, WorkflowQuery.EQUALS, “Underway");
          WorkflowQuery query = new WorkflowQuery(
            queryLeft, WorkflowQuery.AND, queryRight);
          List workflows = wf.query(query);
          for (Iterator iterator = workflows.iterator(); iterator.hasNext();)
            Long wfId = (Long) iterator.next();
          }
          §AbstractWorkflow導(dǎo)向workflowstore進(jìn)行實(shí)際查詢,最后將查詢結(jié)果存儲與arraylist中


          Functions
          部分

          Osworkflowfunction來定義商業(yè)邏輯和一些需要定義執(zhí)行的服務(wù)。用functions標(biāo)簽來表示。

          兩種functionsprepost

          Pre 是在工作流進(jìn)行某個變遷之前需要被執(zhí)行的。一個比較好的例子:為了在resultstate變更產(chǎn)生,而先建立caller

          Post是在之后執(zhí)行的。如當(dāng)某一個state改變后,發(fā)送一email到某處。

          Functions可以在兩個分別的地方被指定:stepsactions

          Trigger Functions
            
          Trigger和jobDetail,trigger觸發(fā)條件滿足后,則會激活真正的job實(shí)例,job實(shí)例真正執(zhí)行的是trigger function(在配置文件中定義)
          Validators

          Registers

          一個function:用來返回一個用以被其他普通對象能夠容易訪問得到的對象。尤其是指workflow 的實(shí)體類。返回的對象類型不閑典型的例子如:documentmetadataissuetask等。非常便利。

          <registers>
                 <register name="doc" class="com.acme.DocumentRegister"/>
          </registers>
          ...
          <results>
                 <result condition="doc.priority == 1" step="1" status="Underway" 
                            owner="${someManager}"/>
                 <unconditional-result step="1" status="Queued"/>
          </results>

          Conditions

          變量

          授權(quán)與限權(quán)

          自動執(zhí)行的action

          設(shè)置auto=true

          Common and global actions

          Commonglobalactions的主要作用在于在工作流定義文件中能夠避免代碼重復(fù)。

          基本思想就是簡單。這兩種actions是在最開始就進(jìn)行說明的,在initial-actions元素后面。

          這兩處還不能完全理解好!

          Common actions:在最開始定義好,可以在其他地方如此引用

          <common-action id="100" />

          例如一個“send mail”的action

          Global actions:不同之處在于顯式的被某一個step引用。它通常對所有的steps都是可用的。一個例子:“終止工作流”,在任何一步,都有可能終止工作流。

          需要注意的是:這兩種actions要具備唯一的ID,而不能和其他actionID重復(fù)。

          接下來主要講解關(guān)于function的四種情況:

          osworkflow中的function就是可以在變遷之前或者后進(jìn)行執(zhí)行的內(nèi)容。

          1、  基于javafunctions

          classloader中加載java 類,通過jndi找會java類,遠(yuǎn)程ejbs,本地ejb

          這一類型的function必須實(shí)現(xiàn)接口:com.opensymphony.workflow.FunctionProvider在這個接口中有一個方法execute。這個方法(execute)需要三個參數(shù) 可以自己去查api即可找到這三個參數(shù),兩個map一個propertyset

          public interface FunctionProvider {

            public void execute(Map transientVars, Map args, PropertySet ps) throws WorkflowException;
          }

           

                 所有的Function實(shí)現(xiàn)類都必須實(shí)現(xiàn)這個FunctionProvider接口中execute方法,而且能夠處理的信息,也全部來自這個方法中的三個參數(shù):

           

          transientVars

          這個是最為核心的參數(shù),記錄非常重要的一些對象,比如WorkflowContextWorkflowEntry,輸入?yún)?shù)等等。

          args

          這個是function配置中的arg參數(shù),具體請參考osworkflow dtd

          ps

          PropertySet對象,記錄了流程實(shí)例所需要保存的數(shù)據(jù),可以理解成osworkflow所描述的流程相關(guān)數(shù)據(jù)。

           

                





          具體transienVars中包含哪些對象,請參考 FunctionProvider api doc

           

                 下面就說說如何利用Function進(jìn)行任務(wù)的分配。

           

                 個人建議你在Steppre-function中做處理,配置如下:

              <step id="4" name="Assign">

                <pre-functions>

                  <function type="class">

                    <arg name="class.name">nucleus.assign.AssignmentFunction</arg>

                    <arg name="Participant">A</arg>

                    <arg name="ParticipantType">role</arg>
                    <arg name="actionID">22</arg>

                  </function>

                </pre-functions>

                <actions>

                   ······

                </actions>

              </step>

           

          看了這個配置形式,大家應(yīng)該明白如何去處理。你可以在function中獲取自己所定義的角色、根據(jù)角色獲取人員、根據(jù)人員產(chǎn)生workitem······ 。你在function 所作的這一切操作對osworkflow engine來說都是透明的—— 你所產(chǎn)生的worklist所代表的含義只有你自己知道。

          其中我為什么會附加了一個arg屬性:actionID?這是因?yàn)槲倚枰嬖V每一個workitem在其應(yīng)該處理哪一個動作。 因?yàn)橥獠砍绦蚨际峭ㄟ^Workflow.doAction(long, int, java.util.Map) 這個接口來激活流程的運(yùn)轉(zhuǎn)或改變實(shí)例的狀態(tài)。

          基于
          javafunctions在以下類型是可用的。

          1)、class

          對于一個class functionclassloader必須能夠知道你的function的類名。如下:

          <function type="class">
                <arg name="class.name">com.acme.FooFunction</arg>
                <arg name="message">The message is ${message}</arg>

          </function>

          2)、jndi

          jndi function class想類似,當(dāng)然必須已經(jīng)確實(shí)存在于jndi樹中,在這里,需要一個jndi.location來進(jìn)行配置:

          <function type="jndi">
                <arg name="jndi.location">java:/FooFunction</arg>
                <arg name="message">The message is ${message}</arg>

          </function>

          3)、remote-ejb

          這部分跳過

          <function type="remote-ejb">
                <arg name="ejb.location">java:/comp/env/FooEJB</arg>
                <arg name="message">The message is ${message}</arg>

          </function>

          (4)local-ejb

          跳過

          <function type="local-ejb">
                <arg name="ejb.location">java:/comp/env/FooEJB</arg>
                <arg name="message">The message is ${message}</arg>

          </function>

          2、  beanshell function

          osworkflow支持beanshell,這是一種腳本語言。可以在http://www.beanshell.org/來查看beanshell的相關(guān)內(nèi)容。

          在這種情況下,需要將xml過程定義中的type設(shè)置成beanshell。另外還需要有個一個參數(shù)名字為script的參數(shù),此參數(shù)值是實(shí)際需要被執(zhí)行的。

          例如:

          <function type="beanshell">
                <arg name="script">  
                      System.out.println("Hello, World!");
                </arg>

          </function>

          三種變量:entrycontextstore

          entry:實(shí)現(xiàn)com.opensymphony.workflow.spi.WorkflowEntry并且表示工作流實(shí)例。

          Contextcom.opensymphony.workflow.WorkflowContext。允許beanshell functions回滾事務(wù)或者確定callername

          Storecom.opensymphony.workflow.WorkflowStore允許function訪問工作流的持久存儲層。

          <function type="beanshell">
                <arg name="script">  
                      propertySet.setString("world", "Earth");
                </arg>
          </function>
          <function type="beanshell">
                <arg name="script">  
                      System.out.println("Hello, "+propertySet.getString("world"));
                </arg>

          </function>

          輸出結(jié)果是“helloearth”因?yàn)槿魏未鎯υ?/SPAN>propertyset中的變量將可以在整個工作流中被持久使用。

          3、  BSF function(perlscript, vbscript, javascript)

          除了上面說過的兩種typefunction。還有bsf類型的function

          BSFbean scripting framework)是IBM的一個組織做的一個通用環(huán)境可以使用VBScript, Perlscript, Python, and JavaScript

          <function type="bsf">
                <arg name="source">foo.pl</arg>
                <arg name="row">0</arg>
                <arg name="col">0</arg>
                <arg name="script">
                      print $bsf->lookupBean("propertySet").getString("foo");
                </arg>

          </function>

          個人覺得這部分可以先跳過去,知道有這么一回事就可以了。

          4、  Utility Function

          可以到apicom.opensymphony.workflow.util這部分查看。下面只是列出一些主要的功能。相當(dāng)于java.util里的東西。

          主要用于創(chuàng)建動態(tài)的工作流定義,主要是包括一些實(shí)用功能,如callerwebworkexecutorejbinvokerjmsmessagemostrecentownerschedulejobunschdulejobsendmail

          這部分碰到不懂就去查api是個好辦法,這里就不去多寫的。

          osworkflow的schedule:
           
          定時執(zhí)行某項(xiàng)任務(wù)的功能
          <function type="class">
           <arg name="class.name">com.opensymphony.workflow.util.ScheduleJob</arg>
           <arg name="triggerId">1</arg>
           <arg name="jobName">testJob</arg>
           <arg name="triggerName">testTrigger</arg>
           <arg name="groupName">test</arg>
           <arg name="repeat">10</arg>
           <arg name="repeatDelay">2000</arg>
           <arg name="cronExpression">0,5,10,15,20,25,30,35,40,45,50,55 * * * * ?</arg>
           <arg name="username">test</arg>
           <arg name="password">test</arg>
           <arg name="local">true</arg>
           <arg name="schedulerStart">true</arg>
          </function> 


          validators:

          functions類似,osworkflow有下面幾種不同形式的validatorsjava-basedbeanshell,和bsfJava-basedvalidators必須實(shí)現(xiàn)com.opensymphony.workflow.Validator接口(如果是remote-ejb,則需實(shí)現(xiàn)com.opensymphony.workflow.ValidatorRemote接口)。Java-based這種情況是通過拋出個InvalidInputException異常表明一個輸入是不合法的,并且停止工作流action

          beanshellbsf中,有一點(diǎn)小小不同,即使異常可以在腳本中拋出,但是不能抵達(dá)到jre。所以在beanshellbsf中用錯誤信息來完成。邏輯如下:

          u       如果返回值是一個InvalidInputException對象,這個對象立刻拋出到client

          u       如果返回值是一個mapmap被用做一個error/errormessage對。

          u       如果返回值是一個String [],偶數(shù)字被做為key。奇數(shù)做為value來構(gòu)造一個map

          u       其他情況,把值轉(zhuǎn)換成string并且作為一個普通的錯誤信息來添加。

          Registers:

          Register是一個在工作流定義文件中用來動態(tài)注冊的運(yùn)行時(塊)

          它也是和validatorsfunctions差不多,都是能夠以java-basedbeanshellbsf不同格式出現(xiàn)。

          Conditions:

          Conditionsosworkflow小小不相似之處在于:在bsf或者beanshell腳本中,有一個額外的對象叫做“jn”。這個jn來源于com.opensymphony.workflow.joinnodes。它的作用就是連接條件(join-conditions)。除此之外,condition必須有一個返回值(true or false)。

          Condition必須被conditions包含成為其子元素。Conditions有一個屬性type。可以為and或者orAnd表示:所有condition元素必須都為true或者falseOr表示只要有一個condition元素為true。如果你需要更多復(fù)雜的condition邏輯。可以考慮實(shí)現(xiàn)condition或者conditionremote接口,beanshellbsf。如果只有一個condition子元素的時候,conditionstype屬性值可以省略。

          2.7中。可以嵌套conditions,這樣可以讓你實(shí)現(xiàn)更為復(fù)雜的商業(yè)邏輯。

          下面是一個寫標(biāo)準(zhǔn)的conditions

          OSUserGroupConditionStatusConditionAllowOwnerOnlyConditionDenyOwnerCondition

          Soap支持,暫時略!因?yàn)闀簳r可能涉及不到!

          Gui Designer部分略。
                                        (申明:本文來源于網(wǎng)絡(luò),摘錄于此,僅為日后方便查看)

          posted on 2006-03-02 11:48 Live-in Java 閱讀(1000) 評論(0)  編輯  收藏 所屬分類: Workflow
          主站蜘蛛池模板: 永昌县| 教育| 柘荣县| 通道| 大埔区| 芦溪县| 庄河市| 香港| 张掖市| 嵩明县| 石门县| 揭西县| 兴业县| 津南区| 龙州县| 禄丰县| 农安县| 黄石市| 蓝山县| 甘孜| 鹿泉市| 双牌县| 河池市| 白玉县| 六枝特区| 渭源县| 准格尔旗| 常山县| 浑源县| 廊坊市| 玉树县| 山丹县| 罗山县| 余干县| 宣武区| 厦门市| 江川县| 塔河县| 红安县| 双江| 光泽县|