瞅瞅Infinispan事务管理源码是啥样的

希望可以更直观地了解Infinispan的事务管理,(提一点Infinispan是遵循LGPL,具体开源协议参阅《各种开源协议介绍 BSD、Apache Licence、GPL V2 、GPL V3 、LGPL、MIT》)本文重点在JTA的使用

在上一篇《Ehcache 事务管理源码探析》中针对Ehcache的JTA事务管理说明了一番,是在JBoss服务器环境下使用JTA。同样在Infinispan中也具有获取JBoss容器事务管理器的能力,即配置事务查找器为 JBossTransactionManagerLookup,实现源码如下:

/**
* Uses JNDI to look-up the {
@link TransactionManager} instance from "java:/TransactionManager".
*
*
@author Bela Ban, Aug 26 2003
*
@since 4.0
*/
public class JBossTransactionManagerLookup implements TransactionManagerLookup {

public TransactionManager getTransactionManager() throws Exception {
String as7Location = "java:jboss/TransactionManager";

InitialContext initialContext = new InitialContext();
try {
// Check for JBoss AS 7
return (TransactionManager) initialContext.lookup(as7Location);
} catch (NamingException ne) {
// Fall back and try for AS 4 ~ 6
String legacyAsLocation = "java:/TransactionManager";

try {
// Check for JBoss AS 4 ~ 6
return (TransactionManager) initialContext.lookup(legacyAsLocation);
} catch (NamingException neAgain) {
throw new ConfigurationException("Unable to locate a transaction manager in JNDI, either in " + as7Location + " or " + legacyAsLocation);
}

} finally {
Util.close(initialContext);
}
}
}

在此就不再细说了,关键看另外一种在没有JBoss环境下的JTA事务管理该是怎样的。即配置Infinispan事务管理查找器为:JBossStandaloneJTAManagerLookup。看源码:

/**
* JTA standalone TM lookup.
*
*
@author Jason T. Greene
*
@since 4.0
*/
public class JBossStandaloneJTAManagerLookup implements TransactionManagerLookup {
private Method manager, user;
private static final Log log = LogFactory.getLog(JBossStandaloneJTAManagerLookup.class);

@Inject
public void init(Configuration configuration) {
// The TM may be deployed embedded alongside the app, so this needs to be looked up on the same CL as the Cache
try {
manager = Util.loadClass("com.arjuna.ats.jta.TransactionManager", configuration.getClassLoader()).getMethod("transactionManager");
user = Util.loadClass("com.arjuna.ats.jta.UserTransaction", configuration.getClassLoader()).getMethod("userTransaction");
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}

public TransactionManager getTransactionManager() throws Exception {
TransactionManager tm = (TransactionManager) manager.invoke(null);
if (log.isInfoEnabled()) log.retrievingTm(tm);
return tm;
}

public UserTransaction getUserTransaction() throws Exception {
return (UserTransaction) user.invoke(null);
}
}

看上去似乎很简单,Infinispan使用该种方式也很简单,引入jbossjta.jar即可。如此对Infinispan缓存的事务管理功能就有了,但是有一个疑问,怎么与数据库的事务管理结合起来呢?我们知道之前《JBoss下的JTA使用理解》中借助JBoss容器只需配置数据源就可以了,这该怎么办呢?对事务类型有疑问可参看 事务处理总结(JDBC事务|JTA事务|容器事务

继续

让Infinispan使用JBoss JTA事务,引入jbossjta.jar,根据JTA规范,集成数据库的事务,应该让JDBC驱动实现JTA中参与者应该实现的接口,主要是XAResource,经测试MySQL JDBC驱动包括XA接口实现。之前是通过在JBoss中写好配置文件,从JNDI获取XA数据源,现在不借助JBoss容器,在应用中创建XADataSource,示例如下:

package database.mysql.xa;

import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;

/**
*
@author yaohw
*
*/
public class XAUtil {

public static MysqlXADataSource getXADataSource(){
MysqlXADataSource xaDS = new MysqlXADataSource();
xaDS.setDatabaseName("mytest");
xaDS.setServerName("127.0.0.1");
xaDS.setPortNumber(3306);
xaDS.setUser("root");
xaDS.setPassword("root");
return xaDS;
}

public static void main(String[] args) {
MysqlXADataSource xaDS = getXADataSource();
System.out.println(xaDS);
}
}

接着是重要的一步,该如何让JTA事务管理将该数据源的操作纳入到管理范围内。寻寻觅觅看到Transaction接口中有一个方法: boolean enlistResource(javax.transaction.xa.XAResource arg0),好!就是他了。同样还有一个相反的操作boolean delistResource(javax.transaction.xa.XAResource arg0, int arg1) 。

具体获取连接以及XAResource的方式就比较简单,不赘述。
接下来测试:

try {
tm.begin();
value = cache.get(key);
if(value == null){
value = adminDAO.findAdminById(Integer.parseInt(key.toString()));
cache.put(key, value);
}
System.out.println("get after put :"+cache.get(key));
Admin a = new Admin();
a.setPassword("hello");
a.setUsername("boy");
adminDAO.addAdmin(a);

// rollback();
tm.commit();
System.out.println("get after rollback :"+cache.get(key));
} catch (Exception e1) {
e1.printStackTrace();
rollback();
}

现在总算可以在离开JBoss的怀抱,数据库和缓存同生同灭了。

posted @ 2012-02-10 14:16  echx  阅读(1012)  评论(0编辑  收藏  举报