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"?>
<!-- 下面配置資料源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 name="username">
<value>test</value>
<property name="password">
</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>
</bean>
<!-- 配置osworkflow中所用的propertyset,這裡配置的是預設的記憶體方式的propertyset。-->
<bean id="propertySetDelegate" class="com.opensymphony.workflow.util.PropertySetDelegateImpl">
<!-- 配置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>
<!-- 配置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 id="osworkflowConfiguration" class="com.opensymphony.workflow.config.SpringConfiguration">
<property name="store"><ref local="workflowStore"/></property>
<property name="factory"><ref local="workflowFactory"/></property>
<!-- 配置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>
<!-- 下面的配置是配置讓oswrorkflow使用spring的事務架構 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
<!-- 應用程式在代碼中唯一要關注的就隻有這一個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>
</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持久化。