OSWorkflow 收集

OSWorkflow 基本概念 >>
http://www.blogdriver.com/showBlog.do?diaryID=113138
   
Step
大致相当于 流程所在的位置 。譬如企业年检,年检报告书在企业端算一个 step ,在工商局算第二个 step ,在复核窗口算第三个 step 。每个 step 可以有多种状态( status )和多个动作( action ),用 Workflow.getCurrentSteps () 可以获得所有当前的 step (如果有并列流程,则可能同时有多个 step ,例如一次年检可能同时位于 初审 ”step 广告经营资格审查 ”step )。
 
Status
流程在某个 step 中的状态 。很容易理解,譬如 待认领 审核不通过 之类的。 OSWorkflow 中的状态完全是由开发者自定义的,状态判别纯粹是字符串比对,灵活性相当强,而且可以把定义文件做得很好看。
 
Action
导致流程状态变迁的动作 。一个 action 典型地由两部分组成:可以执行此动作的条件( conditions ),以及执行此动作的结果( results )。条件可以用 BeanShell 脚本来判断,因此具有很大的灵活性,几乎任何与流程相关的东西都可以用来做判断。
 
Result
执行动作后的结果 。这是个比较重要的概念。 result 分为两种, conditional-result unconditional-result 。执行一个动作之后,首先判断所有 conditional-result 的条件是否满足,满足则使用该结果;如果没有任何 contidional -result 满足条件,则使用 unconditional-result unconditional-result 需要指定两部分信息: old-status ,表示 当前 step 的状态变成什么 ;后续状态,可能是用 step+status 指定一个新状态,也可能进入 split 或者 join
 
conditional-result 非常有用。还是以年检为例,同样是提交年检报告书, 未提交 被退回 是不同的状态,在这两个状态基础上执行 提交 动作,结果分别是 初次提交 退回之后再次提交 。这时可以考虑在 提交 动作上用 conditional-result
 
Split/Join
流程的切分和融合 。很简单的概念, split 提供多个 result join 则判断 多个 current step 的状态,提供一个 result
 
*     *     *
 
熟悉这些概念,在流程定义中尽量使用中文,可以给业务代码和表现层带来很多方便。
电子政务 / OA 如果要使用 workflow engine 的话 , shark, jbpm 之类的 workflow engine 有点杀鸡用牛刀的味道 . shark jbpm 都强迫你使用它的用户模型 , 怎样把企业现有的用户模型 ( 包括组织结构 ) 映射过来是很繁琐的事情 , 比如常见的 OA 应用中 , 申请者对应的部门负责人为下一个流程的人工参与者 , 使用 shark 或者 jbpm 都得绕一圈 , 通过现有的人力资源系统 , 获得用户 , 再对应过来 . 这还仅仅是一个简单的需求 , 更不用说国内企业千奇百怪的组织结构 , 以及各种特殊流程 , wfmc 或者其他所谓的 workflow 通用标准去做不怎么标准的事情 , 吃力不讨好 . osworkflow 这种基于状态机的 workflow engine 反而会轻松很多 , 而且它也没有强迫你使用它的用户模型 . 另外纠正一点 : osworkflow 不仅仅支持简单的 BeanShell , 还支持 java class, bsf, ejb. 如果做电子政务 / OA 的话 , 觉得目前 osworkflow 是最适用的 opensource workflow engine.
 
OSWorkflow BeanShell 的运行环境 >>
http://www.blogdriver.com/showBlog.do?diaryID=109107
   
以前问 Potian 脚本可以做什么 ,现在明白了。脚本语言具有无穷大的威力,只要你给它无穷大的运行环境( context )。设计可以嵌入脚本的框架时,就要考虑给脚本怎样的 context 。一些最可能用到的东西,应该放在脚本伸手可及的地方;如果所有东西都可以通过一个全局 Service Locator 导航获得,那么脚本就什么都可以做。
 
