Java JMS接口和实现

Java JMS接口和实现,java,jms,portability,standards-compliance,Java,Jms,Portability,Standards Compliance,JMS API声明了许多通用和具体的接口(例如,连接与队列连接)。 有文件证明,最佳实践是使用通用接口(例如会话和非队列会话)。如果我的应用程序同时使用队列和主题,并且我将使用常规,即:连接-->会话-->主题/队列,并假设支持所有JMS实现(TiBCO、WebLogic、Websphere等),那么我是否可以假设使用常规实体将适用于这两种开箱即用类型(队列和主题) 为了强调我的观点:我是否可以假设所有实现者都实现了java.jms.Connection接口,并且可以在一般情况下对这两种类型都起

JMS API声明了许多通用和具体的接口(例如,连接与队列连接)。 有文件证明,最佳实践是使用通用接口(例如会话和非队列会话)。如果我的应用程序同时使用队列和主题,并且我将使用常规,即:连接-->会话-->主题/队列,并假设支持所有JMS实现(TiBCO、WebLogic、Websphere等),那么我是否可以假设使用常规实体将适用于这两种开箱即用类型(队列和主题)

为了强调我的观点:我是否可以假设所有实现者都实现了java.jms.Connection接口,并且可以在一般情况下对这两种类型都起作用

谢谢,
Guy

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

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


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

我不理解为什么在前面的回答和讨论中有这样一个假设:非持久订阅不可移植。下面是一个代码示例(),它既不持久,又兼容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查找中检索的主题还是队列都无关紧要。上面的链接指向一篇文章,其中包含为WMQv6编写的工作代码示例和JNDI对象,但它们在WMQv7上同样有效(但QMgr的设置略有不同,因为发布/订阅不再需要单独的代理组件)

除此之外,最初的响应程序是正确的,因为只要应用程序符合JMS规范,它就应该在任何符合JMS的传输中运行。虽然这是事实,但它没有考虑到供应商的传输实现中的差异通过JMS抽象冒泡而影响您的代码

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

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

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


因此,一定要理解规范并编写可移植代码,但也要理解供应商对规范的实现,以及可移植性的边界在哪里。在任何情况下,持久订阅和非持久订阅之间都没有界限。

好的,谢谢,但如果我选择使用连接会话(而不是TopicSession),我就无法创建非持久订阅。这意味着我需要回到TopicConnectionFactory、TopicConnection、TopicSession等。。。。为了支持队列,我需要将其复制到QueueConnectionFactory等。。。Ant对此有何想法?这是一个有效的观点,尽管您是否仍然能够从持久订阅中session.unsubscribe()来模拟非持久订阅?据我所知,关于持久订阅:1。您需要为连接2设置客户端ID。您假设服务器被配置为支持持久订阅服务器,因为我不能假设关于服务器的任何内容,订阅可能会失败,因此我需要非持久订阅。