3D PLM Enterprise Architecture

Middleware Abstraction

Using an Error Class with HRESULTs or Exceptions

Associating information with errors
Technical Article

Abstract

This article explains how to use error classes and messages, and how to create new ones.


What Are Error Classes?

When you design and code your methods, and when the process goes out of the scope you have determined without being able to recover, you either return to the caller a HRESULT value stating that an error occurs or throw an exception. You associate with this HRESULT or make up the exception with an error class instance to convey the error severity, the error message, possibly filled with parameters you get from your method's variable values to show why the method goes out of its scope, and if the error class has data members, you can pass these variable values using these data members to the caller or exception catcher.

Dealing with error classes includes mainly:

[Top]

Instantiating Existing Error Classes

When you want to convey information with a returned HRESULT or throw an exception, you need to instantiate an existing error class

Choose an existing error class that matches the error. Avoid to create new error classes. In the same way, choose an existing error message that matches the error. Avoid to create new ones.

When you want to convey information with a returned HRESULT or throw an exception, you need to instantiate an existing error class, as follows:

...
  CATResourceError * pError = new CATResourceError("FileERR_2000",
                                                   "CATFileErrorCatalog"); 
...

The first parameter is the error message key, without the possible suffix used as a descriptor, and the second parameter is the error message catalog file name, without extension. The file is named in this case CATFileErrorCatalog.CATNls and should be found in the directory concatenation set by the CATMsgCatalogPath environment variable at run time.

An error class that is not created using the macros may have additional constructor arguments, and may have initialization methods to call. If the error class you use has data members, they are intended to pass parameter values to the caller or exception catcher. Use run time values of appropriate variables of your method to value these parameters.

[Top]

Filling In the Error Message with Run Time Parameter Values

If the error message includes parameters to value at run time, you should supply these values. To do this, convert the appropriate variables of your methods as CATUnicodeString instances, and assign them to the error class instance just created to build the message with these values.

If the message to use is a single one, use the SetNLSParameters method. If you have a composite message, set the parameters, if any, for each message of your composite message separately using the SetNLSRequestParams, SetNLSDiagnosticParams, and SetNLSAdviceParams methods respectively. Refer to Creating New Error Messages to know more about error messages.

[Top]

Setting the Error Type and Identifier

The error type and identifier are associated with the error to help the caller understand what happens and how to handle the error.

[Top]

Setting the Error Type

The type of the error describes its severity. An error can have the following types, whose values are taken from the CATErrorType enumeration, and the associated prompts are as follows:

CATErrorTypeCritical: a real problem occurs, and the method cannot complete. It returns when the problem occurs. This is the default if you don't set the error type. The associated prompt box must be an instance of the CATDlgNotify class with the CATDlgNfyError style.
CATErrorTypeFatal: the method stops with no possible recovery. The associated prompt box must be an instance of the CATDlgNotify class with the CATDlgNfyAbortRetryIgnore style.
CATErrorTypeWarning: something happens that doesn't stop the method which completes, but returns a warning. The associated prompt box must be an instance of the CATDlgNotify class with the CATDlgNfyWarning style.
CATErrorTypeInformation: there is no error and the method successfully completes, but this information can be handy. The associated prompt box must be an instance of the CATDlgNotify class with the CATDlgNfyInformation style.

The type is set using the SetType method. It takes the error type as parameter:

...
  pError->SetType(CATErrorTypeFatal);
...

[Top]

Setting the Error Identifier

The error identifier is part of the message key and deduced from it when passed to the constructor. Refer to Creating New Error Messages to know which part of the message key is used as error identifier.

[Top]

Informing the End User with a Prompt Box

You can send the error message to the end user in a prompt box using a CATDlgNotify class instance, as follows.

...
  CATDlgNotify * pPromptBox = new CATDlgNotify(pParent, "Error", CATDlgNfyAbortRetryIgnore);
  pPromptBox->SetTitle(pOccurringError->GetNLSSource());
  pPromptBox->SetText(pOccurringError->GetNLSMessage());
  pPromptBox->SetVisibility(CATDlgShow);
...

User the following styles according to the error type [2]:

Error Type

Style

CATErrorTypeCritical CATDlgNfyError
CATErrorTypeFatal CATDlgNfyAbortRetryIgnore
CATErrorTypeWarning CATDlgNfyWarning
CATErrorTypeInformation CATDlgNfyInformation

You should simply set the title using the GetNSLSource method, and the text using the GetNSLMessage method.

[Top]

Tracing the Error

If the error is a major one, you must trace it. Error traceability is possible using two macros:

The messages are passed as character strings to be logged in the abend log. They must be written in correct english since they can be read by the customer.

[Top]

Analyzing the Error

You can can analyze the error class instance using the following methods:

Data to Analyze Method Comment
Error class base class name IsAKindOf The error class base class name helps you determine which kind of error happens
Error class name ClassName The error class name helps you call the class methods or retrieve data members, if any
Return code GetReturnCode The return code helps you determine the code returned
Error severity GetInformationOnErrorType The error severity helps you decide if the error is critical, fatal, a warning, or an information
Error context GetSourceContext The source context is the name of the application that issues the error (CATIA by default)
Error source GetNLSSource The error source is made up of a concatenation of the source context, the error message catalog file name, and the error message key
Error identifier GetId The error identifier helps you precisely identify the error
Error message key GetMsgId The error message key helps you determine the message associated with the error
Error message catalog GetMsgCatalog The error message catalog helps you determine where the error message is stored
Error message GetNLSMessage The error message is retrieved as built by the caller with parameters valued
Request part of the message GetNLSRequest As above, for the Request part of the error message
Diagnostic part of the message GetNLSDiagnostic As above, for the Diagnostic part of the error message
Advice part of the message GetNLSAdvice As above, for the Advice part of the error message
Source file name GetSourceFileName The source file name is the path name of the source file in which the error occurs
Source line number GetSourceLineNumber The source line number is the number of the line in the source filewhere the error occurs