com.opensymphony.workflow.util.beanshell 这个包里的几个类就是 OSWorkflow 配置文件中 BeanShell 脚本的运行环境,每个类对应一种 BeanShell 定义。譬如对于 type="beanshell" name="bsh.condition" BeanShell 脚本,它得到的运行环境是这样设置的( BeanShellCondition.passesCondition 方法):
 
        Interpreter i = new Interpreter();  // BeanShell 解释器
        Map transientVars;
        PropertySet ps;
        WorkflowContext context;
        WorkflowEntry entry;
        ClassLoader loader;
            i.set("entry", entry);
            i.set("context", context);
            i.set("transientVars", transientVars);
            i.set("propertySet", ps);
            i.set("jn", transientVars.get("jn"));

 
通过 entry 变量( WorkflowEntry )可以得到工作流 ID 、名称、状态(激活、挂起、结束等等);通过 context 变量( WorkflowContext )可以得到调用者( caller ,我打算用这个值来作为每个工作流实例的唯一标识,不知道是否合理); transientVars 是一个 Map ,传递临时性的参数; propertySet 是持久化的属性设置。
 
jn 变量是用在 join 节点中的 —— 当两个流程需要合并时,就会进入一个 join 节点。譬如说,年检流程和广告审查流程、注册流程和并联审批流程,它们的合并就要在一个 join 节点中判断两条流程是否都达到合适的位置。调用 jn.getStep () 方法可以获得任意一个 step ,然后调用 getStatus () 方法就可以判断任意 step 的当前状态。
/
OSWorkflow 真灵活 >>
http://www.blogdriver.com/showBlog.do?diaryID=108339
   
比如年检流程, 未提交年检报告书 的状态其实有好几种情况:首次填写未提交、报告书被退回未提交、初审不通过未提交。把这几个状态分别定义为 UnCommit1 UnCommit2 UnCommit3 。在 提交 的动作那里判断条件时,用 BeanShell 写一个脚本:
 
String status = getStatus();
status.indexOf ("UnCommit") >= 0;
 
也就是说,只要当前状态字中含有 “UnCommit” 字样,就可以执行 提交 的动作。嘿嘿,噶灵活地。现在要把 BeanShell 的中文问题解决一下,再试试分支流程。
 
OSWorkflow 奋斗一天 >>
http://www.blogdriver.com/showBlog.do?diaryID=107566
   
解决了两个问题:
 
不能根据 Hibernate 映射文件生成数据库 —— SchemaExport 生成数据库的时候, DOM4J 报错 “org.xml.sax.driver” 系统属性没有设置。查看了一下,在以往的任何一个项目中,这个系统属性都没有设置,但都可以生成数据库,不知道为什么在这里就不行了。自己动手给 SchemaExport 做了个包装,先设置 org.xml.sax.driver 系统属性值为 org.apache.xerces.parsers.SAXParser ,再调用 SchemaExport
 
执行速度巨慢 —— 是因为没有开启工作流工厂的缓存。在 osworkflow.xml 定义文件中加上 <property key="cache" value="true" /> ,速度明显提高。第一次加载工作流定义时, XML 解析和验证( validation )费时较多,改用 JDOM 解析( CrimsonDOMAdapter ),有所加快。
 
Hibernate 持久化时, OSWorkflow 要求 client 提供 SessionFactory ,然后自主控制 session transaction 。我计划将它纳入 G-Roller 框架,直接向 HibernateWorkflowStore 提供 SessionAdapter ,仍然用 G-Roller 统一管理 session transaction 。首先要把核心部分的单元测试补起来, hani 这个家伙从来不爱写测试,偶尔写几个也是 sample 一样的,估计是 OpenSymphony 公司给他下的任务 —— 就像我的文档任务一样。
 
 
 
