在基于工作流进行业务系统开发时,通常需要在某些事件发生时或某些情况下,由低层工作流引擎调用上层的业务处理逻辑,比如在示例业务需求中,当部门主管审批员工请假申请时,审批事件发生时需要将审批意见插入到数据库表中,并进入后续相应的步骤,这里的将审批意见插入数据库,可以在业务程序中审批处理代码中直接插入,也可以只让审批处理代码只负责调用工作流引擎的“审批处理”步骤的doAction,而在doAction的过程中由引擎调用插入数据的操作;又例如在某些动作执行后向用户发送邮件通知。
这样当采用由引擎调用业务处理后,就可以在不改变程序代码的情况下调整业务过程及处理方式,比如去掉插入审批意见到数据库、取消动作后发送邮件通知等。业务过程的可配置性大大提高。
在工作流管理系统参考模型中,工作流引擎调用业务逻辑就是指的Interface 3,即如下图所示
在示例中,由引擎调用业务处理是通过Function的回调实现的,这个Function需要实现com.opensymphony.workflow.FunctionProvider,然后实现其中的execute(Map transientVars, Map args, PropertySet ps)方法。参数说明:
Map transientVars表示临时变量,这些变量可以通过doAction(long id, int actionId, Map inputs)的inputs传入,也可以通过initialize(String workflowName, int initialAction, Map inputs)的inputs传入,此外还包含一些全局变量,如entry、context、actionId等;
Map args表示调用Function的属性,这些属性在过程定义文件xml中设定;
PropertySet ps 持久变量,这些变量设置后将存储到数据库或其他存储介质,在本示例中通过在doAction中设置该变量,然后在流程跳转时根据该变量进行相应跳转,即实现业务流程的不同流向。
示例代码
在部门主管审批时调用的ApproveFunction,这个Function只是将审批结果插入数据库中
- public void execute(Map transientVars, Map args, PropertySet ps) {
- logger.info("execute ......");
- WorkflowEntry entry = (WorkflowEntry) transientVars.get("entry");
- long wfid = entry.getId();
- int actionId = ((Integer) transientVars.get("actionId")).intValue();
- logger.info("execute actionId=" + actionId);
- int applyID = ((Integer) transientVars.get("applyID")).intValue();
- String approver = (String) transientVars.get("approver");
- int opinion = ((Integer) transientVars.get("opinion")).intValue();
- LeaveApprove LeaveApprove = new LeaveApprove(applyID, approver, opinion);
- LeaveDAO leaveDao = new LeaveDAO();
- leaveDao.addLeaveApprove(LeaveApprove);
- ps.setInt("opinion", opinion);
- logger.info("execute leaveDao has added leaveApprove!");
- }
public void execute(Map transientVars, Map args, PropertySet ps) {
logger.info("execute ......");
WorkflowEntry entry = (WorkflowEntry) transientVars.get("entry");
long wfid = entry.getId();
int actionId = ((Integer) transientVars.get("actionId")).intValue();
logger.info("execute actionId=" + actionId);
int applyID = ((Integer) transientVars.get("applyID")).intValue();
String approver = (String) transientVars.get("approver");
int opinion = ((Integer) transientVars.get("opinion")).intValue();
LeaveApprove LeaveApprove = new LeaveApprove(applyID, approver, opinion);
LeaveDAO leaveDao = new LeaveDAO();
leaveDao.addLeaveApprove(LeaveApprove);
ps.setInt("opinion", opinion);
logger.info("execute leaveDao has added leaveApprove!");
}
过程定义配置文件中相关的回调
- <step id="2" name="请假申请审核">
- <actions>
- <action id="2" name="部门主管审批请假申请">
- <restrict-to>
- <conditions type="AND">
- <condition type="beanshell">
- <arg name="script">true</arg>
- </condition>
- <condition type="class">
- <arg name="class.name">com.opensymphony.workflow.util.StatusCondition</arg>
- <arg name="status">Underway</arg>
- </condition>
- <condition type="class">
- <arg name="class.name">com.opensymphony.workflow.util.OSUserGroupCondition</arg>
- <arg name="group">manager</arg>
- </condition>
- </conditions>
- </restrict-to>
- <pre-functions>
- [color=red]<function type="class">
- <arg name="class.name">com.qiny.leave.ApproveFunction</arg>
- </function>[/color]
- <function type="beanshell">
- <arg name="script">
- System.out.println("步骤 2 请假申请审核 pre-functions $$$$$$$");
- </arg>
- </function>
- </pre-functions>
- <results>
- <result old-status="Finished" status="Underway" step="5">
- <conditions type="AND">
- <condition type="beanshell">
- <arg name="script">
- propertySet.getInt("opinion")==2
- </arg>
- </condition>
- </conditions>
- <post-functions>
- <function type="beanshell">
- <arg name="script">
- System.out.println("步骤 2 请假申请审核 部门经理审批没有通过 ...");
- </arg>
- </function>
- </post-functions>
- </result>
- <unconditional-result old-status="Finished" status="Underway" step="3" owner="hr1"/>
- </results>
- <post-functions>
- <function type="beanshell">
- <arg name="script">
- System.out.println("步骤 2 请假申请审核 post-functions .......");
- </arg>
- </function>
- </post-functions>
- </action>
- </actions>
- </step>
<step id="2" name="请假申请审核">
<actions>
<action id="2" name="部门主管审批请假申请">
<restrict-to>
<conditions type="AND">
<condition type="beanshell">
<arg name="script">true</arg>
</condition>
<condition type="class">
<arg name="class.name">com.opensymphony.workflow.util.StatusCondition</arg>
<arg name="status">Underway</arg>
</condition>
<condition type="class">
<arg name="class.name">com.opensymphony.workflow.util.OSUserGroupCondition</arg>
<arg name="group">manager</arg>
</condition>
</conditions>
</restrict-to>
<pre-functions>
[color=red]<function type="class">
<arg name="class.name">com.qiny.leave.ApproveFunction</arg>
</function>[/color]
<function type="beanshell">
<arg name="script">
System.out.println("步骤 2 请假申请审核 pre-functions $$$$$$$");
</arg>
</function>
</pre-functions>
<results>
<result old-status="Finished" status="Underway" step="5">
<conditions type="AND">
<condition type="beanshell">
<arg name="script">
propertySet.getInt("opinion")==2
</arg>
</condition>
</conditions>
<post-functions>
<function type="beanshell">
<arg name="script">
System.out.println("步骤 2 请假申请审核 部门经理审批没有通过 ...");
</arg>
</function>
</post-functions>
</result>
<unconditional-result old-status="Finished" status="Underway" step="3" owner="hr1"/>
</results>
<post-functions>
<function type="beanshell">
<arg name="script">
System.out.println("步骤 2 请假申请审核 post-functions .......");
</arg>
</function>
</post-functions>
</action>
</actions>
</step>