Handling checked exceptions
Methods on the interfaces that are defined in JMS 1.1 or earlier throw checked exceptions. The base class for these exceptions is JMSException. Therefore, catching JMSExceptions provides a generic way of handling these types of exceptions.
Every JMSException encapsulates the following information:- A provider specific exception message, which the application can obtain by calling the Throwable.getMessage() method.
- A provider specific error code, which the application can obtain by calling the JMSException.getErrorCode() method.
- A linked exception. An exception that is thrown by a JMS 1.1 API call is often the result of a lower level problem which is reported by another exception that is linked to this exception. Your application can obtain a linked exception by calling either the JMSException.getLinkedException() method or the Throwable.getCause() method.
When we use the JMS 1.1 API, most exceptions that are thrown by the IBM MQ classes for JMS are instances of subclasses of JMSException. These subclasses implement the com.ibm.msg.client.jms.JmsExceptionDetail interface, which provides the following additional information:
- An explanation of the exception message. Your application can obtain this message by calling the JmsExceptionDetail.getExplanation() method.
- A recommended user response to the exception. Your application can obtain this message by calling the JmsExceptionDetail.getUserAction() method.
- The keys for the message inserts in the exception message. Your application can obtain an iterator for all the keys by calling the JmsExceptionDetail.getKeys() method.
- The message inserts in the exception message. For example, a message insert might be the name of the queue that caused the exception, and it might be useful for the application to access that name. Your application can obtain the message insert corresponding to a specified key by calling the JmsExceptionDetail.getValue() method.
All the methods in the JmsExceptionDetail interface return null if no details are available.
For example, if an application tries to create a message producer for an IBM MQ queue that does not exist, an exception is thrown with the following information: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.The exception that is thrown, com.ibm.msg.client.jms.DetailedInvalidDestinationException, is a subclass of javax.jms.InvalidDestinationException and implements the com.ibm.msg.client.jms.JmsExceptionDetail interface.
Linked exceptions
A linked exception provides further information about a runtime problem. Therefore, for each JMSException that is thrown, an application should check the linked exception.
The linked exception itself might have another linked exception, and so the linked exceptions form a chain that leads back to the original underlying problem. A linked exception is implemented by using the chained exception mechanism of the java.lang.Throwable class, and your application can obtain a linked exception by calling the Throwable.getCause() method. For a JMSException, the getLinkedException() method delegates to the Throwable.getCause() method.
For example, if an application specifies an incorrect port number when connecting to a queue manager, the exceptions form the following chain:com.ibm.msg.client.jms.DetailIllegalStateException | +---> com.ibm.mq.MQException | +---> com.ibm.mq.jmqi.JmqiException | +---> com.ibm.mq.jmqi.JmqiException | +---> java.net.ConnectionExceptionTypically, each exception in a chain is thrown from a different layer in the code. For example, the exceptions in the preceding chain are thrown by the following layers:
- The first exception, an instance of a subclass of JMSException, is thrown by the common layer in IBM MQ classes for JMS.
- The next exception, an instance of com.ibm.mq.MQException, is thrown by the IBM MQ messaging provider.
- The next two exceptions, both of which are instances of com.ibm.mq.jmqi.JmqiException, are thrown by the Java Message Queueing Interface (JMQI). The JMQI is the component that is used by the IBM MQ classes for JMS to communicate with a queue manager.
- The final exception, an instance of java.net.ConnectionException, is thrown by the Java class library.
For more information about the layered architecture of IBM MQ classes for JMS, see IBM MQ classes for JMS architecture. We can code the application to iterate through this chain to extract all the appropriate information, as shown in the following example:
import com.ibm.msg.client.jms.JmsExceptionDetail; import com.ibm.mq.MQException; import com.ibm.mq.jmqi.JmqiException; import javax.jms.JMSException; . . . catch (JMSException je) { System.err.println("Caught JMSException"); // Check for linked exceptions in JMSException 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 JMSException) { JMSException je1 = (JMSException) 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(); } }Note that the application should always check the type of each exception in a chain because the type of exception can vary and exceptions of different types encapsulate different information.
Obtaining IBM MQ specific information about a problem
Instances of com.ibm.mq.MQException and com.ibm.mq.jmqi.JmqiException encapsulate IBM MQ specific information about a problem.
An MQException encapsulates the following information:- A completion code, which the application can obtain by calling the getCompCode() method.
- A reason code, which the application can obtain by calling the getReason() method.
For examples of how to use these methods, see the sample code in linked exceptions.
A JmqiException also encapsulates a completion code and a reason code. In addition to this, a JmqiException contains the information in an AMQ nnnn or CSQ nnnn message, if one is associated with the exception. Your application can obtain the various components of this message by calling the following methods:- The getWmqMsgExplanation() method returns the explanation of the AMQ nnnn or CSQ nnnn message.
- The getWmqMsgSeverity() method returns the severity of the AMQ nnnn or CSQ nnnn message.
- The getWmqMsgSummary() method returns the summary of the AMQ nnnn or CSQ nnnn message.
- The getWmqMsgUserResponse() method returns the user response that is associated with the AMQ nnnn or CSQ nnnn message.
Parent topic: Exceptions in IBM MQ classes for JMS