Errors and exception handling
Correct handling of errors and exceptions is important for correct integration node operation. You must consider how and when your user-defined extension must handle errors and exceptions.
The errors and exception handling here describes factors that you must consider when you develop user-defined extensions for IBM® App Connect Enterprise in the C programming language. If you are developing user-defined extensions using the Java™ programming language, you can use standard Java error and exception handling methods. If, for example, IBM App Connect Enterprise throws an exception internally, a Java exception of class MbException is made available.
The integration node generates C++ exceptions to handle error conditions. These exceptions are caught in the relevant software layers in the integration node, and are handled accordingly. However, programs written in C cannot catch C++ exceptions, and all exceptions thrown, by default, bypass all C user-defined extension code and are caught in a higher layer of the integration node.
Utility functions, by convention, typically use the return value
to pass back requested data; for example, the address or handle of
an integration node object. The return value sometimes indicates that
a failure has occurred. For example, if the address or handle of an
integration node object could not be retrieved, zero (CCI_NULL_ADDR)
is returned. Additionally, the reason for an error condition is stored
in the return code output parameter, which is, by convention, part
of the function prototype of all utility functions. If the utility
function completed successfully and returnCode
was
not null, returnCode
contains CCI_SUCCESS. Otherwise,
it contains one of the return codes described here. You can test the
value of returnCode
to determine whether a utility
function was successful.
returnCode
parameter
to that utility function. If a null value was specified for returnCode
,
and an exception occurs: - The user-defined extension is not be aware of that exception
- The utility function does not return to the user-defined extension
- Execution control passes to higher layers in the integration node stack to process the exception
Therefore, a user-defined extension cannot perform its own error
recovery. If, however, the returnCode
parameter is
specified, and an exception occurs, a return code of CCI_EXCEPTION
is returned. In this case, cciGetLastExceptionData or cciGetLastExceptionDataW (the
difference being that cciGetLastExceptionDataW returns
a CCI_EXCEPTION_WIDE_ST which can contain Unicode trace text) can
be used to obtain diagnostic information on the type of exception
that occurred. The data is returned in the CCI_EXCEPTION_ST or CCI_EXCEPTION_WIDE_ST
structure.
If there are no resources to be released, do not set the returnCode argument in your user-defined extension. Not setting this argument allows exceptions to bypass your user-defined extensions. These exceptions can then be handled higher up the IBM App Connect Enterprise stack, by the integration node.
Message inserts can be returned in the CCI_STRING_ST members of the CCI_EXCEPTION_ST structure. The CCI_STRING_ST allows the user-defined extension to provide a buffer to receive all required inserts. The integration node copies the data into this buffer, and returns the number of bytes output and the actual length of the data. If the buffer is not large enough, no data is copied and the "dataLength" member can be used to increase the size of the buffer, if required.
The user-defined extension can set a non-null value for returnCode
and
provide its own error recovery, if required. The utility function
calls return to the user-defined extension and pass their status through returnCode
.
All exceptions that occur in a utility function must be passed back
to the integration node for additional error recovery to be performed;
that is, when CCI_EXCEPTION is returned in returnCode
.
You do this by calling cciRethrowLastException,
after the user-defined extension has completed its own error processing.
Calling cciRethrowLastException causes the C interface
to re-throw the last exception so that it can be handled by other
layers in the integration node. In the same way as the C exit call, cciRethrowLastException does
not return in this case.
If an exception occurs and is caught by a user-defined extension, the extension must not call utility functions except cciGetLastExceptionData, cciGetLastExceptionDataW, or cciRethrowLastException. An attempt to call other utility functions results in unpredictable behavior that can compromise the integrity of the integration node.
If a user-defined extension encounters a serious error, cciThrowException or cciThrowExceptionW can be used to generate an exception that is processed by the integration node in the correct manner. The generation of such an exception causes the supplied information to be written to the system log (syslog or Eventviewer) if the exception is not handled. The information is also written to trace (if trace is active).
Types of exception and integration node behavior
The integration node generates a set of exceptions that can be passed to a user-defined extension. These exceptions can also be generated by a user-defined extension when an error condition is encountered. The exception classes are: