??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲伊人久久综合影院,亚洲伊人久久大香线焦,亚洲私人无码综合久久网 http://m.tkk7.com/killvin/category/8035.htmlzh-cn Tue, 27 Feb 2007 08:46:46 GMT Tue, 27 Feb 2007 08:46:46 GMT 60 OSWorkflow深入分析 Q?重新定义Configuration接口 http://m.tkk7.com/killvin/archive/2006/03/02/33314.htmlkillvin killvin Thu, 02 Mar 2006 13:04:00 GMT http://m.tkk7.com/killvin/archive/2006/03/02/33314.html 在OSWorkflow中最让h恼火的就是它的接口定义!我会p些接口的混ؕ展开一pd的分析,今天先说说Configuration接口
偶承了它的Configuration接口
import com.company.engine.workflow.store.IWorkFlowStore; import com.opensymphony.workflow.StoreException; import com.opensymphony.workflow.config.Configuration; import com.opensymphony.workflow.spi.WorkflowStore;
public interface IConfiguration extends Configuration { /** * @deprecated getIWorkflowStore() */ WorkflowStore getWorkflowStore() throws StoreException; /** * return WorkFlowStore which implements the interface of IWorkFlowStore * @return * @throws StoreException */ IWorkFlowStore getIWorkflowStore() throws StoreException; }
你可能奇怪我Z要承它的接口(肯定是Bad smellQ,原因如下Q?/P>
IWorkFlowStore 接口定义
import com.opensymphony.workflow.StoreException; import com.opensymphony.workflow.spi.Step; import com.opensymphony.workflow.spi.WorkflowEntry; import com.opensymphony.workflow.spi.WorkflowStore;
public interface IWorkFlowStore extends WorkflowStore { public Step createCurrentStep(WorkflowEntry _entry , Step _step) throws StoreException;
}
WorkflowStore 接口定义
/** * Persists a step with the given parameters. * * @param entryId The workflow instance id. * @param stepId the ID of the workflow step associated with this new * Step (not to be confused with the step primary key) * @param owner the owner of the step * @param startDate the start date of the step * @param status the status of the step * @param previousIds the previous step IDs * @return a representation of the workflow step persisted */ public Step createCurrentStep(long entryId, int stepId, String owner, Date startDate, Date dueDate, String status, long[] previousIds) throws StoreException;
看到了吧Q?/P>
其实我只是希望在createCurrentStep时按照OO的方法执行,而不是传递那?Bad Smell"的参敎ͼ而OSWorkflow中的WorkflowStore是需要Configuration来获取的Q此时ؓ了增加一个看似合理的ҎQ需要分别承Configuration与WorkflowStoreQ这q没有完Q你需要实C个Configuration实现Q!
import com.company.engine.workflow.store.IWorkFlowStore; import com.opensymphony.workflow.StoreException; import com.opensymphony.workflow.config.DefaultConfiguration; import com.opensymphony.workflow.spi.WorkflowStore;
public class DefaultIConfiguration extends DefaultConfiguration implements IConfiguration { public static DefaultIConfiguration INSTANCE = new DefaultIConfiguration(); private transient IWorkFlowStore store = null;
/** * @deprecated getIWorkflowStore() */ public WorkflowStore getWorkflowStore() throws StoreException { return null; }
public IWorkFlowStore getIWorkflowStore() throws StoreException { if (store == null) { String clazz = getPersistence();
try { store = (IWorkFlowStore) Class.forName(clazz).newInstance(); } catch (Exception ex) { throw new StoreException("Error creating store", ex); }
store.init(getPersistenceArgs()); }
return store; }
}
ȝ
1。OSWorkflow与WorkflowStore接口的关pL较的微妙Q它需要借助于Configuration接口的实现来获取到实际的WorkflowStore对象?/P>
2。由于这L一U微妙关p,对WorkflowStore接口的扩展必连带着需要扩展Configuration接口Q而生这L"果冻效应"的罪祸首就是由于WorkflowStore接口与Configuration接口耦合的太紧?/P>
3。OSWorkflowq没有很好的遵守OO的设计规则,其在它的参C递上Q非常的差!
]]>workflow接口划分 http://m.tkk7.com/killvin/archive/2006/03/02/33312.htmlkillvin killvin Thu, 02 Mar 2006 13:03:00 GMT http://m.tkk7.com/killvin/archive/2006/03/02/33312.html workflow接口划分 1。应用接?Application Interface Q-interface1 工作自w提供的服务接口 Q-interface2 工作与应用之间的接口(主要是提供相x据的调用接口Q?BR> 2。扩展接?PlugIn Interface Q-interface3 工作与l织机构之间的接?BR>Q-interface4 工作与其他工作之间的接口 接口划分成应用接口与扩展接口主要是依据工作与相关应用的调用关p,比如工作与l织机构之间Q是工作调用组l机构中的h员信息,所以主动者是WORKFLOW、被动方是组l机构,所以应该采用扩展接口来实现 在扩展接口上应该采用Adapter模式Q从而工作不局限于某个特定的实?BR> 目前的进?BR>0。Application Interface接口已经基本实现?BR>PlugIn Interface接口目前基本完工Q但OSWorkflow的实现实在是非常的丑陋,需要更改的地方太多Q而且对于Interface3不可以用它采用的User / Group模型Q而且它用了OSUserq个框架Q对于多数的应用E序基本可以说不适合Q而且它的Usercȝ然是Final ?!而且我发现它的很多类的属性都是ProtectedQ也是说除了他们自己根本没有办法扩展,即扩展也是很丑陋的方式Q?BR> 1。现在最大的问题是它的WorkStore接口的扩展,我采用DB2的方式实C它的接口Q但q样的方式会与DB2l定在一P如果自己写实现就要根据不同的DB采用不同的SQL语言Q也是不同的方a{略Q!而且考虑到性能估计不是什么好LQ看来明天需要更换成HibernateWorkStore的Ş式,q样工作的持久层接口将工作在Hibernate之上Q看来很完美的解决了q个问题?BR> 2。而且我扩展了它的PropertySetQ其不再依靠JNDILDataSourceQ而是通过嵌入在程序内部采用JDBC的Ş式寻找数据库q接Q这h׃必ؓ了验证一个问题去建立那该ȝ数据库缓冲池了(而且JNDI的Ş式也׃可避免的要用到容器,太重了!Q?BR> 3。我~写了UserGroupCondition的实现类Q这个类的作用就是调用Interface3的方法,从而判断某个用h否属于某个组Q现在的做法是让WorkStore实现Interface3的偷懒办法,但很乱,看来q是要写一个Adapterd现interface3才对Q) 4。目前工作流引擎的工厂类已经实现完工q测试通过?BR> 用了q一个月的时间完成了q些工作Q看h很少但是基本上大量的旉p在熟悉工作流规范、WFMC标准、以及学习和扩展OSWorkflow接口上,不过对OSWorkflow的实现基本上掌握了,如果抛开OSWorkflow自己也可以采用自q方式d玎ͼ或者会考虑使用Spring的方式(Interface3的Adapter不行采用Spring实现Q?BR> BTW: OSWorkflow的实现其实比较的丑陋Q而且~码Ҏ没有什么规范,接口的定义也是天马行I,看来Heni除了他的大嘴外应该好好的提高自己的技术修充R-实在不敢恭维q位"大师"的编码水qI ]]> WorkFlow的事务回滚实? http://m.tkk7.com/killvin/archive/2006/03/02/33313.htmlkillvin killvin Thu, 02 Mar 2006 13:03:00 GMT http://m.tkk7.com/killvin/archive/2006/03/02/33313.html 版本 0.11 已经完成 1。完成了接口1 和接? 的方?BR>2。完成接?的默认实?BR>3。完成事务回滚的实现ҎQ等待测?BR> 未完?BR>1。接?的注册与实例化解x?BR>2。应用的q发讉K问题以及解决数据的脏读问?BR>3。与具体的某个应用挂接ƈ试 Q事务的回滚 OSWorkFlow的事务回滚是依靠WorkflowContextq个接口来实现的Q在New出某个WorkFlow的时候需要声明WorkflowContext的实现类Q一般会采用uper.context = new GearWheelWorkFlowContext(_caller);Ҏ 比如q样实现Q?BR> public GearWheelWorkFlow(String _caller) { super.context = new GearWheelWorkFlowContext(_caller); } 但OSWorkFlow的WorkflowContext的默认实现BasicWorkFlowContext中根本没有实现setRollbackOnlyҎQ也没有了参考的可能 再看看这个接口的其他实现cM都是建立在JTAq样的跨Session的事务服务上Q比如它的EJB的实C是要调用容器提供的JTA实现才行Q而JTA的实现比如要JNDI到数据库池,此时的应用光JTA+JNDI已l宣?Q这L例子必须生存在应用服务器的环境下Q! 可是Q我不死心,我记得Hibernate可以实现本地事务Q也是依靠JDBC本n的事务处理能力,而要实现q样的功能就需要在数据库连接的获取上下一些功夫,也就是要保证回滚的数据库q接必须是获取时的那个连接,而存储连接就成了一个需要首先解决的问题?BR> 解决数据库连接的存储问题 目前存储数据库连接除了依靠静态类外,q有一个通用的方法ThreadLocalc,q样获取数据库连接的Ҏ写成了如下的形式Q?BR> 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(); } /** * 获取数据库连?BR>* @return * @throws SQLException */ public Connection getConn() throws SQLException { return (Connection)threadLocal.get(); } /** * 初始化数据库,q在~冲中注册数据库q接 * @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没有异常的声明,Ҏ中即使抛Z异常也要自己"忍了"Q看来良好的接口声明其实是非帔R要的?BR> 2。而且需要重载原来JDBCWorkflow 中的cleanupҎQ将其中的代码屏蔽掉Q数据库的关闭放在了setRollbackOnly访访的finally中,原因是׃我们要统一的管理数据库q接所引发的,我们不能够在WorkFlowStore的每一个方法执行完毕后关闭连接,因ؓq样的话你根本没有了事务回滚的可能,所以此时的q接需要在WorkflowContext中来处理?BR> 感触 OSWorkFlow的实现方法ƈ不是像网上所说的那样的优U和文雅,更像是一个未完成d?半成?QHeni被网上鼓吹ؓ大牛Q但一个不写注释和文的hQ根本称不上什么大牛! OSWorkFlow更多的是实现了一个微内核Q而它的用h式是与OSUserq样的框架耦合的(偶已l将q样的耦合打开了,也就是接?的定义)Q它的相x据是与PropertySet框架耦合的(也就是接?的定义)Q而且采用OSWorkFlow要经q很原始的修改(比如我实CDB2下的WorkFlowStore的实玎ͼ?BR> 不过也好即以后不采用OSWorkFlowQ自己实C个这L引擎也应该没有什么问题的Q有旉了我倒是很想看看别的工作的产品?img src ="http://m.tkk7.com/killvin/aggbug/33313.html" width = "1" height = "1" /> ]]> OSWorkflow你让我把数据库关闭写在哪里! http://m.tkk7.com/killvin/archive/2006/03/02/33311.htmlkillvin killvin Thu, 02 Mar 2006 13:02:00 GMT http://m.tkk7.com/killvin/archive/2006/03/02/33311.html 在Workflow事务回滚中遇C问题Q是q样?/P>
DB2ConnectFactory 中getConnҎ /** * 获取数据库连?BR>* @return * @throws SQLException */ public Connection getConn() throws SQLException { Object obj = threadLocal.get(); if(obj == null) { this.initFactoryStack(); }else { connect = (Connection)obj; } connect.setAutoCommit(false); //事务的回滚必d立在Commit状态ؓFalse下,默认是true logger.debug("Get connect from factory - " + connect.hashCode()); return connect; }
AbstractWorkflow 的doAction()Ҏ
try { //transition the workflow, if it wasn't explicitly finished, check for an implicit finish if (!transitionWorkflow(entry, currentSteps, store, wf, action, transientVars, inputs, ps)) { checkImplicitFinish(id); } } catch (WorkflowException e) { context.setRollbackOnly(); // q里调用WorkContext对象的setRollbackOnly()ҎQ执行事务的回滚 throw e; }
GearWheelWorkFlowContext 的setRollbackOnlyҎ /** * Tranaction : Set Roll back * @throws SQLException */ public void setRollbackOnly() { logger.debug("Context execute setRollbackOnly() !!"); Connection connect = null; try { DB2ConnectFactory factory = new DB2ConnectFactory(); connect = factory.getConn(); logger.debug("Context get connect " + connect.hashCode());
if(connect != null) connect.rollback(); } catch (Exception e) { e.printStackTrace(); } finally { this.clostConnection(connect); //q里关闭数据库q接 } }
可是q是"异常"情况下的处理程Q如果正常执行呢Q?BR>刚开始我惛_在CleanUp()Ҏ里,但又一想不行,因ؓ正常执行的流E需要做两个工作 1。将Commit状态更Cؓtrue,q提交连?BR>2。关闭数据库q接
关键是关闭数据库的q接在哪里写Q!现在写在CleanUp()不合适,因ؓ每一个WorkStore的方法都要默认(E序已经写死?我可不想重蝲它的所有的ҎQ!Q的关闭数据库连接! 仔细的分析了一下,其实有两个方法可以做?BR>1。编写Proxyc?BR>2。重载所有AbstractWorkflow中设计到事务的方法,Q本来可以重载transitionWorkflow但是Ҏ的类型却为private?!Q在它的Ҏ下增加一?提交"的方法。比如这?/P>
try { //transition the workflow, if it wasn't explicitly finished, check for an implicit finish if (!transitionWorkflow(entry, currentSteps, store, wf, action, transientVars, inputs, ps)) { checkImplicitFinish(id); }
dosubmit();
} catch (WorkflowException e) { context.setRollbackOnly(); // q里调用WorkContext对象的setRollbackOnly()ҎQ执行事务的回滚 throw e; }
可以看到Ҏ2比较"?Q看来下一步即使编写方?的实?/P>
]]> JDBCWorkflow不支持Sequence http://m.tkk7.com/killvin/archive/2006/03/02/33310.htmlkillvin killvin Thu, 02 Mar 2006 13:01:00 GMT http://m.tkk7.com/killvin/archive/2006/03/02/33310.html 早上的时间被该死的WorkflwoStore里的主键生成{略Q?主键生成{略"来源于Hibernate文Q,该死的Sequence,从文资料上看到DB2是支持Sequence的,按照db2的文我执行了如下的语句Q?BR>create sequence seq_os_wfentry start with 10 increment by 10; create sequence seq_os_currentsteps; 执行-ok
可是我以前不太了解Sequence的概念,q片资料倒是很有价?BR>http://www-128.ibm.com/developerworks/db2/library/techarticle/dm-0407zhang/ 不过我以为查询Sequence只需要执行SELECT NEXT VALUE FOR seq_os_wfentry ok了,可是谁知道L报错Q!在比较仔l的看了q片文章之后发现Q其实根本就无法执行q条SQLQ而需要这?BR>INSERT INTO EMPLOYEE ( SERIALNUMBER, FIRSTNAME, LASTNAME, SALARY) VALUES(NEXTVAL FOR EMPSERIAL, 'Martin', 'Wong', 1000.00)
可是看看JDBCWorkflowStore的实玎ͼq里是JDBCWorkflowStore的主键生成策略! protected long getNextEntrySequence(Connection c) throws SQLException { if (log.isDebugEnabled()) { log.debug("Executing SQL statement: " + entrySequence); }
PreparedStatement stmt = null; ResultSet rset = null;
try { stmt = c.prepareStatement(entrySequence); rset = stmt.executeQuery(); rset.next();
long id = rset.getLong(1);
return id; } finally { cleanup(null, stmt, rset); } }
c.prepareStatement(entrySequence) Q?其实执行了一条SQL语句Q所以看来JDBCWorkflowҎ不支持Sequence生成{略Q!
该死的实现方式,看来我要重蝲其实现方式,不过说真的JDBCWorkflow的编码h员其实水q不匝地Q?/P>
]]> 心OSPropertySet Q?PropertySet http://m.tkk7.com/killvin/archive/2006/03/02/33309.htmlkillvin killvin Thu, 02 Mar 2006 13:00:00 GMT http://m.tkk7.com/killvin/archive/2006/03/02/33309.html ]]>
վ֩ģ壺
aɫëƬƵ |
ɫۺ |
ŷa߹ۿ |
һ߹ۿ |
99þþù |
ҹҹþ |
ѿaɫƬ |
þ߿߿ |
Ʒ벻߲ |
ĻƷ |
|
պƬѹۿվ |
þþƷ7ҹa |
Ʒѹۿ |
99þù-99þù
99þùĻ
|
99ƷƵ |
AVѲ |
ްv2017 |
һ |
ձһ |
ʹA18Ƭ |
AVƬ߹ۿ |
ƷƷ |
avþþƷ |
vavaպ߹ۿ |
ѿԿƵƵsɫ |
97ƷȫƵ
|
ձvaһ |
AvרDVD
|
ĻӰ |
ѹۿһ |
þùһ
|
߹ۿר |
Ʒ91 |
ɬɬɫۺ |
ƵŷƵ |
Ʒ |
ۺһҳ
|
ѸƵ |
hƵѹۿ |
Ʒһ |