处理未校验的异常

在 JMS 2.0 中定义的接口上的方法抛出未校验的异常。 这些异常的基类为 JMSRuntimeException。 因此,捕获 JMSRuntimeExceptions 提供了处理这些类型的异常的通用方法。

每个 JMSRuntimeException 包含以下信息:
  • 特定于提供程序的异常消息,您的应用程序可以通过调用 JMSRuntimeException.getMessage() 方法来获取此消息。
  • 特定于提供程序的错误代码,您的应用程序可以通过调用 JMSRuntimeException.getErrorCode() 方法来获取此错误代码。
  • 链接异常。 JMS 2.0 API 调用抛出的异常通常是与此异常关联的另一个异常所报告的较低级别问题的结果。 您的应用程序可以通过调用 JMSRuntimeException.getCause() 方法来获取链接异常。
JMS 2.0 API 提供的接口上调用方法时, IBM® MQ classes for JMS 抛出的大多数异常都是 JMSRuntimeException的子类实例。 这些子类可实现 com.ibm.msg.client.jms.JmsExceptionDetail 接口,此接口提供以下额外信息:
  • 异常消息的解释。 您的应用程序可以通过调用 JmsExceptionDetail.getExplanation() 方法来获取此消息。
  • 推荐用户对异常进行的响应。 您的应用程序可以通过调用 JmsExceptionDetail.getUserAction() 方法来获取此消息。
  • 异常消息中消息插入内容的键。 您的应用程序可以通过调用 JmsExceptionDetail.getKeys() 方法来获取所有密钥的迭代器。
  • 异常消息中的消息插入内容。 例如,消息插入内容可能是导致此异常的队列的名称,此内容可供应用程序使用以访问此名称。 您的应用程序可以通过调用 JmsExceptionDetail.getValue() 方法来获取对应于指定键的消息插入。
如果没有可用的详细信息,那么 JmsExceptionDetail 接口中的所有方法都将返回空值。
例如,如果某个应用程序尝试为不存在的 IBM MQ 队列创建 JMSProducer,那么系统将抛出异常并提供以下信息:
Message : JMSWMQ2008: Failed to open MQ queue 'Q_test'.
Class : class com.ibm.msg.client.jms.DetailedInvalidDestinationException
Error Code : JMSWMQ2008
Explanation : JMS attempted to perform an MQOPEN, but IBM MQ reported an
              error.
User Action : Use the linked exception to determine the cause of this error. Check
              that the specified queue and queue manager are defined correctly.
抛出的异常 com.ibm.msg.client.jms.DetailedInvalidDestinationException是以下类的子类,并实现 com.ibm.msg.client.jms.JmsExceptionDetail 接口。
  • [Jakarta Messaging 3.0 ]jakarta.jms.InvalidDestinationException
  • [JMS 2.0 ]javax.jms.InvalidDestinationException

连锁异常

通常,异常由其他异常所致。 因此,对于抛出的每个 JMSRuntimeException,应用程序应该检查链接异常。

导致 JMSRuntimeException 的原因可能是另一个异常。 这些异常会形成一个指回原始底层问题的连锁链。 异常的原因是通过使用 java.lang.Throwable 类的链式异常机制来实现的,您的应用程序可以通过调用 Throwable.getCause() 方法来获取链接异常。

例如,如果应用程序连接队列管理器时指定了不正确的端口号,异常将形成以下连锁链:
com.ibm.msg.client.jms.DetailIllegalStateException
|
+--->
    com.ibm.mq.MQException
    |
    +--->
        com.ibm.mq.jmqi.JmqiException
        |
        +--->
            com.ibm.mq.jmqi.JmqiException
            |
            +--->
                java.net.ConnectionException
通常,连锁链中的每个异常都是从代码的不同层抛出的。 例如,上述连锁链中的异常由以下层抛出:
  • 第一个异常(即 JMSRuntimeException 的子类的实例)由 IBM MQ classes for JMS 中的公共层抛出。
  • 下一个异常(com.ibm.mq.MQException 的实例)由 IBM MQ 消息传递提供程序抛出。
  • Java 消息队列接口 (JMQI) 抛出以下两个异常 (这两个异常都是 com.ibm.mq.jmqi.JmqiException的实例)。 JMQI 是 IBM MQ classes for JMS 用于与队列管理器通信的组件。
  • 最后一个异常(java.net.ConnectionException 的实例)由 Java 类库抛出。
有关 IBM MQ classes for JMS 的分层体系结构的更多信息,请参阅 IBM MQ classes for JMS 体系结构
您可以对应用程序进行编码以通过此链进行迭代来抽取所有相应的信息,如以下示例中所示: [Jakarta Messaging 3.0 ]