OSWorkFlow又爱又恨
http://www.blogdriver.com/showBlog.do?diaryID=182514
   OSWorkFlow 我研究已有一段时间了,并已在一些项目中开始使用了。 OSWorkFlow 流程定义灵活清晰,工作流引擎支持多种持久方式( MemoryStore ,SerializableStore, JDBCStore, OfbizStore, and EJBStore,HibernateStore 等),具有极强的可扩展性。 OSWorkFlow 强大的脚本支持( BeanShell BSF 等),多样化的 function,function 可以直接使用普通 java 类函数、 Xwork Action JMS EJB 、脚本等。使用 propertyset 动态存取类型化的数据,使用成熟的 Quartz 实现工作流任务定时调度。最新版本 OSWorkFlow2.7 也添加了 Spring 框架的支持,设计器也有了很好的改善。
     可是, OSWorkFlow 的学习资料太少,只有 opensymphony 的一些概论介绍和简单的例子,连一个完善的实际项目使用都没有。代码的注释也是非常少,更不能接受的是只有部分的单元测试,若想在其基础上改进也困难,哎!设计器的代码更烂,好在 OSWorkFlow2.7 的设计器( Designer2.7 )的改进,总算是能在实际中使用。
  期待 OSworkflow 更好的完善、改进、发展 (http://www.opensymphony.com/osworkflow/)...............
 
 
 
OSWorkFlow概论:function(函数)
http://www.blogdriver.com/showBlog.do?diaryID=158730
function (函数),在 OSWorkFlow 中是用来定义(引用)并执行外部的商业逻辑和服务,实现 OSWorkFlow 与外部具体的应用之间交互。
function 有二种类型:
pre function(
预处理函数 ) post function (后处理函数)
pre function
在工作流的一个转变操作执行之前调用,例如:在执行 Action 的一个结果之前,设置这个结果将导致状态改变的 Owner
 <action id="0" name="
启动工作流 ">
      <results>
        <unconditional-result id="2" old-status="Finished" status="Queued" step="1" owner="${caller}">
          <pre-functions>
            <function name="set.caller" type="class">
              <arg name="class.name">com.opensymphony.workflow.util.Caller</arg>
            </function>
          </pre-functions>
        </unconditional-result>
      </results>
    </action>
post function 在工作流的一个转变操作执行完之后调用 : 例如在设备申请工作流中,部门经理审核步骤完成之后可以给申请的员工发 email 通知
等。

function
将被应用在 step Action Result
具体见 workflow_2_7.dtd
..
<!ELEMENT step (meta*, pre-functions?, external-permissions?, actions?, post-functions?)>
<!ELEMENT action (meta*, restrict-to? , validators?, pre-functions?, results, post-functions?)>
<!ELEMENT result (conditions, validators?, pre-functions?, post-functions?)>
..
 
function action 级别的应用:在执行某一步骤的的 Action 时,它会首先执行当前 Action 级别的 pre-function ,再去寻找 Action 里的 result
result 执行完成之后再调用 Action 级别的 post-function ,于是 Action 的执行结束。
如下图:

function
result 级别的应用 : 类似 action 级别
function
step 级别的应用 : 上一个步骤执行结束,运转到当前步骤,执行当前步骤的 pre-function 。当前步骤执行完成,在未运转到下一步骤
之前,执行 post-function
如下图:
 
 
 
注意: OSWorkFlow 里的 Action 和我们具体业务操作中的 Action (比如: xwork 中的 Action )的区别 :
          OSWorkFlow Action 是个更粗粒度的操作,它是指 OSWorkFlow 某一步骤可以执行的操作。在我们经常用的 action (比如: xwork 中的 Action ),是业务相关的一个操作,在 OSWorkFlow 相当于一个具体的 function
 
 
opensymphony 的开源项目 >>
   
很多好用的 openSource.webwork 就来源于这个组织!
opensymphony 也是一個 opensource 案的組織 , 推出了幾個膾炙人口的專案
http://wiki.opensymphony.com/space/OpenSymphonyComponents
 
  OSCore : 一些開發 j2ee 基礎的核心程式
OSUser : 人員管理的程式 , 主要處理 authetication
OSAccess : 存取控管的程式 , 主要處理 authorization
WebWork : 方便簡單的 MVC Framework
WebWork2: 顧名思義 , WebWork 第二版
XWork : Model2x MVC Framework.
SiteMesh : View 端的網頁處理器 ( 許多書籍推薦 )
PropertySet : 管理 properties 的好工具
OSWorkflow : WorkFlow engine 工作流引擎
OSCache : J2EE Cachin g 機制
 
 
BeanShell 的中文问题 >>
http://www.blogdriver.com/showBlog.do?diaryID=108228
   
XML 文件中写这么一段 BeanShell
 
String status = getStatus();       // 通过某种途径得到状态
System.out.println (status);       // 这里输出 未提交
System.out.println (status.indexOf(" 未提交 "));
 
最后一句就得到了 -1
 
System.out.println (" 未提交 ");
 
这句直接就得到了乱码。这到底是 XML 解析器 的问题呢还是 BeanShell 的问题呢?搞不拎清 …… 再试一下去。
 
试过了,在 Java 里面写:
 
  Interpreter i = new Interpreter();
  i.setClassLoader(getClass().getClassLoader());
  i.eval("System.out.println(/"
中文 /");");
 
输出乱码。果然是 BeanShell 的问题。
原来是 BeanShell 版本的问题, 1.2 就不支持中文,换成 2.0 就搞定了。现在我的工作流配置是这个样子:
      <actions>
        <action id="1201" name="
认领年检报告书 ">
          <restrict-to>
            <conditions type="AND">
              <condition type="beanshell" name="bsh.condition">
                <arg name="script">
                 com.opensymphony.workflow.util.beanshell.WorkflowStatus.isStatus(transientVars, "
未认领 ");
                </arg>        
              </condition>
            </conditions>
          </restrict-to>
          <results>
            <unconditional-result old-status="Finished" status="
认领未初审 " step="12" owner="${ycheckId}" />
          </results>
        </action>
好漂亮哦!
 
 
OsWorkFlow配合Hibernate攻略>>
http://www.blogdriver.com/showBlog.do?diaryID=178570
2.  解压后 , osworkflow-2.7.0-example.war 解压到一个目录,我一般起 web ,方便对里面进行修改
3.  部署到 Tomcat5
4.  试验一下 , 这个时候 , 默认的 MemoryWorkflowStore 应该已经工作正常了
5.  开始向 HibernateWorkflowStore 转移 , 先修改 WEB-INF/classes/ 目录下的 osworkflow.xml , 改为
     <persistence class="com.opensymphony.workflow.spi.hibernate.HibernateWorkflowStore">
     </persistence>
6.  把一个 Hibernate.cfg.xml 加到 WEB-INF/classes/ 下面 , 我用的数据库是 mysql .
 <property name="hibernate.hbm2ddl.auto">update</property> 这句是为了帮你创建数据库表的 , 跑起来后最好去掉 , 不去也没关系 .

 <?xml version='1.0' encoding='utf-8'?>
 <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
 <hibernate-configuration>
 <session-factory>
  <!-- properties -->
  <property name="connection.driver_class">org.gjt.mm.mysql.Driver</property>
  <property name="connection.url">jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf-8</property>
  <property name="connection.username">root</property>
  <property name="connection.password">123456</property>
  <property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
  <property name="show_sql">true</property>
  <property name="use_outer_join">true</property>
  <property name="connection.pool_size">10</property>
  <property name="statement_cache.size">25</property>
  <property name="hibernate.hbm2ddl.auto">update</property>
  <mapping resource="com/opensymphony/workflow/spi/hibernate/HibernateCurrentStep.hbm.xml"></mapping>
  <mapping resource="com/opensymphony/workflow/spi/hibernate/HibernateHistoryStep.hbm.xml"></mapping>
  <mapping resource="com/opensymphony/workflow/spi/hibernate/HibernateWorkflowEntry.hbm.xml"></mapping>
  <mapping resource="com/opensymphony/module/propertyset/hibernate/PropertySetItemImpl.hbm.xml"></mapping>
 </session-factory>
 </hibernate-configuration>
7.  hibernate jar hibernate 所有要到的 jar, 统统加到 WEB-INF/lib/
8.  最后一步 , 修改源程序 .
  OsWorkFlow
主要作者 Hani , 认为生成 SessionFactory 的责任并不是 OsWorkFlow 的事情 , 坚持应该是用户 , 或者是服务器生成后 , 传给 HibernateWorkflowStore . 他可能是 Spring 的思想太深了吧 . 我也赶紧开始学习了 . 但是如果这样的话 , 最好加个说明 , 说这个产品的 Hibernate 特性还必须配合 Spring 才行 , 那么我再装一个 . 既然他没有说明 , 我又暂时还打算用 spring, 而我又不想改 web 层任何 代码 , 那么我就只好修改他的源程序 , HibernateWorkflowStore 里面生成一个独一无二的 SessionFactory .
  
  
修改一是添加下面在开头 :
  private static SessionFactory sessionFactory;
  //~ Constructors ///
  static{
   try {
     sessionFactory = new Configuration().configure().buildSessionFactory();
   } catch (HibernateException ex) {
      throw new RuntimeException("Configuration problem: " + ex.getMessage(), ex);
    }
 
  }
   二是在 init
   sessionFactory = (SessionFactory) props.get("sessionFactory"); 注释
   编译 , 生成 class, 放到 osworkflow-2.7.0.jar, 取代原来的 HibernateWorkflowStore.class , 重启服务器 ,OK
 
 
Shark 第一印象 >>- >> from GIGIX
  
试了一下 Enhydra Shark 工作流引擎,暂时还不知道如何编程使用,只有一些肤浅的印象。
 
庞大 —— OSWorkflow Werkflow 都大了许多,概念非常完整,一时间还很难完全理解这些概念。对于 OSWorkflow Werkflow 这种轻量级工作流来说,要管理的唯一目标就是流程实例( process instance ),操纵流程实例的状态变迁,至于如何使用流程实例、状态如何发展,都在工作流引擎之外。 Shark 管理的目标要宽泛得多,比如有 User UserGroup 的概念,用户必须有此角色(即 group )才能涉足此流程。不知道这会不会和统一用户管理平台冲突。
 
标准 —— 完全符合 WfMC 参考模型,并且没有任何额外扩展,采用 XPDL 作为工作流定义语言。标准是好事,但是对于一些比较特殊的流程,我担心它的扩展能力。比如电子政务中经常会出现一种 无序流程 (只要领导插手,就可以随便到任何位置), WfMC 是否能支持呢?另外, Enhydra 提供 JaWE 编辑器,可能是最好的 XPDL 可视化编辑器。
 
支持多语言插件 —— 对于需要自动执行的流程, Shark 允许插入多种语言的运行单元,包括 Java JavaScript BeanShell Python 等等,相信提供对 Groovy 的支持也会很简单。我们自己的工作流不支持自动执行, OSWorkflow 只支持简单的 BeanShell (语句直接写在配置文件中)。
 
持久化 —— 默认的持久化方式是 DODS ,这是 Enhydra 自己做的一个 O/R mapping 。原来用的数据库是 HSQL ,我今天尝试迁移到 MySQL 还没有成功,因此也不知道这个持久化机制究竟如何。另外还提供 LDAP 的持久化,持久化方式的移植也不知道是否困难。我相信 O/R mapping 基础上移植不会太难。
 
服务接口 —— 可以作为应用程序的一部分在代码级集成,也可以作为外部服务通过 RPC 集成。 Shark 很重视 CORBA 接口,对于异构环境的集成应该是很有帮助的。这里也有一点性能上的顾虑:应用内集成时,工作流引擎和工作流实例会不会带来太大的性能开销?毕竟它给我一种重量级的感觉。
 
明天如果有空就继续尝试,先把应用内集成搞明白,那么 RPC 集成也就简单了
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值