OSWorkflow之四——流程开发
开始一个流程
我们通过XML完成的只是流程的定义,真正需要流程跑起来,我们还需要一个个流程的实例。
?
Workflow接口
OSWorkflow最主要最常用的操作都是通过Workflow接口来完成的。OSWorkflow针对Ofbiz、EJB、XFireSOAP、OfbizSOAP都给出了自己的Workflow实现,我们可以根据场景选用。
?
BasicWorkflow
BasicWorkflow是我们在大多数场合下使用频率最高的Workflow实现。
?
initialize方法
通过initialize方法,我们可以创建属于我们自己的流程实例,完成一些初始化操作,并返回新创建的流程id。以下是initialize的方法签名:
?
/** * Initializes a workflow so that it can begin processing. A workflow must be initialized before it can * begin any sort of activity. It can only be initialized once. * * @param workflowName The workflow name to create and initialize an instance for * @param initialAction The initial step to start the workflow * @param inputs The inputs entered by the end-user * @throws InvalidRoleException if the user can't start this function * @throws InvalidInputException if a validator is specified and an input is invalid. * @throws InvalidActionException if the specified initial action is invalid for the specified workflow. */ public long initialize(String workflowName, int initialAction, Map inputs) throws InvalidRoleException, InvalidInputException, WorkflowException, InvalidEntryStateException, InvalidActionException;
?
workflowName:我们在定义workflow是name属性的值,比如下例中的example,
?
<workflow name="example" type="resource" location="example.xml"/>?
initialAction:我们在流程定义文件中定义的initialAction的id,比如下例中的100,
?
<initial-actions><action id="100" name="Start Workflow"><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="Underway" step="1" owner="${caller}"/></results></action></initial-actions>?
inputs:用来保存我们自己需要用到的一些key-value,他可以在action里的condition、function、validator中作为各自的方法参数传递,我们可以在相应的接口方法中轻易的读写。
?
以下是initialize方法的实例代码:
?
Workflow workflow = new BasicWorkflow("caller");Configuration config = new DefaultConfiguration();workflow.setConfiguration(config);long workflowId = workflow.initialize("example", 100, null);?
doAction方法
doAction方法用来执行一个动作行为,驱动着流程的运转。
?
/** * Perform an action on the specified workflow instance. * @param id The workflow instance id. * @param actionId The action id to perform (action id's are listed in the workflow descriptor). * @param inputs The inputs to the workflow instance. * @throws InvalidInputException if a validator is specified and an input is invalid. * @throws InvalidActionException if the action is invalid for the specified workflow * instance's current state. */ public void doAction(long id, int actionId, Map inputs) throws InvalidInputException, WorkflowException;?
参数:
?
id:workflow entity id 即实例id
actionId:action id
inputs:同initialize方法inputs参数。
?
getCurrentSteps方法
返回指定workflow实例的当前step对象的集合
?
/** * Returns a Collection of Step objects that are the current steps of the specified workflow instance. * * @param id The workflow instance id. * @return The steps that the workflow instance is currently in. */ public List getCurrentSteps(long id);
参数:
id:workflow entity id 即实例id
?
getHistorySteps方法
返回指定workflow实例的当前历史step对象的集合
?
/** * Returns a list of all steps that are completed for the given workflow instance id. * * @param id The workflow instance id. * @return a List of Steps * @see com.opensymphony.workflow.spi.Step */ public List getHistorySteps(long id);?
参数:
id:workflow entity id 即实例id
?
action到底做了些什么
不论是initialize方法还是doAction方法,最后都会通过AbstractWorkflow的transitionWorkflow方法来完成流程流转的,下图是transitionWorkflow方法的执行步骤。
?
?
VariableResolver
VariableResolver接口只有一个translateVariables方法,OSWorkflow给出了一个默认实现DefaultVariableResolver。他负责将我们在XML流程定制文件中使用的类似“${var}”这样的占位符给替换成其具体的值。他首先会去transientVars中去找key=var的值,如果没有找到则会到propertySet去找。如此一来,我们就可以在XML文件中使用类似“${var}”这样的占位符,只要我们在之前把它们保存到transientVars或者propertySet就可以啦。
?
让OSWorkflow运行在Spring事务中
要让OSWorkflow和我们的应用运行在同一个事务中,前提是我们需要保证我们有相同的connection(JDBC)或者sessionFactory(hibernate),然后我们可以给Workflow接口创建一个事务代理,当Workflow接口的方法被执行时,可以加入到当前线程开启的事务中去,通过IOC容器这一切都变得那么简单。请参考以下红色部分的字体。
?
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"><bean id="propertySetDelegate"/></property></bean><bean id="workflowStore"/></property><property name="propertySetDelegate"><ref bean="propertySetDelegate" /></property></bean><bean id="workflowFactory"/></property><property name="factory"><ref local="workflowFactory" /></property></bean><bean id="workflowTypeResolver" /></property><property name="resolver"><ref local="workflowTypeResolver" /></property></bean><bean id="transactionInterceptor"/></property><property name="transactionAttributes"><props><prop key="*">PROPAGATION_REQUIRED</prop></props></property></bean><bean id="workflow" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="singleton"><value>false</value></property><property name="proxyInterfaces"><value>com.opensymphony.workflow.Workflow</value></property><property name="interceptorNames"><list><value>transactionInterceptor</value><value>basicWorkflow</value></list></property></bean></beans>?
通过之前篇幅的探讨,我们的Spring Application Context应该如以上清单所示。如果使用Spring更高的版本,我们甚至可以通过其高级的特性来完成事务相关的配置,这些就不在此讨论范围之内啦。
?
OSWorkflow还有很多特性被我略过了,如对SOAP和EJB的相关支持,等等。对于没有提到的部分,大家也都可以一起分享探讨。
?