WorkFlow的事務回滾實現

          Posted on 2006-03-02 21:03 killvin 閱讀(634) 評論(0)  編輯  收藏 所屬分類: osworkflow
          Workflow Project 目前狀態
          版本 0.11

          已經完成
          1。完成了接口1 和接口2 的方法
          2。完成接口3的默認實現
          3。完成事務回滾的實現方法-等待測試

          未完成
          1。接口3的注冊與實例化解決方案
          2。應用的并發訪問問題以及解決數據的臟讀問題
          3。與具體的某個應用掛接并測試


          -事務的回滾
          OSWorkFlow的事務回滾是依靠WorkflowContext這個接口來實現的,在New出某個WorkFlow的時候需要聲明WorkflowContext的實現類,一般會采用uper.context = new GearWheelWorkFlowContext(_caller);方法
          比如這樣實現:

          public GearWheelWorkFlow(String _caller)
          {
          super.context = new GearWheelWorkFlowContext(_caller);
          }

          但OSWorkFlow的WorkflowContext的默認實現BasicWorkFlowContext中根本沒有實現setRollbackOnly方法,也就沒有了參考的可能

          再看看這個接口的其他實現類也都是建立在JTA這樣的跨Session的事務服務上,比如它的EJB的實現也是要調用容器提供的JTA實現才行!而JTA的實現比如要JNDI到數據庫池,此時的應用光JTA+JNDI就已經宣布 -這樣的例子必須生存在應用服務器的環境下!!

          可是,我不死心,我記得Hibernate可以實現本地事務,也就是依靠JDBC本身的事務處理能力,而要實現這樣的功能就需要在數據庫連接的獲取上下一些功夫,也就是要保證回滾的數據庫連接必須是獲取時的那個連接,而存儲連接就成了一個需要首先解決的問題。

          解決數據庫連接的存儲問題
          目前存儲數據庫連接除了依靠靜態類外,還有一個通用的方法ThreadLocal類,這樣獲取數據庫連接的方法寫成了如下的形式:

          package com.company.common;
          import java.sql.Connection;
          import java.sql.DriverManager;
          import java.sql.ResultSet;
          import java.sql.SQLException;
          import java.sql.Statement;
          import java.util.Collections;
          import java.util.HashMap;
          import java.util.Map;
          import org.apache.log4j.Logger;
          public class DB2ConnectFactory
          {
          /**
          * Logger for this class
          */
          private static final Logger logger = Logger.getLogger(DB2ConnectFactory.class);
          private static ThreadLocal threadLocal = new ThreadLocal();
          //~
          private Connection connect = null;
          private Statement state = null;
          private ResultSet result = null;
          private boolean closeConnWhenDone = false;
          //~
          private String url = "jdbc:db2:WORKFLOW";
          private String user = "";
          private String password = "";
          private String driverClassName = "COM.ibm.db2.jdbc.app.DB2Driver";

          public DB2ConnectFactory() throws SQLException
          {
          this.init();
          }

          /**
          * 獲取數據庫連接
          * @return
          * @throws SQLException
          */
          public Connection getConn() throws SQLException
          {
          return (Connection)threadLocal.get();
          }

          /**
          * 初始化數據庫,并在緩沖中注冊數據庫連接
          * @throws SQLException
          */
          private void init() throws SQLException
          {
          try
          {
          // Get connect object
          Class.forName(driverClassName);
          closeConnWhenDone = true;

          connect = DriverManager.getConnection(url, user, password);
          state = connect.createStatement();

          //Register the connection object in the threadlocal
          threadLocal.set(connect);
          }
          catch (Exception e)
          {
          e.printStackTrace();
          throw new SQLException(e.getMessage());
          }
          }

          }

          解決事務回滾
          剛才說了需要實現WorkflowContext接口
          package com.company.engine.workflow;
          import java.sql.Connection;
          import java.sql.SQLException;
          import org.apache.log4j.Logger;
          import com.company.common.DB2ConnectFactory;
          import com.opensymphony.workflow.WorkflowContext;
          public class GearWheelWorkFlowContext implements WorkflowContext
          {
          /**
          * Logger for this class
          */
          private static final Logger logger = Logger.getLogger(GearWheelWorkFlowContext.class);

          private static ThreadLocal threadLocal = new ThreadLocal();

          // ~ Instance fields
          // ////////////////////////////////////////////////////////
          private String caller;
          // ~ Constructors
          // ///////////////////////////////////////////////////////////
          public GearWheelWorkFlowContext(String caller)
          {
          this.caller = caller;
          }
          // ~ Methods
          // ////////////////////////////////////////////////////////////////
          public String getCaller()
          {
          return this.caller;
          }
          /**
          * Tranaction : Set Roll back
          * @throws SQLException
          */
          public void setRollbackOnly()
          {
          Connection connect = null;
          try
          {
          DB2ConnectFactory factory = new DB2ConnectFactory();
          connect = factory.getConn();
          if(connect != null) connect.rollback();
          }
          catch (Exception e)
          {
          e.printStackTrace();
          }
          finally
          {
          this.clostConnection(connect);
          }
          }

          private void clostConnection(Connection connect)
          {
          try
          {
          if(connect != null) connect.close();
          }
          catch (Exception e)
          {
          e.printStackTrace();
          }
          }
          }

          總結
          1。我們可以看到由于接口中setRollbackOnly沒有異常的聲明,方法中即使拋出了異常也要自己"忍了"!看來良好的接口聲明其實是非常重要的。

          2。而且需要重載原來JDBCWorkflow 中的cleanup方法,將其中的代碼屏蔽掉!數據庫的關閉放在了setRollbackOnly訪訪的finally中,原因就是由于我們要統一的管理數據庫連接所引發的,我們不能夠在WorkFlowStore的每一個方法執行完畢后就關閉連接,因為這樣的話你根本沒有了事務回滾的可能,所以此時的連接需要在WorkflowContext中來處理。


          感觸
          OSWorkFlow的實現方法并不是像網上所說的那樣的優秀和文雅,更像是一個未完成任務的"半成品",Heni被網上鼓吹為大牛,但一個不寫注釋和文檔的人,根本稱不上什么大牛!
          OSWorkFlow更多的是實現了一個微內核,而它的用戶模式是與OSUser這樣的框架耦合的(偶已經將這樣的耦合打開了,也就是接口3的定義),它的相關數據是與PropertySet框架耦合的(也就是接口2的定義),而且采用OSWorkFlow要經過很原始的修改(比如我實現了DB2下的WorkFlowStore的實現)。

          不過也好即使以后不采用OSWorkFlow,自己實現一個這樣的引擎也應該沒有什么問題的,有時間了我倒是很想看看別的工作流的產品。
          主站蜘蛛池模板: 新绛县| 边坝县| 通榆县| 霍林郭勒市| 盐边县| 于田县| 佳木斯市| 弥勒县| 府谷县| 太白县| 祁连县| 柳江县| 罗甸县| 高陵县| 吉水县| 宁武县| 洪雅县| 东至县| 宁陕县| 平邑县| 景东| 华容县| 英吉沙县| 高青县| 卓尼县| 喀喇沁旗| 辰溪县| 房山区| 海盐县| 昌乐县| 佛冈县| 思南县| 神木县| 凤翔县| 息烽县| 永福县| 神农架林区| 古蔺县| 孝感市| 家居| 英吉沙县|