6.10 Exception Handling

XMA uses the IMC-Enterprise-Framework Exception classes:

  1. SysException is used when the root cause is a program failure or resource shortage in soft- or hardware.

  2. AppException is used when the root cause is a condition in the business logic itself, either illegal data or state. This condition as been predicted and been foreseen and taken care of at programming time. The exception is thrown by the own code to give a other layers a kind of notification of this state.

  3. Notification can be used to format messages to be displayed to the end-user.

More details about the exception classes can be found below.

The XMA framework transports only a SysException or an AppException (both are RuntimeExceptions and accept a Throwable as detail) from the XMA server side to the client, any other Exception will result in a SysException. That means that in this case the original root Exception (actual its message and stack) is encapsulated inside a SysException (in the Java 1.4 "caused by" style). Also it makes no sense to subclass a SysException or an AppException as the XMA client will not know this subclass and not be able to deserialize it. To differentiate between different types of Exceptions the methods SysException.setCode(int code) / AppException.setCode(int code) can be used.

Some projects might like to implement one single method for Exception handling and transforming of own exception types to a SysException for all RPCs (with the setting of error codes and messages). For this the method ComponentServer.convertToBaseException(Throwable detail) can be overwritten (usually this is done in the project specific ComponentServer class). This method is always called when an Exception occurred in a server side RPC implementation. The SysException or AppException returned by this method is then transported to the client.

System Exceptions (see SysException ) indicate abnormal conditions that have the following properties:

  1. They indicate unexpected failures or resource shortages in hardware . Examples: Failure of processor, disk or network. Shortages of any kind: Out of disk space, out of file handles, network traffic jam, no more data base connections, database table space full.

  2. They indicate unexpected failures of system-level-software . Examples: Failures of the operating system, the database system, the application server.

  3. They indicate unexpected failures of application-level-software because of programming errors .

  4. System-exceptions are always unexpected, cannot be predicted in advance and therefore cannot be dealt with reasonably in the program (beyond reporting in a generic way).

  5. They may appear in almost any method , since business logic in online applications usually accesses data sources like database or backend systems that may throw these exceptions.

  6. Since the end-user does not cause and cannot solve the underlying cause of system-exceptions, system-exceptions should not primarely be reported to him, but to a system-administrator. Therefore, if an application throws a System Exception, this exception will be included in failure statistics of the application server and usually triggers a problem management process that is beyond the scope of the application project.

Usually, System Exceptions are not shown directly to the end-user, but are often wrapped in a generic Application Exception that is displayed instead. The end-user does not understand the root cause of the System Exception and cannot get rid of it.

The programmer may throw System Exceptions to wrap checked exceptions from subsystems, the most common example: A database access method throws a java.sql.SQLException which is a checked exception. Then morphing the SQLException to a SysException is done like:

try {
    callSQLMethod(args);   // throws SQLException
} catch (SQLException ex) {
    throw new SysException (ex, args.toString());
}
    

Application Exceptions (see AppException ) also abruptly terminate some piece of business logic, but what makes them different from System Exceptions is the following:

  1. They indicate conditions that are known at programming time and the handling is anticipated by the programmer.

  2. The root cause of the failure condition is either invalid data or invalid state with respect to the data triggered by end-user activity.

  3. They may appear even if the hardware and software is operating correctly .

  4. If the application has an XMA-client and the end-user triggers the condition by providing malformed input data, Application Exceptions are displayed to the end-user at the XMA-client.

  5. Application Exceptions are not included in application server error statistics and do not trigger a problem management process outside the application project.

A typical example of an AppException is the following: Suppose you want to update a database-record the end-user has been editing by issuing a call to ImcDAO.update(BusinessData d), see class ImcDAO . This method throws an exception if the record has been changed in the meantime, indicating that another person was faster in updating the very same record. You may signal that fact to the user in the following way:
...
try {
    new ImcDAO().update (myCustomer);
} catch (ImcAlreadyChangedException ex) {
    throw new AppException (ex, "The customer with number {0} has been changed by another user in the meantime. Please retry ...",
                                myCustomer.getNumCustomer().toString);
}
    
XMA: This exception, when thrown at the XMA-server, will display a message-box at the XMA-client with an error-icon, an OK-button and the above defined text.

Sometimes it seems to be not very easy to decide between System- or Application-Exceptions. Here is a short version of the rule:

Application Exceptions may occur frequently and do not indicate a problem to Systems- and Application-Management in the data center. Application Exceptions are dealt with and cured in the program itself. System exceptions indicate failures that the application itself cannot cure. Therefore, they are included in the error statistics and trigger a problem management process outside the application.

If the distinction is still unclear for you, think about the consequences. At the IMC-server, statistics are collected. Among others, the number of server calls is recorded. Calls terminating with SysExceptions are separately highlighted because they indicate something that must be manually dealt with. If you do not want your exceptions to be included in these statistics, because you can recover from the exceptions yourself, then throw AppException s. An application is considered to be running well and without problems if it does not throw SysException s. A SysException indicates a problem that will draw somebodys attention towards it.

Notifications (see Notification ) are facts that a piece of business logic wants to tell to its caller. They might be of type ERROR, WARNING, INFORMATION or QUESTION. Their detection need not disrupt the execution thread. Notifications may also be collected in NotificationList s.

Notifications are not Exceptions. Therefore, the detecting method must return a Notification as output parameter.

System Exceptions, Application Exceptions and Notifications have some properties in common. For example, all may be shown to the end-user, they have describing texts and a code to descriminate between different types of Application Exceptions, for example. Therefore, all implement the interface INotification which provides the following properties:


The classes AppExeption , SysException and Notification provide multiple constructors to provide messages with zero, one or two parameters, as may be seen in AppException :

    public AppException (String messageFmt) { ...
    public AppException (String messageFmt, Object param1) { ...
    public AppException (String messageFmt, Object param1, Object param2) { ...
    

Here, the format string must follow the rules defined in class java.text.MessageFormat .

[Important]

If you are building a multi language application, the calculation of the right (Locale-dependent) MessageFormat -String must be done before constructing the INotification . I.e., the constructors of the classes implementing INotification require a localized messageFmt -parameter. The INotification -classes just merge the MessageFormat -String with supplied parameters, nothing more. To keep things loosly coupled, the resource-bundle should reside in the module (package) that holds the business-logic that creates the INotification .

[Caution]

You should not subclass AppException and SysException . Instead use the code-property to discriminate amongst different kinds of exceptions. The reason for this restriction: Some business-logic-module might raise a custom exception using a class MyAppException derived from AppException , for example. Unfortunately, any client of this module would need to include MyAppException in its classpath, even propagating this necessity to a remote client. This would imply enormous coupling between modules, just for the purpose to differentiate between different kinds of exceptions.