jeffy

BlogJava 首页 新随笔 联系 聚合 管理
  70 Posts :: 1 Stories :: 14 Comments :: 0 Trackbacks

osworkflow中最最核心的东西就是工作流定义的xml文件。尽管它并不是一定要定义成xml文件。但是xml格式是一种标准的通用的格式。OSWorkflow引擎只负责了“流程的运转”,当然这个运转会根据你所定义的Action和condtion来判断。

这个xml文件为某一个给定的工作流进行描述stepsstatestransitions,和functionality。下面阐述一下此xml的一般规则:

1、  一个工作流由多个steps组成

2、  对于每个step,可以包括多个actions。一个action可以被设置成自动运行或者需要通过人工交互才可以运行。

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

4、  如果设定了多个concitioanl results,所有当中的第一个将被执行,如果没有设定conditional results或者没有conditions满足,那么执行unconditional result

5、  一个result过后可能依旧停留在当前的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是一个持久层数据的map,在全局应用中都是可用的。

9、  还有一种叫做transientVarsmap,它只存活于一个工作流调用过程中的一定的生命周期,它将会对所有functionsconditions,包括所有的registersuser input,以及工作流上下文状态等起作用。

工作流概念:

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

对于stepstatusactions部分就不多说明了,其实我觉得理解概念的最快方法应该是参照实例,即使我们不能用高高大大的词汇描绘出来,能自己理解是什么意思就可以了。

Unconditional result conditional results

这里做以简单介绍,对于每个action,要求至少存在一个Unconditional  result,一个result也就是通过一系列指示来告诉osworkflow下一步的任务是干什么。这种调用使得产生变迁进而从一个state到另外一个state。这种概念是在UML的状态机里有讲,希望了解状态机相关概念的可以到UML相关书籍中查看。

Conditional resultunconditional result的一种扩展。不同的地方在于他需要一些子元素:condition。用and or来标志各个condition之间的关系。

Conditional unconditional 的最终result可以产生三种效应或者说是结果:

1、  一个新的step/status

2、  一个split,出现一或多个step/status

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

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

一个step/status result可以按下面方式简单的设定:

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

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

从一个state split 到多个 states可以按以下方式达到:

<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是比较复杂的用例。一个典型的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>

上面这段代码中最需要关心的就应该是jn。当join实际发生的时候,这个特殊的变量jn可以被用来建立表达式。本质上,可以很容易理解出这个段xml的意思就是:当step68finish时候在此处进行join

api-查询:
 
§目的:希望了解流程当前的运行状况à查询
§WorkflowQuery及其相关类(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导向workflowstore进行实际查询,最后将查询结果存储与arraylist中
§目的:希望了解流程当前的运行状况à查询
§WorkflowQuery及其相关类(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导向workflowstore进行实际查询,最后将查询结果存储与arraylist中


Functions
部分

Osworkflowfunction来定义商业逻辑和一些需要定义执行的服务。用functions标签来表示。

两种functionsprepost

Pre 是在工作流进行某个变迁之前需要被执行的。一个比较好的例子:为了在resultstate变更产生,而先建立caller

Post是在之后执行的。如当某一个state改变后,发送一email到某处。

Functions可以在两个分别的地方被指定:stepsactions

Trigger Functions
  
Trigger和jobDetail,trigger触发条件满足后,则会激活真正的job实例,job实例真正执行的是trigger function(在配置文件中定义)
Validators

Registers

一个function:用来返回一个用以被其他普通对象能够容易访问得到的对象。尤其是指workflow 的实体类。返回的对象类型不闲典型的例子如: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

变量

授权与限权

自动执行的action

设置auto=true

Common and global actions

Commonglobalactions的主要作用在于在工作流定义文件中能够避免代码重复。

基本思想就是简单。这两种actions是在最开始就进行说明的,在initial-actions元素后面。

这两处还不能完全理解好!

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

<common-action id="100" />

例如一个“send mail”的action

Global actions:不同之处在于显式的被某一个step引用。它通常对所有的steps都是可用的。一个例子:“终止工作流”,在任何一步,都有可能终止工作流。

需要注意的是:这两种actions要具备唯一的ID,而不能和其他actionID重复。

接下来主要讲解关于function的四种情况:

osworkflow中的function就是可以在变迁之前或者后进行执行的内容。

1、  基于javafunctions

classloader中加载java 类,通过jndi找会java类,远程ejbs,本地ejb

这一类型的function必须实现接口:com.opensymphony.workflow.FunctionProvider在这个接口中有一个方法execute。这个方法(execute)需要三个参数 可以自己去查api即可找到这三个参数,两个map一个propertyset

public interface FunctionProvider {

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

 

       所有的Function实现类都必须实现这个FunctionProvider接口中execute方法,而且能够处理的信息,也全部来自这个方法中的三个参数:

 

transientVars

这个是最为核心的参数,记录非常重要的一些对象,比如WorkflowContextWorkflowEntry,输入参数等等。

args

这个是function配置中的arg参数,具体请参考osworkflow dtd

ps

PropertySet对象,记录了流程实例所需要保存的数据,可以理解成osworkflow所描述的流程相关数据。

 

      





具体transienVars中包含哪些对象,请参考 FunctionProvider api doc

 

       下面就说说如何利用Function进行任务的分配。

 

       个人建议你在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>

 

看了这个配置形式,大家应该明白如何去处理。你可以在function中获取自己所定义的角色、根据角色获取人员、根据人员产生workitem······ 。你在function 所作的这一切操作对osworkflow engine来说都是透明的—— 你所产生的worklist所代表的含义只有你自己知道。

其中我为什么会附加了一个arg属性:actionID?这是因为我需要告诉每一个workitem在其应该处理哪一个动作。 因为外部程序都是通过Workflow.doAction(long, int, java.util.Map) 这个接口来激活流程的运转或改变实例的状态。

基于
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想类似,当然必须已经确实存在于jndi树中,在这里,需要一个jndi.location来进行配置:

<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的相关内容。

在这种情况下,需要将xml过程定义中的type设置成beanshell。另外还需要有个一个参数名字为script的参数,此参数值是实际需要被执行的。

例如:

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

</function>

三种变量:entrycontextstore

entry:实现com.opensymphony.workflow.spi.WorkflowEntry并且表示工作流实例。

Contextcom.opensymphony.workflow.WorkflowContext。允许beanshell functions回滚事务或者确定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>

输出结果是“helloearth”因为任何存储在propertyset中的变量将可以在整个工作流中被持久使用。

3、  BSF function(perlscript, vbscript, javascript)

除了上面说过的两种typefunction。还有bsf类型的function

BSFbean scripting framework)是IBM的一个组织做的一个通用环境可以使用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这部分查看。下面只是列出一些主要的功能。相当于java.util里的东西。

主要用于创建动态的工作流定义,主要是包括一些实用功能,如callerwebworkexecutorejbinvokerjmsmessagemostrecentownerschedulejobunschdulejobsendmail

这部分碰到不懂就去查api是个好办法,这里就不去多写的。

osworkflow的schedule:
 
定时执行某项任务的功能
<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必须实现com.opensymphony.workflow.Validator接口(如果是remote-ejb,则需实现com.opensymphony.workflow.ValidatorRemote接口)。Java-based这种情况是通过抛出个InvalidInputException异常表明一个输入是不合法的,并且停止工作流action

beanshellbsf中,有一点小小不同,即使异常可以在脚本中抛出,但是不能抵达到jre。所以在beanshellbsf中用错误信息来完成。逻辑如下:

u       如果返回值是一个InvalidInputException对象,这个对象立刻抛出到client

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

u       如果返回值是一个String [],偶数字被做为key。奇数做为value来构造一个map

u       其他情况,把值转换成string并且作为一个普通的错误信息来添加。

Registers:

Register是一个在工作流定义文件中用来动态注册的运行时(块)

它也是和validatorsfunctions差不多,都是能够以java-basedbeanshellbsf不同格式出现。

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。如果你需要更多复杂的condition逻辑。可以考虑实现condition或者conditionremote接口,beanshellbsf。如果只有一个condition子元素的时候,conditionstype属性值可以省略。

2.7中。可以嵌套conditions,这样可以让你实现更为复杂的商业逻辑。

下面是一个写标准的conditions

OSUserGroupConditionStatusConditionAllowOwnerOnlyConditionDenyOwnerCondition

Soap支持,暂时略!因为暂时可能涉及不到!

Gui Designer部分略。
                              (申明:本文来源于网络,摘录于此,仅为日后方便查看)

posted on 2006-03-02 11:48 Live-in Java 阅读(992) 评论(0)  编辑  收藏 所属分类: Workflow

只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问