JMS API声明了许多常规和具体接口(例如,Connection vs. QueueConnection)。 据记载,最佳实践是使用通用接口(例如Session而不是QueueSession)。如果我的应用程序同时使用队列和主题,那么我就是通用的,那就是:Connection - > Session - > Topic / Queue,并假设支持所有JMS实现(TiBCO,WebLogic,Websphere等... )我可以假设使用通用实体将适用于两种类型的开箱即用(队列和主题)?
强调我的观点:我可以假设所有实现者都实现了java.jms.Connection接口,并且可以适用于这两种类型的一般事项吗?
谢谢, 盖
答案 0 :(得分:1)
java.jmx.Connection在JMS 1.1规范中不是可选的,因此有效的实现应该有效。 JMS中的大多数可选内容列在JMS 1.1 spec的第8章“JMS应用程序服务器设施”中。
值得注意的一点是,根据规范, Connection 的 ExceptionListener 是可选的。
我想这里的要点是你真的应该根据规范检查你的设计和实现,以确保你不依赖于任何可选功能,并且你应该在便携式实现方面相当安全。
答案 1 :(得分:1)
我不明白为什么在之前的回复和讨论中假设非持久订阅不可移植。这是一个非持久且符合JMS 1.1的代码示例(download link)。
session = connection.createSession(transacted, Session.AUTO_ACKNOWLEDGE);
myDest = (Destination)ctx.lookup(dLookup);
MessageConsumer myConsumer = session.createConsumer(myDest);
Message inMessage = null;
do {
inMessage = myConsumer.receive(10000);
if( inMessage instanceof TextMessage ) {
System.out.println( "\n" + "Got message: "+((TextMessage) inMessage).getText());
}
session.commit();
} while ( inMessage != null );
myConsumer.close();
在上一个示例中,订阅者不仅非持久,而且无论是从JNDI查找中检索的主题还是队列都无关紧要。上面的链接是一篇文章,其中包含为WMQ v6编写的工作代码示例和JNDI对象,但它们在WMQ v7上同样运行良好(但由于pub / sub不再需要单独的代理组件,因此QMgr的设置略有不同)。 p>
除此之外,原始响应者是正确的,只要应用程序符合JMS规范,它应该在任何符合JMS的传输中运行。这是真的,它没有考虑到供应商的传输实现的差异在JMS抽象中冒出来影响你的代码。
例如,JMS提供了一个多级异常,其中顶级是JMS异常,下一级是链接异常。它是供应商可以放置特定于供应商的错误代码的链接异常。例如,在WMQ中,您可能会收到一个链接异常,指示队列已满或链接异常,告知您队列已损坏。其中一个是瞬态和重试行为是适当的,而另一个表示致命错误。如果应用程序不理解链接异常中的错误,则无法区分。
一些旨在便携的应用程序通过简单地将所有异常视为致命来处理此问题。它们关闭所有对象和连接并重新初始化。我还看到了一种方法,开发人员放弃所有可移植性尝试,并查看特定于供应商的代码的链接异常。这些方法之间的某个地方是具有特定于供应商的垫片或包装JMS对象的子类的商店,因此应用程序可以保持可移植性,但仍然适当地响应特定于供应商的异常。
即使假设这些事情不是问题,了解供应商如何解释和实施规范仍然很重要。例如,某些传输在代理失败时无缝地使客户端失败。开发人员可能依赖于该行为并省略其应用程序中的任何重新连接逻辑。但是如果问题不是经纪人而是在客户的网络连接怎么办?应用程序挂起多长时间尝试进行故障转移以及用户看到了什么?规范没有解决这些问题,可移植性只能让你到目前为止。
因此,无论如何都要了解规范和编写可移植代码,还要了解供应商对规范的实现以及可移植性的边界在于该实现。在任何情况下,该边界都不在持久订阅和非持久订阅之间。