按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
7。2 JMSException
JMS 定义了JMSException 作为JMS 方法抛出的异常的根类。JMSException 是一个受检查
异常,捕捉它就可以处理所有JMS 相关的异常。JMSException 提供了下面的信息:
z 提供商特有的描述错误的字符串——这个字符串是标准的 java 异常消息,可用
getMessage()获得这个消息。
z 提供商特有的字符串型错误代码。
z 对另一个异常的引用——一个 JMS 异常通常是由底层问题引起。如果合适,底层
异常可以被关联到JMS 异常。
JMS 方法在它们的标识符中只包含JMSException 。JMS 方法可以抛出任意的标准JMS 异
常,以及JMS 供应商特有的异常。JMS 方法的javadoc 只给出了必需的异常情况。
7。3 标准异常
除了JMSException 外,JMS 定义了几个其他异常,它们标准化了基本错误原因的报告。
只有几种情况必须抛出指定的JMS 异常。这些情况在异常描述中用单词“必须”标出。
这些情况都是唯一的,在这些情况下客户端逻辑应当根据特定的问题抛出特定的JMS 异常。
在其他情况下,强烈建议JMS 提供商尽可能使用标准的异常。JMS 提供商如果需要也可
以从这些异常中提取供应商特有的异常。
JMS 定义了下面的标准异常:
z IllegalStateException:当在不合法或不合适的时间,或提供商没有处于处理请求操
作的合适状态,则抛出这个异常。例如,如果 Session。mit()在非事务会话中被
调用,则必须抛出这个异常。当调用与域不匹配的方法时,例如调用
TopicSession。CreateQueueBrowser() ,必须抛出这个异常。
z JMSSecurityException :当提供商拒绝客户端提交的用户名/密码时必须抛出这个异
49 / 66
…………………………………………………………Page 50……………………………………………………………
常。它也可以用于安全限制阻止方法完成的情况。
z InvalidClientException:当客户端企图设置连接的客户端标识,但提供商拒绝了这个
标识的值时,就必须抛出这个异常。
z InvalidDestinationException:当提供商不能识别给定的目的地或目的地不再有效时,
必须抛出这个异常。
z InvalidSelectorException:当 JMS 客户端企图用无效的语法向提供商提供消息选择
器时,必须抛出这个异常。
z MessageEOFException:当正在读取StreamMessage 或ByteMessage 时到达了不期望
的流结尾,则必须抛出这个异常。
z MessageRormatException:当JMS 客户端企图使用消息不支持的数据类型或企图将
消息的数据读作错误的类型时,必须抛出这个异常。当消息属性值发生同样的类型
错误时也必须抛出这个异常。例如,如果 StreamMessage。writeObject()被给了不支
持的类或如果 StreamMessage。readShort()用于读取布尔值,则必须抛出这个异常。
如果提供商被给了不能接受的类型,则也必须抛出这个异常。注意,一个特殊的情
况是当企图读取不正确格式的 String 数据作为数值型值时,必须抛出
java。lang。NumberFormatException 。
z MessageNotReadableException:当JMS 客户端企图读一个只可写的消息时必须抛出
这个异常。
z MessageNotWriteableException:当JMS 客户端企图写一个只可读的消息时必须抛
出这个异常。
z ResourceAllocationException:当提供商不能定位方法请求的资源时必须抛出这个异
常。例如,当由于JMS 提供商资源缺失而导致调用createTopicConnection 失败时应
当抛出这个异常。
z TransactionProgressException :当由于事务处于处理中而导致操作无效时抛出这个
异常。例如,当会话时分布式事务的一部分时调用 Session。mit()应当抛出这个
异常。
z TransactionRolledBackException :当调用Session。mit 导致当前事务回滚时必须抛
出这个异常。
8 JMS 应用服务器工具
8。1 概述
本章描述用于并发处理订阅消息的JMS 工具。也定义了JMS 提供商如何支持JTS 可感知
的会话。这些工具主要由JMS 提供商使用。
如果JMS 客户端使用JTS 可感知工具来进行客户端编程,则它可能是不可移植的,因为
不要求JMS 提供商支持这些接口。
在本章中描述的工具是JMS 的一个特殊类别。它们是可选的,可能只有部分JMS 提供
商对它们提供支持。
50 / 66
…………………………………………………………Page 51……………………………………………………………
8。2 并发处理订阅的消息
JMS 提供了一个特殊的工具用于创建MessageConsumer,它可以并发的消费消息。
这个工具将这项工作分成三个角色:
z JMS 提供商——用于转发消息。
z 应用服务器——用于创建消费者和管理由并发MessageListener 对象使用的线程。
z 应用——用目的地和可选的消息选择器定义一个订阅,并提供一个单线程的
MessageListener 类来消费它的消息。应用服务器将构造这个类的多个对象来并发消
费消息。
8。2。1 Session
会话提供了应用服务器使用的三个方法:
z setMessageListener() 和 getMessageListener() ——会话的 MessageListener 通过
ConnectionConsumer 消费分配到这个会话的消息,如后面的几个段落描述。
z run()——会话的MessageListener 依次处理由ConnectionConsumer 分配到会话的消
息。当监听器从最后一个消息处理返回时,run()返回。
应用服务器通常被给一个 MessageListener 类,它包含了由应用程序员编写的处理消息
的单线程代码。应用服务器也被给监听器要消费消息的目的地和消息选择器。
应用服务器将负责创建处理消息处理的JMS Connection,ConnectionConsumer 和Session 。
应用服务器将按需创建MessageListener 实例并将它们注册到它自己的会话中。
由于许多监听器需要使用会话的服务,因此监听器很可能要求将它的会话传入到它的构
造器中。
8。2。2 ServerSession
ServerSession 是一个由应用服务器实现的对象。应用服务器使用它来将一个线程和一个
JMS 会话关联起来。
ServerSession 实现了两个方法:
z getSession()——返回ServerSession 的JMS 会话。
z start()——启动ServerSession 线程的执行,并执行关联的JMS 会话的run 方法。
8。2。3 ServerSessionPool
ServerSessionPool 是一个由应用服务器实现的对象,它提供了用于处理
ConnectionConsumer 的消息的ServerSession 池。
它只有一个方法是getServerSession() 。这个方法从池中删除一个ServerSession 并将它返
回给调用者(假定是ConnectionConsumer ),用于消费一个或多个消息。
JMS 没有说明如何实现池。它可能是一个静态的ServerSession 池,或者它可以使用更专
业的算法来按需动态创建ServerSession 。
如果ServerSessionPool 没有了ServerSession,那么getServerSession()方法可能阻塞。如
51 / 66
…………………………………………………………Page 52……………………………………………………………
果ConnectionConsumer 被阻塞,那么它不能转发新的消息直到ServerSession 返回。
8。2。4 ConnectionConsumer
对于应用服务器来说,连接提供了创建 ConnectionConsumer 的专用工具。它消费的消
息由目的地和消息选择器指定。另外,ConnectionConsumer 必须交给ServerSessionPool 用于
处理它的消息。指定 maxMessages 值用于限制 ConnectionConsumer 一次可以加载到
ServerSession 会话的消息数量。
通常,当拥堵轻微时,ConnectionConsumer 从池中得到一个ServerSession,用一个消息
加载它的会话,然后启动它。当拥堵严重时,消息可能被退回。如果发生退回,
ConnectionConsumer 可以用多个消息来加载每个 Session 。这减少了线程上下文的切换,减
小了某些消息处理排序时资源的使用。
8。2。5 ConnectionConsumer 如何使用ServerSession
由JMS 提供商实现的ConnectionConsumer 使用ServerSession 来处理一到多个到达的消
息。按以下方式做这项工作:
z 从ServerSessionPool 中得到一个ServerSession 。
z 得到ServerSession 的Session 。
z 用一个或多个消息加载Session 。
z 然后其他ServerSession 来消费这些消息。
用于QueueConnection 的ConnectionConsumer 将它的消息加载到QueueSession,同样,
用于TopicConnection 的ConnectionConsumer 加载TopicSession 。
注意,JMS 没有说明 ConnectionConsumer 如何用消息加载 Session 。由于
ConnectionConsumer 和Session 都由同一个JMS 提供商实现,因此它们可以用私有机制完成
这种加载。
8。2。6 应用服务器如何实现ServerSession
JMS 没有说明ServerSession 的实现。下面出现的普通实现解释了这个概念:
z 应用服务器为 ServerSession 创建一个线程,注册 ServerSession 的 runObject 。
runObject 的实现是应用服务器私有的。
z ServerSession 的start 方法调用线程的start