??xml version="1.0" encoding="utf-8" standalone="yes"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="example_5">
<start-state name="开?>
<event type="node-leave">
<action name="action1"></action>
</event>
<transition name="tr1" to="工作?></transition>
<transition name="tr2" to="求学?></transition>
</start-state>
<state name="工作?>
<event type="node-enter">
<action name="工作" class="com.wide.example5.WorkAction"></action>
</event>
<transition name="" to="l成正果"></transition>
</state>
<state name="求学?>
<event type="node-enter">
<action name="学习" class="com.wide.example5.StudyAction"></action>
</event>
<transition name="" to="l成正果"></transition>
</state>
<end-state name="l成正果">
<event type="node-enter">
<action name="圆满" class="com.wide.example5.EndAction"></action>
</event>
</end-state>
</process-definition>
q是一个比较简单的jbpm程模板Q通过q几天的学习Q基本上是看别h的事子)发现jbpm原来q么的复杂的Q好多东西想C来,特别是一个同行ȝ出的例子Q非常简z的描述了各个小功能炏V以下也是一个很单的jpdl模板Q清楚的描述了note与state的区别。jbpm提供了好几种不同的节炏V?br>
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="example_7">
<start-state name="start">
<transition name="tr1" to="state"></transition>
<transition name="tr2" to="node"></transition>
</start-state>
<state name="state"> <!-- 只有{收signal才执?nbsp;-->
<transition name="" to="end"></transition>
</state>
<node name="node"> <!-- 直接执行Q当{到这节点Ӟ马上执行transition -->
<transition name="" to="end"></transition>
</node>
<end-state name="end"></end-state>
</process-definition>
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;
import java.io.*;
public class Execute {
static JbpmConfiguration cfg=JbpmConfiguration.getInstance();
/**
* 把流E部|到数据?br> * @param file
*/
public void deploy(String file){
JbpmContext jc=null;
try{
FileInputStream fis = new FileInputStream("src/proc2.xml");
ProcessDefinition pd=ProcessDefinition.parseXmlInputStream(fis);
jc=cfg.createJbpmContext();
jc.deployProcessDefinition(pd);
}catch(Exception e){
e.printStackTrace();
}finally{
jc.close();
}
}
public static void main(String args[])throws Exception {
Execute e=new Execute();
//e.deploy("src/proc2");
JbpmContext jc=cfg.createJbpmContext();
GraphSession gs=jc.getGraphSession();
ProcessDefinition pd=gs.findLatestProcessDefinition("example_5");
ProcessInstance pi=new ProcessInstance(pd);
Token token=pi.getRootToken();
System.out.println("token-->"+token.getNode().getName());
token.signal("tr1");
System.out.println("tr1-->"+token.getNode().getName());
token.signal();
System.out.println("kk->"+token.getNode().getName());
System.out.println("是否已结?>"+pi.hasEnded());
jc.save(pi);
}
}
该class只需要实现ActionHandler接口p了,具体有啥用我C没搞懂:Q我一直努力着?
]]>
public void setUp(){
//cfg.createSchema(); //重徏jbpm存储?.
}
以下是一个部|的Ҏ
assertNotNull("JbpmConfiguration is null",cfg);
FileInputStream fis = new FileInputStream("src/proc1.xml");
ProcessDefinition pd=ProcessDefinition.parseXmlInputStream(fis);
assertNotNull("definition should not be null",pd);
JbpmContext jc=cfg.createJbpmContext();
try{
jc.deployProcessDefinition(pd);
}finally{
jc.close();
}
}
JbpmContext jbpmContext = cfg.createJbpmContext() ;
try {
GraphSession graphSession = jbpmContext.getGraphSession();
ProcessDefinition processDefinition =
graphSession.findLatestProcessDefinition("pro1");
ProcessInstance processInstance =
new ProcessInstance(processDefinition);
Token token = processInstance.getRootToken();
assertEquals("start", token.getNode().getName());
// Let's start the process execution
token.signal();
assertEquals("state1", token.getNode().getName());
jbpmContext.save(processInstance);
} finally {
// Tear down the pojo persistence context.
jbpmContext.close();
}
}
JbpmContext jbpmContext = cfg.createJbpmContext() ;
try {
GraphSession graphSession = jbpmContext.getGraphSession();
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition("pro1");
List processInstances = graphSession.findProcessInstances(processDefinition.getId());
ProcessInstance processInstance = (ProcessInstance) processInstances.get(0);
// this.assertEquals("message",(String)(processInstance.getContextInstance().getVariable("message")));
processInstance.signal();
assertTrue(processInstance.hasEnded());
jbpmContext.save(processInstance);
} finally {
jbpmContext.close();
}
}
实际上,上面的几D代码中写来写去p几句话吧。加载流E,生成实例Q然后签收执行?br>明天l箋......
]]>
1、在lib目录下徏立oracle目录Q把oracle 9.1的jdbc驱动class12.jar拯q来?br>2、在src/resources目录下徏立oracle目录Q把hsqldb目录入的两个文g拯q来?br>3、修改create.db.hibernate.properties
4、在src目录入copy build.deploy.xml文g到src目录Qƈ改名为build.deploy.oracle.xmlQ然后修Ҏ件的create.db target。内容如?/span>
工作定义?/font>
1.1 工作定义语法检?br /> 1.2 工作定义有效性检查?br /> 1.3 程可视化徏模?br /> 1.4 l织机构数据的引用?br /> 1.5 支持ȝq程定义
1.6 工作数据定义 ?br /> 1.7 囑Ş打印工作过E定义图?br /> 1.8 以xml格式保存q程定义文g
1.9 直接Ҏ板库讉K操作
1.10 xmlq程定义文g打开~辑
工作模板库
2.1 工作模板的导入和导出?br /> 2.2 工作模板版本控制?br /> 2.3 工作模板复制?br /> 2.4 工作模板所有者定?br /> 2.5 工作模板状态(草稿、发布、过Ӟ
2.6 工作模板有效时?/font>
实例初始化?/font>
3.1 通过Email启动
3.2 通过文本文gQText FilesQ启?br /> 3.3 通过XML消息启动
3.4 旉事g启动
3.5 手工启动
3.6 q程调用启动
工作模式?/font>
4.1 序QSequenceQ?br /> 4.2 q行分支QAND-splitQ?br /> 4.3 q行汇聚QAND-joinQ?br /> 4.4 条g分支QConditional routingQ、互斥选择QExclusive Choice、XOR
4.5 单汇聚(XOR-joinQ?br /> 4.6 多重选择QOR-split、Conditional routingQ?br /> 4.7 多重汇聚Q?Q?
4.8 部分汇聚QPartial joinQMI
4.9 取消zd
4.10 取消实例
4.11 同步/异步子过E?br />
工作Q务分配?/font>
5.1 d分配的两U模式(拉和推)
5.2 d队列Q拉模式Q?br /> 5.3 按工作量分配dQ推模式Q?br /> 5.4 分配dl所有h员(部门、角艌Ӏ工作组Q?br /> 5.5 按h员优先数分配dQ适合Z角色d分配Q?br /> 5.6 先来先做QFCFAQ,Q务队列中最早创建的d分配l最先提出执行Q务请求的人员
5.7 分配dl指定h?br /> 5.8 推模式下的Q务分配异常处理(d分配异常Ӟ通知模板所有者或工作管理员Q?br /> 5.9 d重分配(Q务分配给其他用户、指定角色中的用戗角Ԍ
5.10 d替代者,׃h员指定(交办、代办)
工作动作?/font>
5.11 接收dQ状态{换)accept
5.12 退Ӟ回退C一节点Q)decline
5.13 执行d
5.14 完成dQ状态{换)
5.15 反向回传/抽单/召回QProcess RollbackQ?br /> 5.16 分配dl指定角?br /> 5.17 分配dl指定h?br /> 5.18 使用路由表分配Q务?br /> 5.19 取消d分配
5.20 创徏子过E(Q务节点用子过E代替?Q?br /> 5.21 讄d优先U(动态修改工作流zd优先U)
5.22 讄d说明
5.23 讄d期限Q设|之时v旉Dc指定时间点Q?br /> 5.24 取消d
5.25 挂vQ暂停)d
5.26 l止d
5.27 启动工作实?br /> 5.28 挂vQ暂停)工作实?br /> 5.29 取消工作实?br /> 5.30 l止工作实?br /> 5.31 讄工作实例说?br /> 5.32 讄工作实例变量(工作实例变量赋|Q可以作为工作流异常处理的一U方?/font>
工作活动\由?/font>
6.1 Z角色路由QQ务分配给角色Q职务发生变化,程设计不需变化Q?br /> 6.2 Z关系路由Q根据相对职务关p\由)
6.3 讑֮型(Ad hocQ\由(由办理h员指定下一节点办理人)Ҏ程处理内容Q由办理Z指定人员中选择合适的下一步执行h?/font>
工作组l机构?/font>
7.1 支持LDAP目录服务
7.2 支持l(GroupQ?br /> 7.3 循环l?br /> 7.4 权重l?br /> 7.5 工作职务l(相同职务的hl成一个组Q?br /> 7.6 支持动态定义组Q流E执行过E中定义的组Q?br /> 7.7 多重角色理Q一人数职)
7.8 相对职务关系
7.9 l织图拥有hQ组l结构的分l护Q?/font>
工作时间管理?/font>
8.1 非工作日讑֮
8.2 旉事情启动工作实例(指定旉炏V时间间隔、周期时_
8.3 d挂v恢复Q指定时间点、时间间隔)
8.4 q程实例挂v恢复Q指定时间点、时间间隔)
8.5 d时通知
8.6 工作超旉知
8.7 pȝ旉
工作系l通知
9.1 以邮件方式通知工作时
9.2 可自订通知邮gQ新d通知Q?br /> 9.3 d式邮仉知Q相对Web-based被动方式Q?br /> 9.4 工作异帔R知
9.4 d取消通知
9.5 工作取消通知
工作异常处理?/font>
10.1 异常的分c?br /> 10.2 不同的异常处理方?br /> 10.3 异常的报告、通知机制
10.4 异常恢复E序的预定义
工作接口需求?/font>
11.1 与Email服务器接口(JMSQ?br /> 11.2 与文件系l接口(如NTFS、unix-FSQ?br /> 11.3 与ERP、CRM、HR、SCM{系l接?br /> 11.4 与文档管理系l系l接?br /> 11.5 与其它工作流pȝ接口
11.6 与其它应用系l接?/font>
工作系l需求?/font>
12.1 支持多个操作pȝQ包括windows、AIX、Solaris、HP-Unix、Linux{?br /> 12.2 支持多种数据库,包括MS SQL server、Oracle、DB2、MySQL{?br /> 12.3 支持多种应用服务器,包括weblogic、websphere、Jboss、Apusic、Tomcat{?br /> 12.4 完备的系l日?br /> 12.5 可处理大量流E?br /> 12.6 从失败(或错误)中恢复系l(自动、手动)、系l(应用Q数据备?br /> 12.7 支持q发处理
工作系l管理?/font>
13.1 囑Ş化流E监?br /> 13.2 程实例动态修改(修改未执行的q程步骤Q?br /> 13.3 工作负荷量显C?br /> 13.4 工作统计(程模板、流E实例、Q务统计)
13.5 自定义统计报?br /> 13.6 l计数据囑Ş化显C?br /> 13.7 临时更改收g?br /> 13.8 工作重?br /> 13.9 程实例挂v/恢复
13.10 zd实例挂v/恢复
13.11 代理未来工作
13.12 可指定代理期?br /> 13.13 工作实例超时统?br /> 13.14 单一步骤时l计
13.15 可传回子程l计数据
13.16 服务器定时清?/font>
工作客L
14.1 B/Sl构客户端界?br /> 14.2 览器端的数字认证功?br /> 14.3 单点d
14.4 按重要程度排列Q务清?br /> 14.5 用户查看程执行状?br /> 14.6 我的d和共享Q务队列(按角色分c)
14.7 从共享Q务队列中选取d
14.8 用户指定/取消代理?br /> 14.9 昄已被代理的工?/font>
工作数据?/font>
15.1 基本数据cdQ整型、符点型、字W型、日期型、布型Q?br /> 15.2 复合数据cdQ数l)
15.3 XML数据定义
15.4 旉数据Q三U类型:旉炏V时间间隔、周期时_
15.5 附gQword、excel{)文g夹的概念QFolderQ?br /> 15.6 附g的检?出?
15.7 变量作用域(全局变量、过E变量)
15.8 数据的访问控Ӟd、读、不可见Q?br /> 15.9 数据集合QData SetQ(由多个不同类型数据或数据子集合所构成Q?br /> 15.10 数据的表玎ͼ表单Q?br /> 15.11 子表单(sub-formQ?br />
x看,自己实现的太了Q!Q只做到了皮毛而已!需l箋努力
工作系l功能特性描q?/span>
~写Q?/span>
jerry
创徏日期Q?/span>
2005-05-18
最后更斎ͼ
2005-05-20
版次Q?/span>
1.0
1.
程操作
程在流转过E中需要确定的Z一环节以及该环节的相应的参与?/span>
(
人或应用E序
)
Q所有的程操作均是围绕q两斚wq行?/span>
1.1.
{收
对事进行签收表明该程步骤q行生效阶段Q说明当前h员已事从待办状态切换ؓ了在办状态?/span>
1.2.
直?/span>
(
直流
)
直流为流E操作中最为简单的一U操作,直流为当前环节往下仅有一个环节,不存在分支的{Q在直流q程中可定的是程下一环节Q不可确定的是执行此环节的h?/span> ( 需要系l根据流E设计时配置的环节参与角色获取具有相x限的人员Q根据配|的是否需要选择人员来决定是否显C选h界面 ) ?/span>
1.3.
分?/span>
(
分流
)
分流在流E操作中也很常见Q分ؓ当前环节往下具有一个以上的环节可供选择Q即存在分支的流转,在此U情况下往往需要提供选择环节的页面以供用L定需要发往哪个环节?/span>
1.4.
q流
q流为当前环节往下具有一个以上的环节可供选择Q即存在分支的流转,但ƈ不需要用户选择往哪个环节的一U流转操作,在ƈ的情况下系l将自动往所有的分支环节{Qƈ{待所有分支环节办理完毕后汇总至他们共同的下一环节?/span>
1.5.
条g{
条g{为根据流E设计时所~写的脚本由pȝ计算出结果ƈ军_程的下一环节或下一环节的参与者。D例来_当前甌事项金额大于 10 万的时候至l理审批Q而大?/span> 50 万的时候则需递交臛_ȝ理审扏V?/span>
1.6.
退?/span>
审批人员收到甌事项后发现申h件不W或资料不齐{时需要退回当前申请事至甌人或上一环节受理人,q种程操作通常UCؓ退回?/span>
1.7.
取回
当审批h员发现申请事发送给了一个不合适的办理人员Ӟ如该办理人员未{收该事,则审批h员可此甌事项取回Q避免不必要的麻烦?/span>
1.8.
挂v
׃甌事项的资料不W或其他原因需要将当前甌事项q行暂停办理Q挂起当前流E,当需要恢复的时候则恢复该流El执行?/span>
1.9.
l止
(
撤销甌
)
׃甌事项的不合理或申请h员需要撤销该事的甌Ӟ可对该流E进行终止或撤销甌操作?/span>
1.10.
会签
甌事项需要几个h员按序的进行审批,事项按序依次发送给相应的h员进行事的审批。D例来_事项需要进行会{,选择人员分别为张三、李四、王五,那么张三首先接收到该事项Q张三填写意见后q行发送,pȝ自动发送至李四q行处理Q李四处理完毕后pȝ自动发送至王五Q王五处理完毕后q入实现的下一处理环节处理?/span>
1.11.
催办
事项审批q程中的审批人员如觉得该事项在某一个审批h员处停留旉太长的话可对其进行催促,以提醒其q速办理该事项Q在程操作上称为催办?/span>
1.12.
竞争办理
竞争办理的概念ؓ当两个用户都收到某事ҎQ谁先签收了该事则对该事项q行办理Q同时该事项也将从另一用户的待办列表中U除?/span>
1.13.
联审
联审为流E操作中较复杂的一U,事项发送后发送至当前环节的下面所有环节,q时的环节通常׃个子程构成Q在各自的子程执行完毕后统一回至LE的下一环节中,此种{q程UCؓ联审?/span>
1.14. 跌{
审批人员在进行事审ҎQ觉得该事项不需要经q流E图上所C意的其下的环节而可直接跌{C面的其他L一个环节进行流转?/span>
如审批h员觉得不需要提交至U长审批以及处长审批Q则可直接通过跌{操作事直接送至办公室环节进行办理?/span>
1.15.
传阅
审批人员在进行事审ҎQ觉得需要将该事传送给相关人员q行查看Q此{q程UCؓ传阅Q相关h员在接收到此事项后只可查看不可进行审扏V?/span>
1.16.
传阅办理
传阅办理与传阅的不同之处在于接收到此事项的h员可选择Ҏ事项q行办理或不办理Q而事的{q不{待此传阅办理过E的l束?/span>
1.17.
意见补签
事项的审批h员在事项已经发送至后箋环节办理的过E中均可q行意见的补{,此操作称为意见补{?/span>
2.
程理
2.1.
调度
在流E执行的q程中根据流E的执行状态等{可对该程事项q行调度Q将事项调度至相应的环节中?/span>
2.2.
监控
ҎE事进行监控,包括查看程的执行过E?/span> ( 最好是可视化的囑Ş表示 ) 、流E执行过E中的相关信?/span> ( 如签收h、签收时间、办理时间等 ) ?/span>
2.3.
查询
Ҏ程事项的关键字ҎE事进行简单或l合的查询?/span>
2.4.
l计分析
Ҏ询所得的程事项q行l计分析Q主要ؓ分析某类事项的办l率、效率、在办g、已办结件、已归档件等{?/span>
3.
程列表
3.1.
待办列表
在待办列表中列出发送至当前用户的所有事,包括事项的一些基本信?/span> ( 标题Q时间等{?/span> ) Q用户通过此处q行事项的签收工作?/span>
3.2.
已办列表
在已办列表中列出l过当前用户办理但目前尚未办l归档的所有事,用户可通过此对q些事项的办理状况进行监控,同时也可对事进行催办操作?/span>
3.3.
已办l列?/span>
在已办结列表中列出经q当前用户办理ƈ已办l归档的所有事,用户可通过此查看事的整个办理q程以及办理l果?/span>
4.
与应用的接口
4.1.
l织机构的接?/span>
在事Ҏ转过E中需要确定下一环节的参与者,此时如配|了此环节需q行选h操作Q此旉要调用应用的l织机构接口以提供选h界面供用户选择下一环节的参与者,接口中需提供按角色获取h员以及根据h员组装出其相应的l织机构树?/span>
4.2.
角色的接?/span>
在流E设计时需配置相应环节的参与角Ԍ此时需调用应用提供的角色接口,接口中需提供获取该流E事类型的角色、创程事项cd的角色的功能Q或者也可以采用在设计阶D不调用应用接口Q当程部v臛_用时同时创徏所需的角艌Ӏ?/span>
4.3.
表单的接?/span>
表单使得程pȝ有了实际的应用意义,表单作ؓ{q程中的载体Q与程pȝ的接口至关重要,涉及到表单的存储方式Q表单数据的获取方式Q流E环节中表单的挂接,程信息与表单信息构成的相关数据表?/span>
<workflow>
<initial-actions>
<action id="0" name="开?>
<pre-functions>
<functions type="class">
<arg name="class.name">com.opensymphony.workflow.util.Caller</arg>
</functions>
</pre-functions>
<results>
<unconditional-result old-status="Finished" status="Queued" step="1" owner="${caller}" />
</results>
</action>
</initial-actions>
<steps>
<step id="1" name="送假?>
<actions>
<action id="1" name="送出">
<restrict-to>
<conditions>
<condition type="class">
<arg name="class.name">
com.opensymphony.workflow.util.AllowOwnerOnlyCondition
</arg>
</condition>
</conditions>
</restrict-to>
<pre-functions>
<function type="class">
<arg name="class.name">com.opensymphony.workflow.util.Caller</arg>
</function>
</pre-functions>
<results>
<unconditional-result old-status="Finished" status="Queued" step="2" owner="${caller}"/>
</results>
</action>
</actions>
</step>
<step id="2" name="送假?>
<actions>
<action id="2" name="批准">
<pre-functions>
<function type="class">
<arg name="class.name">com.opensymphony.workflow.util.Caller</arg>
</function>
</pre-functions>
<results>
<unconditional-result old-status="finished" status="Queued" step="3" owner="${caller}"/>
</results>
</action>
<action id="3" name="驛_">
<pre-functions>
<function type="class">
<arg name="class.name">com.opensymphony.workflow.util.Caller</arg>
</function>
</pre-functions>
<results>
<unconditional-result old-status="finished" status="Queued" step="1" owner="${caller}"/>
</results>
</action>
</actions>
</step>
<step id="3" name="停止" />
</steps>
</workflow>
q是请假单的W二个演变,d?
<restrict-to>
<conditions>
<condition type="class">
<arg name="class.name">
com.opensymphony.workflow.util.AllowOwnerOnlyCondition
</arg>
</condition>
</conditions>
</restrict-to>
q个配置。这D配|就是用来限定下一步的执行人必Lq一步的发v人?br />
osworkflow限制的用法有Q?br />事實上OSWorkflow 2.7版提供了以下四種限制條g?br />
<property key="history.table" value="OS_HISTORYSTEP"/>
<property key="current.table" value="OS_CURRENTSTEP"/>
<property key="historyPrev.table" value="OS_HISTORYSTEP_PREV"/>
<property key="currentPrev.table" value="OS_CURRENTSTEP_PREV"/>
<property key="step.id" value="ID"/>
<property key="step.entryId" value="ENTRY_ID"/>
<property key="step.stepId" value="STEP_ID"/>
<property key="step.actionId" value="ACTION_ID"/>
<property key="step.owner" value="OWNER"/>
<property key="step.caller" value="CALLER"/>
<property key="step.startDate" value="START_DATE"/>
<property key="step.finishDate" value="FINISH_DATE"/>
<property key="step.dueDate" value="DUE_DATE"/>
<property key="step.status" value="STATUS"/>
<property key="step.previousId" value="PREVIOUS_ID"/>
</persistence>
<factory class="com.opensymphony.workflow.loader.XMLWorkflowFactory">
<property key="resource" value="workflows.xml"/>
</factory>
</osworkflow>
propertyset.xml文g格式如下Q?br /><?xml version="1.0" encoding="UTF-8"?>
<propertysets>
<propertyset name="jdbc"
class="com.opensymphony.module.propertyset.database.JDBCPropertySet">
<arg name="datasource" value="java:comp/env/jdbc/DefaultDS"/>
<arg name="table.name" value="OS_PROPERTYENTRY"/>
<arg name="col.globalKey" value="GLOBAL_KEY"/>
<arg name="col.itemKey" value="ITEM_KEY"/>
<arg name="col.itemType" value="ITEM_TYPE"/>
<arg name="col.string" value="STRING_VALUE"/>
<arg name="col.date" value="DATE_VALUE"/>
<arg name="col.data" value="DATA_VALUE"/>
<arg name="col.float" value="FLOAT_VALUE"/>
<arg name="col.number" value="NUMBER_VALUE"/>
</propertyset>
</propertysets>
workflows.xml文g格式如下Q?br />
<workflows>
<workflow name="leave" type="resource" location="leave.xml"/>
</workflows>
osuser.xml文g格式如下Q?br /><?xml version="1.0" encoding="UTF-8"?>
<opensymphony-user>
<provider class="com.opensymphony.user.provider.jdbc.JDBCAccessProvider">
<property name="user.table">os_user</property>
<property name="group.table">os_group</property>
<property name="membership.table">os_membership</property>
<property name="user.name" >username</property>
<property name="user.password">passwordhash</property>
<property name="group.name">groupname</property>
<property name="membership.userName" >username</property>
<property name="membership.groupName">groupname</property>
<property name="datasource">java:comp/env/jdbc/DefaultDS</property>
</provider>
<provider class="com.opensymphony.user.provider.jdbc.JDBCCredentialsProvider">
<property name="user.table">os_user</property>
<property name="group.table">os_group</property>
<property name="membership.table">os_membership</property>
<property name="user.name" >username</property>
<property name="user.password">passwordhash</property>
<property name="group.name">groupname</property>
<property name="membership.userName" >username</property>
<property name="membership.groupName">groupname</property>
<property name="datasource">java:comp/env/jdbc/DefaultDS</property>
</provider>
<provider class="com.opensymphony.user.provider.jdbc.JDBCProfileProvider">
<property name="user.table">os_user</property>
<property name="group.table">os_group</property>
<property name="membership.table">os_membership</property>
<property name="user.name" >username</property>
<property name="user.password">passwordhash</property>
<property name="group.name">groupname</property>
<property name="membership.userName" >username</property>
<property name="membership.groupName">groupname</property>
<property name="datasource">java:comp/env/jdbc/DefaultDS</property>
</provider>
<authenticator class="com.opensymphony.user.authenticator.SmartAuthenticator" />
</opensymphony-user>
请假列子的配|如下:
package com.pdw.wfbo;
import java.util.HashMap;
import java.util.Map;
import com.opensymphony.workflow.*;
import com.opensymphony.workflow.basic.BasicWorkflow;
import com.opensymphony.workflow.config.DefaultConfiguration;
public class LeaveWFBO {
/**
* 送出假单
* @param employee
* @return
*/
public long send(String employee) {
Workflow workflow=new BasicWorkflow("peidw");
DefaultConfiguration config=new DefaultConfiguration();
workflow.setConfiguration(config);
long workflowId=-1;
try {
workflowId=workflow.initialize("leave",0,null);//leave是workflows.xml里配|的工作名U?br /> workflow.doAction(workflowId,1,null);
}catch(Exception e) {
e.printStackTrace();
}
return workflowId;
}
/**
* 批假
* @param workflowId 工作编?br /> * @param actionId 工作~号Q? 准许Q? 驛_
*/
public void allow(long workflowId,int actionId) {
Workflow workflow=new BasicWorkflow("peidw");
DefaultConfiguration config=new DefaultConfiguration();
workflow.setConfiguration(config);
try {
System.out.println("actionId->"+actionId);
System.out.println("workflowId->"+workflowId);
workflow.doAction(workflowId,actionId,null);
}catch(Exception e) {
e.printStackTrace();
}
}
}
q是上面的这个例子的一个说?/div>
|
(史帝? 2005/6/6, hi.steven@gmail.com) |
![]() |
主要定义了用户对工作的操作Ҏ和用戯得工作流信息的方法。如doAction(long id, int actionId, Map inputs)Ҏ可以执行工作的Actionq生transactionQ用戯用getAvailableActions(long id, Map inputs)可以获得知道工作实例中W合条g的可以执行的Action?/p>
2.com.opensymphony.workflow.WorkflowContext 工作的Context接口?/p>
只有两个ҎQ其中getCaller()获得调用者,setRollbackOnly()可以回滚Action造成的transaction?/p>
setRollbackOnly()Ҏ非常重要Q可以在此方法中实现工作数据与业务数据的事务处理。由于工作流引擎流E数据与业务数据分离开理Q所以工作流数据与业务数据之间的事务处理往往比较困难Q甚x很多商业的工作流引擎都没有解册个问题,造成软g上的漏洞。可惜在BasicWorkflowContext中ƈ没有实现回滚时的事务处理Q但实现h应该不会很困难,在以后会单独考虑?/p>
3.com.opensymphony.workflow.spi.WorkflowEntry 工作实例的接口?/p>
定义了获得工作流实例信息的方法?/p>
4.com.opensymphony.workflow.config.Configuration 工作配|接口?/p>
获得osworkflw的配|信息和程的定义信息, osworkflow中的例子是使用此接口的默认实现。如果想让osworkflw与自qpȝ更好的整合,q个接口需要自己实现?/p>
5.com.opensymphony.workflow.loader.AbstractWorkflowFactory 程定义的解析器?/p>
osworkflow中提供了此抽象类?U实玎ͼ最常用的是XMLWorkflowFactoryQ可以对~写的工作流定义xml文gq行解析?/p>
6.com.opensymphony.workflow.spi.WorkflowStore 工作存储接口?/p>
实现此接口可以实现用多种途径保存工作信息,jdbc,hibernate,ejb,memory.........
AbstractWorkflowcLworkflow接口的最基本的实现?/p>
1.public int[] getAvailableActions(long id, Map inputs)ҎQ?/p>
q回当前可以执行的Ation?/p>
2. public void setConfiguration(Configuration configuration)ҎQ?/p>
讄工作配|方法?/p>
3.public Configuration getConfiguration()ҎQ?/p>
q回工作配|方法,如果没有获得配置信息Q初始化配置信息?/p>
4.public List getCurrentSteps(long id)Q?/p>
获得工作当前所在步骤?/p>
5.public int getEntryState(long id):
获得工作的状态?/p>
6.public List getHistorySteps(long id)
获得工作的历史步骤?/p>
7. public Properties getPersistenceProperties()
获得讄的持久化参数?/p>
8.public PropertySet getPropertySet(long id)
得到工作的PropertySetQ调用store中的Ҏ?/p>
9.public List getSecurityPermissions(long id)
得到工作当前Step的permissions?/p>
10.public WorkflowDescriptor getWorkflowDescriptor(String workflowName)
得到工作的定义?/p>
11.public String getWorkflowName(long id)
Ҏ工作实例返回工作流定义名?/p>
12. public String[] getWorkflowNames()
q回pȝ中配|的所有工作流的名字?/p>
13.public boolean canInitialize(String workflowName, int initialAction)Qpublic boolean canInitialize(String workflowName, int initialAction, Map inputs)Qprivate boolean canInitialize(String workflowName, int initialAction, Map transientVars, PropertySet ps) throws WorkflowException
判断指定的工作流初始化Action是不是可以执行?/p>
14.public boolean canModifyEntryState(long id, int newState)
判断工作是不是可以转换到指定状态?/p>
15.public void changeEntryState(long id, int newState) throws WorkflowException
转换工作状态?/p>
16.public void doAction(long id, int actionId, Map inputs) throws WorkflowException
执行Action?/p>
17.public void executeTriggerFunction(long id, int triggerId) throws WorkflowException
调用工作的Trigger Function
18.public long initialize(String workflowName, int initialAction, Map inputs) throws InvalidRoleException, InvalidInputException, WorkflowException
初始化一个新的流E实例。返回流E实例id?/p>
19.public List query(WorkflowQuery query)Qpublic List query(WorkflowExpressionQuery query)
查询程实例?/p>
20.public boolean removeWorkflowDescriptor(String workflowName) throws FactoryException
删除已经配置的工作流定义?/p>
21.public boolean saveWorkflowDescriptor(String workflowName, WorkflowDescriptor descriptor, boolean replace) throws FactoryException
保存工作定义?/p>
22.protected List getAvailableActionsForStep(WorkflowDescriptor wf, Step step, Map transientVars, PropertySet ps) throws WorkflowException
获得指定步骤的可用Actions?/p>
23.protected int[] getAvailableAutoActions(long id, Map inputs)
q回可执行的AutoActions?/p>
24.protected List getAvailableAutoActionsForStep(WorkflowDescriptor wf, Step step, Map transientVars, PropertySet ps) throws WorkflowException
q回指定Step中可执行的AutoActions?/p>
25.protected WorkflowStore getPersistence() throws StoreException
q回配置的store?/p>
26.protected void checkImplicitFinish(long id) throws WorkflowException
判断工作是不是q有可执行的ActionQ如果没有,完成此工作流实例?/p>
27.protected void completeEntry(long id, Collection currentSteps) throws StoreException
l束工作实例,是把改变流E实例的状态ƈ把当前的Steps都放入到历史表中。?/p>
28.protected boolean passesCondition(ConditionDescriptor conditionDesc, Map transientVars, PropertySet ps, int currentStepId) throws WorkflowException
29.protected boolean passesCondition(ConditionDescriptor conditionDesc, Map transientVars, PropertySet ps, int currentStepId) throws WorkflowExceptionQprotected boolean passesConditions(String conditionType, List conditions, Map transientVars, PropertySet ps, int currentStepId) throws WorkflowException
判断条g是不是符合?/p>
30.protected void populateTransientMap(WorkflowEntry entry, Map transientVars, List registers, Integer actionId, Collection currentSteps) throws WorkflowException
产生临时变量transientVarsQ包含contextQentryQstoreQdescriptorQactionIdQcurrentStepsQ以及定义的register和用L输入变量?/p>
31.protected void verifyInputs(WorkflowEntry entry, List validators, Map transientVars, PropertySet ps) throws WorkflowException
验证用户的输入?/p>
32.private boolean isActionAvailable(ActionDescriptor action, Map transientVars, PropertySet ps, int stepId) throws WorkflowException
判断Action是否可用?/p>
33.private Step getCurrentStep(WorkflowDescriptor wfDesc, int actionId, List currentSteps, Map transientVars, PropertySet ps) throws WorkflowException
获得Action所在Step?/p>
34.private boolean canInitialize(String workflowName, int initialAction, Map transientVars, PropertySet ps) throws WorkflowException
判断工作是不是可以实例化?/p>
35.private Step createNewCurrentStep(ResultDescriptor theResult, WorkflowEntry entry, WorkflowStore store, int actionId, Step currentStep, long[] previousIds, Map transientVars, PropertySet ps) throws WorkflowException
产生新的当前Step?/p>
36.private void executeFunction(FunctionDescriptor function, Map transientVars, PropertySet ps) throws WorkflowException
执行Function?/p>
37.private boolean transitionWorkflow(WorkflowEntry entry, List currentSteps, WorkflowStore store, WorkflowDescriptor wf, ActionDescriptor action, Map transientVars, Map inputs, PropertySet ps) throws WorkflowException
完成工作的transation?br />
4. public WorkflowStore getWorkflowStore() throws StoreException
获得工作初始化cR?br />
2. StatusQ某个Step的状态,每个Step可以有多个Status。比如上例中阅读Q等待提意见Q等待签字,{待交秘书处理,都是Step的状态。StepQStatus共同l成了工作流的状态,也就实现了FSM中的Status。Step的Status在OSWorkflow中就是一D|本,状态的判断其实是自定义的一D|本的比较Q非常灵zR?/p>
3. ActionQ造成工作状态{换的动作Q比如”阅L件“动作,造成了工作流状态从”领导审批+{待阅读"转换成“领导审批+{待提出意见”。由于工作流的状态是StepQStatusQ所以Action可以造成Stats的变化,也可以造成Step的变化?/p>
4. ResultQ工作流状态的转换Q也是Action造成的结果。也是FSM中的Transition。每个Action中至包含一个unconditional result和包?或多个conditional resultQResult的优先序?W一个符合条件的conditional result > 其他W合条g的conditional result > unconditional result?/p>
5.Split/Join:字面意思就可以解释。Split可以产生多个unconditional resultQ而Join可以判断多个Step的状态,如果都满x件的时候,Join产生一个unconditional result。可以用来实现其他工作流产品定义中的同步区的作用Q比如一个投标文件的评标q程Q分别要在技术方面和商务斚wҎ书进行评分,q样可以用Split工作流分开q入商务评标l和技术评标组分别q行评标Q当两个评标q程都完成后使用Join两个流E合qӞq对两个评标做的评分q行汇怅R?/p>
6.External FunctionsQ执行的功能和动作。Q何的工作引擎都要与实际的业务操作相l合QExternal Functions是OSWorkflow中执行业务操作的部分Q比如审ҎE中Q领导填写意见后领导的意见更新C务数据库中的q程。Functions有两U类型,pre step function和post step functionQ分别发生{Ud和发生{Ud执行。Functions可以被定义到Step中和Action中?/p>
7.Trigger FunctionsQ一U不是定义在Action中的FunctionQ依靠计划自动执行?/p>
8.ValidatorsQ用来检验用戯入是否符合条Ӟ只有W合条gQAction对应的{UL能执行,如果不符合条Ӟq回InvalidInputException异常?br />
转于:ch(耐心)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE workflow PUBLIC "-//OpenSymphony Group//DTD OSWorkflow 2.7//EN" "http://www.opensymphony.com/osworkflow/workflow_2_7.dtd"> <workflow> <initial-actions> <action id="0" name="開始"> <results> <unconditional-result old-status="Finished" status="Queued" step="1" /> </results> </action> </initial-actions> <steps> <step id="1" name="填假?> <actions> <action id="1" name="送出"> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="2" owner="User100" /> </results> </action> </actions> </step> <step id="2" name="批假?> <actions> <action id="2" name="准許"> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="3" owner="${caller}"/> </results> </action> <action id="3" name="駁回"> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="1" owner="${caller}"/> </results> </action> </actions> </step> <step id="3" name="停止" /> </steps> </workflow>
在商用和开源世界里QOSWorkflow 都不同于q些已有的工作流pȝ。最大不同在?OSWorkflow 有着非常优秀的灵zL?
OSWorkflow Z有限状态机概念。每?state ?step ID ?status 联合表现Q可单理解ؓ step 及其 status 表示有限状态机?stateQ。一?state 到另一 state ?transition 依赖?action 的发生,在工作流生命期内有至一个或多个zd?state。这些简单概念展C OSWorkflow 引擎的核心思想Qƈ允许一个简?XML 文g解释工作业务流E?
{QTranstionQ?一个State到另一个State的{UR?
动作QActionQ?Action 触发了发生在 Step 内或 Step 间的{Q或者说是基?State 的流转。一?step 里面可以有多个Action。Action 和Step 之间的关pLQStep 说明“在哪里”,Action 说明“去哪里”?一?Action 典型地由两部分组成:可以执行此ActionQ动作)?ConditionQ条ӞQ以及执行此动作后的 ResultQ结果)?
条gQConditionQ类g逻辑判断Q可包含“AND”和“OR”逻辑。比如一个请假流E中的“本部门审批阶段”,该阶D利用“AND”逻辑Q判断流E状态是否ؓ{候处理中Q以及审批者是否ؓ本部门主?
l果QResultQ?Result 代表执行ActionQ动作)后的l果Q指向新?Step 及其 Step StatusQ也可能q入 Split 或?Join。Result 分ؓ两种Q?Contidional-Result Q有条gl果Q,只有条g为真时才使用该结果,?Unconditional-ResultQ无条gl果Q,当条件不满或没有条件时使用该结果?
分离/q接QSplit/JoinQ流E的切分和融合。很单的概念QSplit 可以提供多个 ResultQ结果)QJoin 则判断多?Current Step 的态提供一?ResultQ结果)?
对于一个执行的工作?/a>来讲Q步骤的切换是不可避免的。一个工作流在某一时刻会有一个或多个当前步骤Q每个当前步骤都有一个状态|当前步骤的状态值组成了工作实例的状态倹{一旦完成了一个步骤,那么q个步骤不再是当前步骤Q而是切换C个新的步骤)Q通常一个新的当前步骤将随之建立hQ以保证工作?/a>l箋执行。完成了的步骤的最l状态值是用Old-Status属性指定的Q这个状态值的讑֮发生在切换到其他步骤之前。Old-Status的值可以是L的,但在一般情况下Q我们设|ؓFinished?
切换本n是一个动作(ActionQ的执行l果。每个步骤可以含有多个动作,I竟要蝲入哪个动作是由最l用戗外部事件或者Tiggerd的自动调用决定的。随着动作的完成,一个特定的步骤切换也将发生。动作可以被限制在用戗用L或当前状态。每一个动作都必须包含一个Unconditional Result?个或多个Conditional Results?
所以,M来说Q一个工作流由多个步骤组成。每个步骤有一个当前状态(例如QQueued, Underway or FinishedQ,一个步骤包含多个动作。每个步骤含有多个可以执行的动作。每个动作都有执行的条gQ也有要执行的函数。动作包含有可以改变状态和当前工作步骤的results?
有条件结?Conditional Result) Conditional Result是Unconditional Result的一个扩展。它需要一个或多个Condition子标{。第一个ؓtrue的ConditionalQ用AND或ORcdQ,会指明发生切换的步骤Q这个切换步骤的发生是由于某个用h行了某个动作的结果导致的?
三种不同的Results(conditional or unconditional) 一个新的、单一的步骤和状态的l合。一个分裂成两个或多个步骤和状态的l合。将q个和其他的切换l合成一个新的单一的步骤和状态的l合。每U不同的result对应了不同的xml描述Q你可以阅读http://www.opensymphony.com/osworkflow/workflow_2_7.dtdQ获取更多的信息。注意:通常Q一个split或一个join不会再导致一个split ?join的发生?
然而,?a class="wikipage" >工作?/a>处于ACTIVATED状态的时候,调用者可以终止或挂vq个工作(讄工作的状态ؓKILLED ?SUSPENDEDQ。一个终止了的工作流不能再执行M动作Q而且永q保持着l止状态。一个被挂v了的工作?/a>会被ȝQ他也不能执行Q何的动作Q除非它的状态再变成ACTIVATED?