1. 将osworkflow与spring和hibernate结合的原因
1)简化对osworkflow的配置
2)利用hibernate框架的一些特性,如持久化,缓存等
3)事务管理,osworkflow本身是不支持事务的,而事务是作为一个产品的基本功能
4)可以利用spring加入其它的扩展功能,如用户认证和鉴权。这点本文没有介绍。
2、准备
下载osworkflow-2.8.0版本 ,下载hibernate-3.2版本,下载spring-framework-2.5.5版本
3、搭建eclipse环境
测试的工程目录如下:
src 源代码目录
oswf 包路径
Test.java 测试类,后面会给出源代码
bin 编译目的目录
oswf 包路径
Test.class 编译生成的class文件
//下面的几个配置文件位于bin目录下
log4j.properties 这是log4j的配置文件,这可以不需要
//下面三个hbm.xml文件是osworkflow持久化的o/r映射文件,这是从osworkflow的源代码目录com"opensymphony"workflow"spi"hibernate3下拷出来的。
HibernateCurrentStep.hbm.xml
HibernateHistoryStep.hbm.xml
HibernateWorkflowEntry.hbm.xml
//下面三个文件直接从osworkflow自带的例子中获取的,其中example.xml是流程定义文件。osuser.xml是osuser的配置文件。workflows.xml是osworkflow配置有哪些流程定义的配置文件。
example.xml
osuser.xml
workflows.xml
osworkflow-spring.xml //这是spring 的配置文件,位于根目录下,后面会给出源代码
//下面两个是eclipse的工程文件
.project
.classpath
4、编写spring 的beans.xml配置文件
文件名如osworkflow-spring.xml,内容如下:
<?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">
<!-- 下面配置数据源datasource,这里用的是spring 自带的一个测试用的连接池。也可以用开源的连接池Jakarta Commons DBCP。 如果程序是运行在servlet容器中,如tomcat中,可直接使用在tomcat中配置的数据库连接池jdni。 这里给出的是oracle数据库驱动,可以换成任意的数据库,如mysql等。 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close"> <property name="driverClassName"> <value>oracle.jdbc.driver.OracleDriver</value> </property> <property name="url"> <value>jdbc:oracle:thin:@127.0.0.1:1521:orcl</value> </property> <property name="username"> <value>test</value> </property> <property name="password"> <value>test</value> </property> </bean> <!-- 配置hibernate的sessionFactory以及相关的配置,这是使用hibernate的入口--> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"><ref local="dataSource"/></property> <property name="mappingResources"> <list> <value>HibernateCurrentStep.hbm.xml</value> <value>HibernateHistoryStep.hbm.xml</value> <value>HibernateWorkflowEntry.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9iDialect</prop> <prop key="hibernate.current_session_context_class">thread</prop> <prop key="hibernate.hbm2ddl.auto">create-drop</prop> </props> </property> </bean>
<!-- 配置osworkflow中所用的propertyset,这里配置的是默认的内存方式的propertyset。--> <bean id="propertySetDelegate" class="com.opensymphony.workflow.util.PropertySetDelegateImpl"> </bean>
<!-- 配置osworkflow的存储工厂WorkflowStore --> <bean id="workflowStore" class="com.opensymphony.workflow.spi.hibernate3.SpringHibernateWorkflowStore"> <property name="sessionFactory"><ref local="sessionFactory"/></property> <property name="propertySetDelegate"> <ref bean="propertySetDelegate"/> </property> </bean>
<!-- 配置osworkflow的工厂类 --> <bean id="workflowFactory" class="com.opensymphony.workflow.spi.hibernate.SpringWorkflowFactory" init-method="init"> <property name="resource"><value>workflows.xml</value></property> <property name="reload"><value>false</value></property> </bean>
<bean id="osworkflowConfiguration" class="com.opensymphony.workflow.config.SpringConfiguration"> <property name="store"><ref local="workflowStore"/></property> <property name="factory"><ref local="workflowFactory"/></property> </bean>
<!-- 配置osworkflow的工作流接口。注意下面的构造函数参数值test是用户名 --> <bean id="workflowTarget" class="com.opensymphony.workflow.basic.BasicWorkflow"> <constructor-arg><value>test</value></constructor-arg> <property name="configuration"><ref local="osworkflowConfiguration"/></property> </bean>
<!-- 下面的配置是配置让oswrorkflow使用spring的事务框架 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
<!-- 应用程序在代码中唯一要关注的就只有这一个Bean,其它不用关注 --> <bean id="workflow" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="transactionManager"/> <property name="target" ref="workflowTarget"/>
<property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean>
</beans>
5、编写测试代码,只有一个类,代码如下:
package oswf;
import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource;
import com.opensymphony.user.Group; import com.opensymphony.user.User; import com.opensymphony.user.UserManager; import com.opensymphony.workflow.Workflow;
public class Test {
public static void main(String[] args) { try{ UserManager um = UserManager.getInstance(); User test = um.createUser("test"); test.setPassword("test");
Group foos = um.createGroup("foos"); Group bars = um.createGroup("bars"); Group bazs = um.createGroup("bazs");
test.addToGroup(foos); test.addToGroup(bars); test.addToGroup(bazs); } catch(Exception e){ System.out.println("create user error,app exit"); return; } System.out.println("create user success");
Resource res = new FileSystemResource("osworkflow-spring.xml"); XmlBeanFactory beanFactory =new XmlBeanFactory(res); Workflow workflow = (Workflow) beanFactory.getBean("workflow"); try { workflow.initialize("example", 100, null); } catch (Exception e) { e.printStackTrace(); } } } 代码是,首先要创建一个用户(这里使用的是osworkflow默认绑定的osuser框架)。然后获取workflow bean,再调用initialize方法创建一个新的流程。
6、问题
1)osworkflow使用了propertyset框架,但propertyset框架和osworkflow都是opensymphony下的一个开源项目。osworkflow中提供的propertyset jar包不支持hibernate3,因此本例子中是使用内存化的propertyset,没有持久化propertyset。
2)osworkflow中的BasicWorkflow类的构造函数必须提供一个参数,参数是osuser中的用户。而且没有提供设置用户的set方法,这样就只能在配置文件中把用户名写死。这只能用在测试环境中。在实际中需要修改这个代码,支持动态设置用户。
3)osuser框架不支持通过hibernate持久化,如果要支持,需要自己下载源代码改写。但osuser支持通过jdbc持久化。