If the error is a major one, you must trace the error, as described in Tracing the Error.

[Top]

Creating New Error Messages

The message associated with the error is stored in a message catalog file. This allows for message translation or customization. The message catalog file should be created as a text file in the CNext\resources\msgcatalog directory for the english version, and in:

and should be suffixed using CATNls. This file is put in the run time view thanks to the mkCreateRuntimeView command, and found using the CATMsgCatalogPath environment variable set by the mkrun command.

Assume that the following message is extracted from the CAAFileErrorCatalog.CATNls file.

An error message is associated with a key that must be unique in the message file and used in the code to fetch the message. It is generally a composite message, made of three elementary messages, as follows:

...
FileERR_1999.Request    = "Attempt to open the file /p";
FileERR_1999.Diagnostic = "This file is not found"; 
FileERR_1999.Advice     = "Locate this file or try another one";
...

Messages have the following structure.

The key must be unique in a message catalog file, and is built using a prefix of your own, here File, followed by the error identifier, here ERR_1999. The descriptor is separated from the key by a dot, like a suffix, such as Diagnostic. The prefix and the descriptor are not required, but the error identifier must always be ERR_nnnn, where ERR is required and nnnn must be an integer. The error identifier must also be unique for a given message catalog file.

Even if you think to write three different messages with the three descriptors given above, they are handled as a single message using the message key. Nevertheless, you need to set their parameters using the SetNLSRequestParams, SetNLSDiagnosticParams, and SetNLSAdviceParams methods respectively.You can also create a message without descriptors, such as the following:

...
FileERR_2000 = "File /p not found.\nTry another one.";
...

When you write your error messages, classify the information to pass to the end user using the descriptor:

As any message, an error message can contain parameters. The value of these parameters are set at run time. To include parameters in your message, use the /p keyword. You can also use /P, or /p1, /p2, or also /P1, /P2, and so on. Each time such a keyword is found in the message, it is candidate to be filled in by a run time value. If no value is passed for a given parameter, it is replaced by ?? in the displayed message. The following is an example of an error message with parameters.

SketchLimitERR_0010.Request    = "The selected elements /p1 and /p2 cannot be relimited";
SketchLimitERR_0010.Diagnostic = "Lengthed elements cannot be relimited.\nTheir lengthes are:
\t/P1 for first element /p2
\t/P3 for second element /p4
They are converted into distances.";
SketchLimitERR_0010.Advice     = "To relimit, do not select lengthed elements"; 

Note that you can use special characters, such as \n or \t. This message is displayed at run time in a prompt as follows:

The title of the prompt box is made of the error source, that is, the concatenation of the running context, the error message catalog file, and the error message key. The running context, here CNext, is the name of the application from which the error is issued. The messages are displayed in the Request-Diagnostic-Advice order. The icon shown in the prompt box depends on the error type set at run time.

[Top]

Creating New Error Classes

An error class can be used for several errors dealing with a common topic. The error class you can create and instantiate should derive from one of the five following classes, since you should never derive from CATError directly:

These classes provide a first error classification:

You can refine this classification. For example, the CATFileError class could be dedicated to file errors and derive from CATResourceError. It is created using macros and have the following header file.

#include "CATResourceError.h"

class CATFileError : public CATResourceError
{
  public:
  CATDeclareError(CATFileError, CATResourceError)
};

and the following source file:

#include "CATFileError.h"

CATImplementError(CATFileError, CATResourceError);

CATImplementNLSErrorClass(CATFileError);

The macros create the class at build time.

You can also want to pass useful parameters to your callers, for example those that you use to fill in the message associated with the error such as the name of the file in error. Using these parameters values, the callers may decide what to do. Create such as class as follows:

#include "CATResourceError.h"

class CATFileError : public CATResourceError
{
  public:
    CATDeclareError(CATFileError, CATResourceError)
    CATFileError(const char * iMsgId, const char * iMsgCatalog, char * iFileName);
    HRESULT SetFileName(char *  iFileName);
    HRESULT GetFileName(char ** oFileName);
  private:
    char * _FileName;
};

 The source file of this class could be as follows:

#include "CATFileError.h"

CATImplementError(CATFileError, CATResourceError);

CATImplementNLSErrorClass(CATFileError);

CATFileError::CATFileError(const char * iMsgId, const char * iMsgCatalog, char * iFileName)
            : CATResourceError(const char * iMsgId, const char * iMsgCatalog)
{
  _FileName = iFileName;
}

HRESULT CATFileError::SetFileName(char *  iFileName)
{
  _FileName = iFileName;
  CATReturnSuccess;
}

HRESULT CATFileError::GetFileName(char ** oFileName)
{
  if (NULL != oFileName)
  {
    *oFileName = _FileName;
    CATReturnSuccess;
  }
  else
    CATReturnFailure;
}

[Top]


In Short

Error class instances can be associated with returned HRESULTs or exceptions, along with an error identifier and a message that can include parameters values from the method current state.  If the method is located at the appropriate level, a prompt can be issued to the end user. Errors can be traced using the CATSysLogAbend and CATSysLogError macros. If necessary, new error messages and new error classes can be created.

[Top]


References

[1] CAA V5 Error Processing Rules
[2] Managing Errors Using HRESULT
[3] Managing Errors Using Exceptions

[Top]


History

Version: 1 [Nov 2001] Document created
[Top]

Copyright © 2000, Dassault Systèmes. All rights reserved.