1

JMS API 声明了许多通用和具体的接口(例如,Connection 与 QueueConnection)。据记载,最佳实践是使用通用接口(例如 Session 而不是 QueueSession)。如果我的应用程序同时使用队列和主题,并且我要笼统地说:Connection-->Session-->Topic/Queue,并且假设支持所有 JMS 实现(TiBCO、WebLogic、Websphere 等)可以我假设使用通用实体将适用于开箱即用的两种类型(队列和主题)?

为了强调我的观点:我可以假设所有实现者都实现了 java.jms.Connection 接口并且可以对这两种类型都有效吗?

谢了,兄弟们

4

2 回答 2

1

java.jmx.Connection 在 JMS 1.1 规范中不是可选的,因此有效的实现应该可以工作。JMS 中的大多数可选内容列在JMS 1.1 规范的第 8 章“JMS 应用服务器设施”中。

值得注意的一点是,根据规范,连接的ExceptionListener是可选的。

我想这里的要点是,您确实应该根据规范审查您的设计和实现,以确保您不依赖任何可选功能,并且您应该在拥有可移植实现方面相当安全。

于 2010-01-24T12:30:47.450 回答
1

我不明白为什么在之前的回复和讨论中假设非持久订阅不可移植。这是一个代码示例(下载链接),它既不耐用又符合 JMS 1.1。

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 上同样有效(但在 QMgr 上的设置略有不同,因为 pub/sub 不再需要单独的代理组件)。

除此之外,原始响应者是正确的,只要应用程序符合 JMS 规范,它就应该在任何符合 JMS 的传输中运行。尽管如此,它并没有考虑到供应商传输实现中的差异会通过 JMS 抽象冒泡影响您的代码。

例如,JMS 提供了一个多级异常,其中顶级是 JMS 异常,下一级是链接异常。这是供应商可以在其中放置供应商特定错误代码的链接异常。例如,在 WMQ 中,您可能会收到指示队列已满的链接异常或告诉您队列已损坏的链接异常。其中之一是暂时的,重试行为是适当的,而另一个表示致命错误。如果应用程序不理解链接异常中的错误,它就无法区分。

一些旨在便携的应用程序通过简单地将所有异常视为致命的来处理这个问题。它们关闭所有对象和连接并重新初始化。我还看到了一种方法,开发人员放弃了所有可移植性尝试,并在链接的异常中查找特定于供应商的代码。这些方法之间的某个地方是具有供应商特定填充程序或包装 JMS 对象的子类的商店,因此应用程序可以保持可移植性,但仍能适当地响应特定于供应商的异常。

即使假设这些事情不是问题,了解供应商如何解释和实施规范仍然很重要。例如,当代理失败时,某些传输会无缝地让客户端失败。开发人员可能会依赖该行为并从他们的应用程序中忽略任何重新连接逻辑。但是,如果问题不在于代理,而在于客户端的网络连接怎么办?应用程序在尝试故障转移时会挂起多长时间?用户会看到什么?该规范没有解决这些问题,可移植性只能让您到目前为止。

因此,一定要了解规范并编写可移植代码,还要了解供应商对规范的实现以及该实现的可移植性边界在哪里。在任何情况下,该边界都不存在于持久订阅和非持久订阅之间。

于 2010-12-22T17:03:53.177 回答