- 浏览: 3514777 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
wanglf1207:
EJB的确是个不错的产品,只是因为用起来有点门槛,招来太多人吐 ...
weblogic-ejb-jar.xml的元素解析 -
qwfys200:
总结的不错。
Spring Web Flow 2.0 入门 -
u011577913:
u011577913 写道也能给我发一份翻译文档? 邮件437 ...
Hazelcast 参考文档-4 -
u011577913:
也能给我发一份翻译文档?
Hazelcast 参考文档-4 -
songzj001:
DbUnit入门实战
Sometimes something that appears trivial turns out to be a lot more involved. Doing JMS request/reply from an EJB is such a case. Let's take a look...
Request/reply
JMS can be used as a form of inter process communication. JMS is meant for asynchronous calls, but it can also used for synchronous calls. In that case, the first process sends a message to a queue or topic, and waits until another process has replied to the message. The reply is sent to a different queue or topic. Advantages of using JMS for interprocess communication is that the two processes are completely decoupled. The two processes only need to agree on what is in the message.
Synchronous communication in JMS is also called request/reply.
The JMS api provides two helper classes to make request/reply easier. They are the QueueRequestor and TopicRequestor classes. Here is an example of how they can be used:
QueueConnection c = (QueueConnectionFactory) (new InitialContext().lookup("qcf")); QueueSession s = c.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue q = (Queue) (new InitialContext().lookup("requestqueue")); QueueRequestor r = new QueueRequestor(s, q); Message reply = r.request(s.createTextMessage("1233442342")); c.close();
Looks simple, right? However, when this code is used in a typical EJB, it will likely not work. Why not? Is there something wrong with the QueeuRequestor ? Well, yes, yet that is not the problem. Let's look at the implementation of the QueueRequestor :
public class QueueRequestor { QueueSession session; Queue queue; TemporaryQueue tempQueue; QueueSender sender; QueueReceiver receiver; public QueueRequestor(QueueSession session, Queue queue) throws JMSException { this.session = session; this.queue = queue; tempQueue = session.createTemporaryQueue(); sender = session.createSender(queue); receiver = session.createReceiver(tempQueue); } public Message request(Message message) throws JMSException { message.setJMSReplyTo(tempQueue); sender.send(message); return receiver.receive(); } public void close() throws JMSException { session.close(); tempQueue.delete(); } }
So we can rewrite the above code sample as follows:
QueueConnection c = (QueueConnectionFactory) (new InitialContext().lookup("qcf")); QueueSession s = c.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue q = (Queue) (new InitialContext().lookup("requestqueue")); Message request = s.createTextMessage("1233442342"); request.setJMSReplyTo(s.createTemporaryQueue(); s.createSender(q).send(m); Message reply = s.createReceiver(q).receive(); c.close();
There's nothing obviously wrong with that, so why does this typically not work when this code is in an EJB?
Transactions
Before we look at the explanation of why the above code doesn't work in an EJB, let's review some basics about application servers and JMS servers. A JMS server is typically a stand alone process. Applications can communicate with this server using a client runtime. The client runtime implements the JMS API as defined in the JMS specification. If you're building a stand-alone application, you use the client runtime directly. Example, when you're using the JMS server shipped with Java CAPS you would be using com.stc.stcjms.jar to talk to the server process (stcms.exe ). The client runtime implemented in com.stc.jms.stcjms.jar implements the JMS api and communicates with the server (stcms.exe ) over tcp/ip sockets.
However, when your code lives in an EJB, you're not using the JMS client runtime directly. For example, when you obtain a connection factory from JNDI in an EJB, you will not get the connection factory object that belongs to the JMS provider itself, but you get a factory that is implemented by a resource adapter. As of J2EE 1.4, the interfacing between the application server and JMS is done through a Resource Adapter. In the example for Java CAPS, you would obtain a connection factory implemented by the JMSJCA resource adapter instead of the com.stc.jms.client.STCQueueConnectionFactory that belongs to the STCMS client runtime.
The Resource Adapter acts like a wrapper around the objects that are implemented in the JMS client runtime. One of the responsibilities of the Resource Adapter is to make sure that JMS acts like a transactional resource. This means that JMS connection (technically, the JMS session) is enlisted with the transaction manager of the applicaiton server. In fact, under the covers the Resource Adapter really uses an XASession rather than an AUTO_ACKNOWLEDGE session. What effect did it have to specify the arguments to
c.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
In fact, these arguments are ignored, so they have no effect whatsoever.
Use of JMS in a transaction
Let's say that we have a bean managed EJB (BMT) with the following code:
EJBContext ctx = ...; ctx.getUserTransaction().begin();
QueueConnection c = (QueueConnectionFactory) (new InitialContext().lookup("qcf")); QueueSession s = c.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue q = (Queue) (new InitialContext().lookup("requestqueue")); Message request = s.createTextMessage("1233442342"); request.setJMSReplyTo(s.createTemporaryQueue(); s.createSender(q).send(m); Message reply = s.createReceiver(q).receive(); c.close(); ctx.getUserTransaction().commit();
The message will be sent to the queue only when the statement getUserTransaction().commit() is executed. Before this statement, the message will not be visible anywhere. So when the receive() method is executed, the message was really not sent to the queue. The other process never gets the request, and hence, a reply will never be received. Since no timeout is specified, the application simply hangs.
Now that we know that, the solution is pretty simple: just commit the transaction before receiving the reply.
ctx.getUserTransaction().begin();
QueueConnection c = (QueueConnectionFactory) (new InitialContext().lookup("qcf")); QueueSession s = c.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue q = (Queue) (new InitialContext().lookup("requestqueue")); Message request = s.createTextMessage("1233442342"); request.setJMSReplyTo(s.createTemporaryQueue(); s.createSender(q).send(m); ctx.getUserTransaction().commit();
ctx.getUserTransaction().begin(); Message reply = s.createReceiver(q).receive(); c.close(); ctx.getUserTransaction().commit();
It depends on the business logic if you can simply split up the transaction in two. Perhaps something else happens in the transaction, for example you could update a database in the same transaction. In that case, you may not want to commit the transaction yet! How can we deal with that situation?
The solution would be to suspend the transaction, create a new
transaction, send the request, commit the new transaction, unsuspend
the first transaction, and continue. Sounds complicated? It is, but it
can be simplified using an EJB: simply add a new business method to the
EJB, make sure that the method's trans-attribute
is set to NotSupported
.
Next, instantiate a new EJB and call that method. By calling that
method, the transaction will automatically be suspended.
Note that it is crucial to instantiate a new EJB: if you just call the new business method from the same EJB instance, the application server will not intercept the method and will not suspend the transaction.
When the EJB is CMT
Pretty much the same goes if the EJB is not BMT but CMT. If a transaction was started, the same deadlock occurs: the send() is never committed until the transaction is committed, so the receive() method will never receive a reply. In that case, add a new business method and make sure that the trans-attribute is set to RequiresNew . The application server will then suspend the main transaction and start a new transaction automatically. As with BMT, make sure that you call the new business method on a new instance of the EJB rather than on the same instance.
When there is no transaction
What happens if there is no transaction when you call send()
? Well, that depends on
the implementation. The specification is not clear on what should
happen when an XA resource is used outside of a transaction. The JMS
CTS implies that the behavior should be that of auto-commit (or AUTO_ACKNOWLEDGE
in JMS
parlance). CTS stands for Compliance Test Suite. The CTS for JMS
consists of a few thousand tests. Every implementation that claims
that be compliant with the JMS spec must pass these tests. Hence,
most implementations, including the one that ships with Java CAPS will
exhibit AUTO_ACKNOWLEDGE
behavior. In that case, the above code will work and the QueueRequestor
can be used.
What about the QueueRequestor?
Can't we use the QueueRequestor with transactions? The simple answer is no. Why did the Resource Adapter not take care of this? The problem is that the QueueRequestor is implemented by the JMS api, and not by the JMS provider or Resource Adapter. Perhaps this is another example why it is generally a bad idea to provide implementation classes in API-s?
There's another problem with the QueueRequestor class: there is no way to specify a timeout value. You would probably prefer a timeout exception rather than having a hanging application.
Conclusion
Knowing what happens under the covers explains why request/reply cannot work in a single transaction. Simply post the request in a separate transaction.
发表评论
-
字符串分割--java中String.split()用法
2013-03-06 14:25 74169在java.lang包中有String.sp ... -
用 HttpServletResponseWrapper 实现 Etag 过滤器
2012-07-09 16:58 3781原文出处:http://blog.chenlb.com/200 ... -
Fitnesse使用
2012-05-05 13:27 23529Fitnesse 的使用 一,介绍 Fitnesse是一种 ... -
Customizing the new FitNesse parser
2012-05-05 13:13 2150FitNesse began its life using ... -
java application中内嵌ActiveX控件
2011-11-14 15:57 5538我这里用的是SWT/JFace开发application,SW ... -
Google Java Developer Tools Downloads
2011-08-09 00:04 2364WindowBuilder Pro原来叫WindowB ... -
Jalita
2011-08-06 00:49 1584Jalita (Java light terminal ada ... -
【转】用Java写字符终端界面
2011-07-29 13:13 2135终端界面GUI开源项目charva。 这个框架让你可以用开发 ... -
[转]mybatis下的分页,支持所有的数据库
2011-07-21 13:21 14858大 家都知道,mybatis的自带分页方法只是逻 ... -
Java framework for text- & console-based forms?
2011-07-21 01:06 1733charva jcurses JNA , ... -
JNA(Java Native Access)学习入门
2011-07-21 01:04 22698Java Native Access 项目 在 ... -
JAVA上加密算法的实现用例
2011-06-25 12:38 4898来源:www.ibm.com ... -
如何将GlassFish作为Windows服务运行
2011-05-18 23:21 2399本文档来自GlassFish官方网站,详细介绍了将 G ... -
JAVA UDP打洞必备知识点---NAT
2011-05-05 12:56 8754一、引言 RFCl631 ... -
Keystore概念,Keytool工具使用
2011-04-28 16:20 2921近来由于项目需要做Single Sign On, 研究了一 ... -
利用Eclipse Profile Plugin监控分析Tomcat性能
2011-04-18 16:14 3715目前新版本的Eclipse在启动应用服务器的时候有一个新的选 ... -
m2eclipse: Eclipse is running in a JRE, but a JDK is required
2011-02-04 23:43 2557Eclipse 安装了Maven插件,启动Eclipse ... -
利用JNative实现Java调用动态库
2010-10-18 00:43 2115由于项目要求,需要用J ... -
RHEL5支持大内存
2010-10-08 16:19 3029安装 RHEL 5 ,硬件为 4G 内存,安装完成 ... -
Windows Server 2003 和 Windows 2000 提供大内存支持
2010-10-08 16:19 1868本文介绍物理地址扩展 ...
相关推荐
- **交互模式:** 描述了JMS支持的请求/回复(Request/Reply)消息交互模式,这是一种常见的通信模式,允许客户端发送请求并等待响应。 综上所述,JMS规范1.1(中文版)详细阐述了Java消息服务的核心概念、架构设计...
实例119 Request-Reply模式的JMS应用 421 实例120 使用Java IDL 426 实例121 EJB与CORBA的交互 430 实例122 基于EJB的真实世界模型 433 实例123 EJB的商业应用——定购单 447 第11章 Java 2 Platform Micro Edition...
Reply模式的JMS应用 421 实例120 使用Java IDL 426 实例121 EJB与CORBA的交互 430 实例122 基于EJB的真实世界模型 433 实例123 EJB的商业应用——定购单 447 第11章 Java 2 Platform Micro Edition...
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
kolesar_3cd_01_0716
latchman_01_0108
matlab程序代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
pimpinella_3cd_01_0716
petrilla_01_0308
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
内容概要:本文档由张卓老师讲解,重点探讨DeepSeek的技术革新及强化学习对未来AI发展的重要性。文章回顾了AI的历史与发展阶段,详细解析Transformer架构在AI上半场所起到的作用,深入介绍了MoE混合专家以及MLA低秩注意机制等技术特点如何帮助DeepSeek在AI中场建立优势,并探讨了当前强化学习的挑战和边界。文档不仅提及AlphaGo和小游戏等成功案例来说明强化学习的强大力量,还提出了关于未来人工通用智能(AGI)的展望,特别是如何利用强化学习提升现有LLMs的能力和性能。 适用人群:本资料适宜对深度学习感兴趣的研究人员、开发者以及想要深入了解人工智能最新进展的专业人士。 使用场景及目标:通过了解最新的AI技术和前沿概念,在实际工作中能够运用更先进的工具和技术解决问题。同时为那些寻求职业转型或者学术深造的人提供了宝贵的参考。 其他说明:文中提到了许多具体的例子和技术细节,如DeepSeek的技术特色、RL的理论背景等等,有助于加深读者对于现代AI系统的理解和认识。
有师傅小程序开源版v2.4.14 新增报价短信奉告 优化部分细节
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
商城二级三级分销系统(小程序+后台含源码).zip
li_3ck_01b_0918
nicholl_3cd_01_0516
媒体关注度是一个衡量公众对某个事件、话题或个体关注程度的重要指标。它主要反映了新闻媒体、社交媒体、博客等对于某一事件、话题或个体的报道和讨论程度。 媒体监督的J-F系数(Janis-Fadner系数)是一种用于测量媒体关注度的指标,特别是用于评估媒体对企业、事件或话题的监督力度。J-F系数基于媒体报道的正面和负面内容来计算,从而为公众、研究者或企业提供一个量化工具,以了解媒体对其关注的方向和强度。 本数据含原始数据、参考文献、代码do文件、最终结果。参考文献中JF系数计算公式。 指标 代码、年份、标题出现该公司的新闻总数、内容出现该公司的新闻总数、正面新闻数全部、中性新闻数全部、负面新闻数全部、正面新闻数原创、中性新闻数原创、负面新闻数原创,媒体监督JF系数。
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!