Principles of Exception Handling


The following are some of the generally accepted principles of exception handling:

  1. If you can't handle an exception, don't catch it.

  2. Catch an exception as close as possible to its source.

  3. If you catch an exception, don't swallow it.

  4. Log an exception where you catch it, unless you plan to re-throw it.

  5. Preserve the stack trace when you re-throw the exception by wrapping the original exception in the new one.

  6. Use as many typed exceptions as you need, particularly for application exceptions. Do not just use java.lang.Exception every time you need to declare a throws clause. By fine graining the throws clause, it is self-documenting and becomes evident to the caller that different exceptions have to be handled.

  7. If you programming application logic, use unchecked exceptions to indicate an error from which the user cannot recover. If you are creating third party libraries to be used by other developers, use checked exceptions for unrecoverable errors too.

  8. Never throw unchecked exceptions in your methods just because it clutters the method signature. There are some scenarios where this is good (For e.g. EJB Interface/Implementations, where unchecked exceptions alter the bean behavior in terms of transaction commit and rollback), but otherwise this is not a good practice.

  9. Throw Application Exceptions as Unchecked Exceptions and Unrecoverable System exceptions as unchecked exceptions.

  10. Structure your methods according to how fine-grained your exception handling must be.

Principle 1 is obviously in conflict with 2. The practical solution is a trade-off between how close to the source you catch an exception and how far you let it fall before you've completely lost the intent or content of the original exception.

Principles 3, 4, and 5 is a problems developers face when they catch an exception, but do not know how to handle it and hence throw a new exception of same or different type. When this happens, the original exception ‚ s stack trace is lost. Listing 9.1 shows such a scenario. The SQLException is caught on Line 15 and re-thrown as a application specific UpdateException on Line 16. In the process, the stacktrace with valuable info about the SQLException is lost. Thus the developer can only trace back to Line 16 where the UpdateException is thrown and not beyond that (This is the best case scenario with compiler debug flags turned on. If hotspot compiler was used, the stacktrace would only have the method name without any line number). Listing 9.2 shows almost similar scenario, but the actual exception is logged to the console. This is not good choice and sometimes not feasible because of reasons cited earlier in this section.

Listing 9.1: Losing Exception stack trace
 10 public void updateDetails(CustomerInfo info)                                             throws UpdateException 11 { 12   try { 13     CustomerDAO custDAO = CustDAOFactory.getCustDAO(); 14     custDAO.update(info); 15   } catch (SQLException e) { 16     throw new UpdateException("Details cannot be updated"); 17   } 18 } 
 
Listing 9.2: Losing Exception stack trace
 public void updateDetails(CustomerInfo info)                                              throws UpdateException {   try {     CustomerDAO custDAO = CustDAOFactory.getCustDAO();     custDAO.update(info);   } catch (SQLException e) {     e.printStackTrace();     throw new UpdateException("Details cannot be updated");   } } 
 

A better approach is shown in Listing 9.3. Here, the SQLException is wrapped in the UpdateException . The caller of the updateDetails can catch the UpdateException , and get the knowledge of the embedded SQLException .

Listing 9.3: Preserving Exception stack trace
 public void updateDetails(CustomerInfo info)                                              throws UpdateException {   try {     CustomerDAO custDAO = CustDAOFactory.getCustDAO();     custDAO.update(info);   } catch (SQLException e) {     throw new UpdateException(e);   } } 
 

Principles 7, 8 and 9 in the above list pertain to the discussion of using checked v/s unchecked exceptions. Checked Exceptions are those that extend java.lang.Exception . If your method throws checked exceptions, then the caller is forced to catch these exceptions at compile time or declare in the throws clause of the method. On the other hand, unchecked exceptions are those that extend java.lang.RuntimeException , generally referred to as runtime exceptions. If your method throws a runtime exception, the caller of the method is not forced to catch the exception or add it to the method signature at compile time.

A rule of thumb is to model application exceptions as checked exceptions and system exceptions as unchecked exceptions. The code below is an example of application exception.

 if (withDrawalAmt > accountBalance)          {            throw new NotEnoughBalanceException(Your account does not have enough balance);          } 

When the account does not have enough balance for requested withdrawal amount, the user gets a NotEnoughBalanceException . The user can decide to withdraw lesser amount. Notice that the application exception is not logged. In case of the application exceptions, the developer explicitly throws them in the code and the intent is very clear. Hence there is no need for content (log or stack trace).

Principle 10 is about the use of debug flags with compilation. At compile time it is possible to tell the JVM to ignore line number information. The byte code without the line information are optimized for hotspot or server mode and the recommended way of deployment for production systems. In such cases, the exception stack traces do not provide the line number information. You can overcome this handicap by refactoring your code during development time and creating smaller and modular methods, so that guessing the line numbers for the exceptions is relatively easier.




Struts Survival Guide. Basics to Best Practices
Struts Survival Guide: Basics to Best Practices (J2ee Survival Series)
ISBN: 0974848808
EAN: 2147483647
Year: 2004
Pages: 96

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net