假设对象 A 的 methodA() 启动一个事务,然后调用对象 B 的 methodB()(对象 B 将得到一个 JDBC 连接并更新数据库)。B 获得的连接将被自动征调到 A 创建的事务中。容器怎么知道要做这件事?当事务启动时,事务上下文与执行线程关联在一起。当 A 创建事务时,A 在其中执行的线程与该事务关联在一起。由于本地方法调用与主调程序(caller)在同一个线程内执行,所以 A 调用的每个方法也都在该事务的上下文中。如果对象 B 其实是在另一个线程,甚至另一个 JVM 中执行的 EJB 组件的存根,情况会怎样?远程对象 B 访问的资源仍将在当前事务中被征用。EJB 对象存根(在主调程序的上下文中执行的那部分)、EJB 协议(IIOP 上的 RMI)和远端的骨架对象协力要使其透明地发生。存根确定调用者是不是正在执行一个事务。如果是,事务标识,或者说 Xid,被作为 IIOP 调用的一部分与方法参数一起传播到远程对象。(IIOP 是 CORBA 远程-调用协议,它为传播执行上下文(比如事务上下文和安全性上下文)的各种元素而备;关于 RMI over IIOP 的更多信息,请参阅参考资料。)如果调用是事务的一部分,那么远程系统上的骨架对象自动设置远程线程的事务上下文,这样,当调用实际的远程方法时,它已经是事务的一部分了。(存根和骨架对象还负责开始和提交容器管理的事务。) 事务可以由任何 J2EE 组件来启动 — 一个 EJB 组件、一个 servlet 或者一个 JSP 页面(如果容器支持的话,还可以是一个应用程序客户机)。这意味着,应用程序可以在请求到达时在 servlet 或者 JSP 页面中启动事务、在 servlet 或者 JSP 页面中执行一些处理、作为页面逻辑的一部分访问多个服务器上的实体 bean 和会话 bean 并使所有这些工作透明地成为一个事务的一部分。
解决方案 »
- 菜鸟问题
- 急急急 java搜索引擎lucene
- HelloWorld的webservice为什么报java.lang.ClassNotFoundException
- struts-menu的javascript问题
- 高分求解:.net 2003 编写的客户端应用程序可以访问 Unix平台上的WebLogic 应用服务器上的 Web Service 吗
- 发email程序出错的问题.
- Spring菜菜的问
- 小弟不才,请大哥大姐们给个意见。。。。。。。。。。。。。。。
- myRyxxRemote bb=(myRyxxRemote)i.next()运行报错java.lang.ClassCastException
- 关于package的提问,马上结贴
- calendar类中,日期滚动的方法是怎么用的?(在线等待)
- 请教错误原因:"Can't rebind anything but a replica-aware stub"这样的错误是怎样产生的?谢谢
当调用begin时,创建一个新事务,并将其放入事务池(是一个Map对象)中,其键值就是线程对象。大概是这样的:TransactionManager.getTranactionPool().put(System.currentThread(),new TransactionObject());
当事务资源如会话Bean需要用到当前事务对象时,就调用
TransactionManager.getTranactionPool().get(System.currentThread());来获得。这也就是为什么EJB容器规定不能在容器中启动新线程的原因之一了(因为容器不好控制(也不是不可能)事务在新线程中传播)。
在JBoss里,你提到的应用是这样实现的:
首先,你要明确:你用到到的那几个bean位于同一个容器中(跨容器的事务传播JBoss3.x不支持,JBoss4.x我不懂),那么这几个bean的调用将位于同一个线程中。
而事务管理器TxManager使用了ThreadLocal类型的变量来保存特定线程的事务信息(包括事务对象),这样那几个位于同一线程的调用就共有了同一个事务对象,也就是说被纳入到同一个事务了。就着么简单!因为在取得资源时判断当前是否有事务的方式,就是判断TxManager中的ThreadLocal变量是否保存了事务对象。
而对于客户端调用EJB方法时的事务传播,因为事务对象其实是存在于容器中的,所以客户端只需在调用EJB方法时顺带捎上事务的全局ID,容器根据改ID取出相应的事务对象,就将客户端和EJB方法纳入到同一个事务中了。这其实是一种变形的跨JVM传播事务,但不是真正的跨JVM传播事务。