| [ directory ] |
|
1.6 Exception ManagementProgramming for exceptions and errors is a key concept of managed execution environments. Applications can achieve predictable flow of execution as long as they execute successfully. However, this well-defined path can be disturbed in the event of an error or an exception. A good exception management service allows developers to trap these exceptions and errors and thereby streamline their processing so that the predictability of the application is maintained even when it is on the road to failure. Such a management service allows for recovery from failure and discovery of replicable error paths in the application. Knowing how an application can fail is as important as knowing how an application can execute successfully. It makes troubleshooting applications very easy. Exceptions represent a breach of an implicit assumption made within the code. For example, if your code tries to access a file that is assumed to exist, but the file is missing, an exception will be thrown. However, if your code does not assume that the file exists and thus checks for its presence first, this scenario will not necessarily generate an exception. 1.6.1 Exception Management in the CLRThe .NET CLR provides exception management by handling exceptions, logging exceptions, and generating events for notification that can be monitored externally to assist system operation. Exceptions can be handled explicitly by the programmer through coding (similar to checked exceptions in Java) or by the runtime (similar to unchecked exceptions and errors in Java). Figure 1.2 shows a flowchart of the process of detecting and propagating exceptions. If the current method detects an exception, then it has the option of handling the exception within itself and recovering from it, or it can add any contextual information to the exception and let it propagate to the caller of the method. The onus of handling the exception then lies with the caller of the method. The exception can thus "bubble up" to the topmost method call, at which point the application can handle the exception before returning it to the user (as in a stack trace in Java). The application cannot recover from this exception. It must gather information, log information, perform any cleanups, send notification, and do any other exception processing before showing the user the exception. Figure 1.2. Flowchart for Exception Detection and Propagation
You can code for exception detection using the try-catch-finally construct. The try block contains code that can throw an exception. When an exception is thrown within this block, the first catch block whose filter matches the class of the exception catches it. Note that the filter is specified in parentheses following the catch keyword. If you have multiple catch blocks, you should ensure that they are ordered from the most specific type to the most generic type. This arrangement ensures that the most specific type of catch block is executed for any given exception. The finally statement executes, allowing cleanup and other code to be executed, whether or not an exception is thrown. You should catch exceptions only when you need to specifically perform any of the following actions:
If a particular method does not need to perform any of these actions, it should not catch the exception; rather, it should allow it to propagate back up the call stack. This keeps your code clean and explicit because you catch only the exceptions that need to be handled within the scope of a particular method and allow all others to continue to propagate. In certain scenarios, an exception you throw may be caught by the runtime, and an exception of another type may be thrown up the call stack in place of the original. In these scenarios your original exception is not lost. Instead, it is set as the InnerException property of the original exception. There are three ways to propagate exceptions:
The .NET Framework has APIs for logging exceptions to the Windows log, database, or a log file; for sending them as asynchronous messages to a message queue or a Simple Mail Transfer Protocol (SMTP) mail; and for creating events out of them to be sent to an external monitoring system that is decoupled from the main application. The monitoring system then notifies interested parties to take appropriate action. This support for logging, monitoring, and notifying is built into the .NET Framework. 1.6.2 Exception Management in JavaMost of the CLR exception management mechanism just described also exists in the Java environment. Java differentiates, however, between checked and unchecked exceptions. Checked exceptions are those that are explicitly coded for. Unchecked (runtime) exceptions and errors don't have to be caught and are propagated automatically up the method call stack. Java has a try-catch-finally construct that can be used to detect, throw, and propagate exceptions. What is missing in the current JDK 1.3 is any built-in support for exception logging to the operating system log, database, and file system. Also, there is no built-in support for asynchronous or synchronous delivery of these exceptions as messages to a message queue or an SMTP mail. Perhaps the reason these features are missing is that the Java designers did not want to make exception logging and notification part of the core exception management services of JDK 1.3. For checked exceptions, it is relatively easy to simulate any kind of logging, notification through third-party logging APIs (such as log4j), JavaMail, and Java Messaging Service (JMS). Future versions of Java may provide hooks to external logging and monitoring systems for unchecked runtime exceptions and errors. |
| [ directory ] |
|