import com.ibm.msg.client.jms.JmsExceptionDetail;
import com.ibm.mq.MQException;
import com.ibm.mq.jmqi.JmqiException;
import jakarta.jms.JMSRuntimeException;
.
.
.
catch (JMSRuntimeException je) {
  System.err.println("Caught JMSRuntimeException");
  // Check for linked exceptions in JMSRuntimeException
  Throwable t = je;
  while (t != null) {
    // Write out the message that is applicable to all exceptions
    System.err.println("Exception Msg: " + t.getMessage());
    // Write out the exception stack trace
    t.printStackTrace(System.err);

    // Add on specific information depending on the type of exception
    if (t instanceof JMSRuntimeException) {
      JMSRuntimeException je1 = (JMSRuntimeException) t;
      System.err.println("JMS Error code: " + je1.getErrorCode());
      if (t instanceof JmsExceptionDetail){
        JmsExceptionDetail jed = (JmsExceptionDetail)je1;
        System.err.println("JMS Explanation: " + jed.getExplanation());
        System.err.println("JMS Explanation: " + jed.getUserAction());
      }
    } else if (t instanceof MQException) {
      MQException mqe = (MQException) t;
      System.err.println("WMQ Completion code: " + mqe.getCompCode());
      System.err.println("WMQ Reason code: " + mqe.getReason());
    } else if (t instanceof JmqiException){
      JmqiException jmqie = (JmqiException)t;
      System.err.println("WMQ Log Message: " + jmqie.getWmqLogMessage());
      System.err.println("WMQ Explanation: " + jmqie.getWmqMsgExplanation());
      System.err.println("WMQ Msg Summary: " + jmqie.getWmqMsgSummary());
      System.err.println("WMQ Msg User Response: " + jmqie.getWmqMsgUserResponse());
      System.err.println("WMQ Msg Severity: " + jmqie.getWmqMsgSeverity());
    }
    // Get the next cause
    t = t.getCause();
  }
}
[JMS 2.0 ]

import com.ibm.msg.client.jms.JmsExceptionDetail;
import com.ibm.mq.MQException;
import com.ibm.mq.jmqi.JmqiException;
import javax.jms.JMSRuntimeException;
.
.
.
catch (JMSRuntimeException je) {
  System.err.println("Caught JMSRuntimeException");
  // Check for linked exceptions in JMSRuntimeException
  Throwable t = je;
  while (t != null) {
    // Write out the message that is applicable to all exceptions
    System.err.println("Exception Msg: " + t.getMessage());
    // Write out the exception stack trace
    t.printStackTrace(System.err);

    // Add on specific information depending on the type of exception
    if (t instanceof JMSRuntimeException) {
      JMSRuntimeException je1 = (JMSRuntimeException) t;
      System.err.println("JMS Error code: " + je1.getErrorCode());
      if (t instanceof JmsExceptionDetail){
        JmsExceptionDetail jed = (JmsExceptionDetail)je1;
        System.err.println("JMS Explanation: " + jed.getExplanation());
        System.err.println("JMS Explanation: " + jed.getUserAction());
      }
    } else if (t instanceof MQException) {
      MQException mqe = (MQException) t;
      System.err.println("WMQ Completion code: " + mqe.getCompCode());
      System.err.println("WMQ Reason code: " + mqe.getReason());
    } else if (t instanceof JmqiException){
      JmqiException jmqie = (JmqiException)t;
      System.err.println("WMQ Log Message: " + jmqie.getWmqLogMessage());
      System.err.println("WMQ Explanation: " + jmqie.getWmqMsgExplanation());
      System.err.println("WMQ Msg Summary: " + jmqie.getWmqMsgSummary());
      System.err.println("WMQ Msg User Response: " + jmqie.getWmqMsgUserResponse());
      System.err.println("WMQ Msg Severity: " + jmqie.getWmqMsgSeverity());
    }
    // Get the next cause
    t = t.getCause();
  }
}
请注意,应用程序应始终检查连锁链中每个异常的类型,因为异常类型可能会有变化,而不同类型的异常封装不同的信息。

获取有关问题的 IBM MQ 特定信息

com.ibm.mq.MQExceptioncom.ibm.mq.jmqi.JmqiException 的实例包含有关问题的特定于 IBM MQ 的信息。

MQException 包含以下信息:
  • 完成代码,您的应用程序可以通过调用 getCompCode() 方法来获取此代码。
  • 原因码,您的应用程序可以通过调用 getReason() 方法来获取此原因码。

有关如何使用这些方法的示例,请参阅 链式异常中的样本代码。

JmqiException 还包含完成代码和原因码。 此外,JmqiException 还会包含 AMQ nnnn 或 CSQ nnnn 消息(如果它与异常关联)中的信息。 应用程序可通过调用以下方法获取此消息的各种组件:
  • getWmqMsgExplanation() 方法返回 AMQ nnnn 或 CSQ nnnn 消息的说明。
  • getWmqMsgSeverity() 方法返回 AMQ nnnn 或 CSQ nnnn 消息的严重性。
  • getWmqMsgSummary() 方法返回 AMQ nnnn 或 CSQ nnnn 消息的摘要。
  • getWmqMsgUserResponse() 方法返回与 AMQ nnnn 或 CSQ nnnn 消息关联的用户响应。