关于分布式事务处理的问题

下面的代码能将sessionA和sessionB中的两方法作为同一事务处理。
try{
InitialContext initial=new InitialContext();
UserTransaction ut=(UserTransaction)initial.lookup("java:comp/UserTransaction"); //1
SessionAHome aHome=(SessionAHome)initail.lookup("SessionA"); //2
SessionA a=aHome.create();
SessionBHome bHome=(SessionBHome)initail.lookup("SessionB"); //2
SessionB b=bHome.create();

ut.begin(); //3
a.fa();
b.fb();
ut.commit(); //4

}
catch(.....){
ut.rollback();
}

1处得到一UserTransaction对象ut,2处分别得到两个sessionbean的对象,但是ut,与a,b之间并没有关联,那当3处ut.begin();时,jts如何知道将事务对象在a.fa()中所操作的资源管理器与b.fb()中所操作的资源管理器之间传播,又如何当4处ut.commit()时,对这两个资源管理器进行两阶段提交,这其中有什么澳妙吗?


奥妙在于存在于它们之间的但不易被人发觉的对象,那就是----线程,JTA规范中明确地描述了使用线程来传播事务。当调用ut.begin()时,事务管理器创建一个新的事务对象,并将其绑定到当前线程上,这样事务资源就可以从当前执行的线程获得事务对象进行操作。

这个要根据你申明的B的事务属性来决定

ejb的事务属性包括required requirednew support notsupport
mandatory never

假设A的事务为T1,B的事务为T2,下面就是B的事务将会根据B的事务属性以及A的事务状态,采用不同的事务状态。


B的属性 A的事务 B的事务
required none T2
T1 T1
requirednew none T2
T1 T2
supports none none
T1 T1
notsupport none none
T1 none
mandatory none error
T1 T1
never none none
T1 error

而且RMI可以传递事务上下文,才能联系不同VM的线程

谢谢上面各位,本人才疏学浅,能不能将详细一点,如怎样对线程进行绑定,是在编译时还是在运行时进行的,我对这种机理觉得太神奇。

说穿了就不会觉得神奇了( 有点像变魔术:-) ),这是由JTA服务器内部实现的,我可以说一下大致的原理(远程事务的部分就不说了(说来话长))。
当调用begin时,创建一个新事务,并将其放入事务池(是一个Map对象)中,其键值就是线程对象。大概是这样的:TransactionManager.getTranactionPool().put(System.currentThread(),new TransactionObject());
当事务资源如会话Bean需要用到当前事务对象时,就调用
TransactionManager.getTranactionPool().get(System.currentThread());来获得。

这也就是为什么EJB容器规定不能在容器中启动新线程的原因之一了(因为容器不好控制(也不是不可能)事务在新线程中传播)。


高人呀,谢谢。
还有能不能提供这方面的资料

jta规范有提到,但没有涉及具体实现。

http://java.sun.com/products/jta/ 这里下载规范

Yes, you are right, The transaction manager will automated create a transaction object when we invoke the ut.begin(), then will put the current thread handle and the object to the map.
Ok, now, anyone object in current thread can use the transaction object through thread handle, and can deliver a true-
false result to the transaction object.

在CORBA的OTS中,事物通过在网络请求中传输事物ID,将事物标示从客户端传送到服务器端,那么在EJB/JTA中,是如何将事物标示在网络中传送的?

J2EE的RMI就是不也是基于IIOP,和CORBA差不多

在JBoss里,你提到的应用是这样实现的:
首先,你要明确:你用到到的那几个bean位于同一个容器中(跨容器的事务传播JBoss3.x不支持,JBoss4.x我不懂),那么这几个bean的调用将位于同一个线程中。
而事务管理器TxManager使用了ThreadLocal类型的变量来保存特定线程的事务信息(包括事务对象),这样那几个位于同一线程的调用就共有了同一个事务对象,也就是说被纳入到同一个事务了。就着么简单!因为在取得资源时判断当前是否有事务的方式,就是判断TxManager中的ThreadLocal变量是否保存了事务对象。
而对于客户端调用EJB方法时的事务传播,因为事务对象其实是存在于容器中的,所以客户端只需在调用EJB方法时顺带捎上事务的全局ID,容器根据改ID取出相应的事务对象,就将客户端和EJB方法纳入到同一个事务中了。这其实是一种变形的跨JVM传播事务,但不是真正的跨JVM传播事务。

其实J2EE容器隐藏了很多细节,跨VM或数据库之间的事务性保证是由内部的资源管理器对参与事务的每个资源都进行征用登记,让我们感觉不到他的存在,显得很神奇似的.

大家可参考年初的DevelopeWorks专刊第二期上的文章,里面有很详细的描述.

Transaction接口中的方法分为:enlistResource和registerSynchronization
这里面的Resource和Synchronization有什么区别.

请问Jboss中如何在客户端(不同的VM)中启动Transaction? 我一直没有成功