Difference between revisions of "Java Error Handling"

From AgileApps Support Wiki
imported>Aeric
imported>Aeric
Line 9: Line 9:


===Error Handling Principles===
===Error Handling Principles===
# All calls to platform functions need to be in a try-catch block.
# All calls to platform functions and standard Java functions need to be in a try-catch block.
# All calls to methods that invoke a platform function need to be in a try-catch block.
# Calls to [[Functions.showMessage]] are useful as part of the normal code flow, but they are useless in a catch-block.<br>(You have to re-throw the exception, or the user never sees it. And when you re-throw it, the error message it contains is the ''only'' thing the user sees.)
# When calling a platform function, ...
# When calling a routine, ...
# A standard Java stack trace is of little value, since is consists almost entirely of calls inside the platform.
# A standard Java stack trace is of little value, since is consists almost entirely of calls inside the platform.
# To get a useful trace, catch every exception and add the name of the current method to the log.
# To get a useful trace, catch every exception and add the name of the current method to the log.
#:a. Call [[Logger.info]]. Use the class name as "category" label.
#:a. Call [[Logger.info]]. Use the class name as "category" label.
#:b. Include the method name in the message.
#:b. Include the method name in the message.
#:c. Include the exception's class name, using <tt>e.getClass().getName()</tt>.<br>For things like ArrayIndexOutOfBounds, that will generally tell you what went wrong.
#:c. Also include the exception's class name, using <tt>e.getClass().getName()</tt>.<br>For things like ArrayIndexOutOfBounds, that will generally tell you what went wrong.
# In a method that is invoked directly from the platform, the rule is to LOG, SHOW, and THROW:
# In a catch block, the rule is to LOG and RE-THROW:
#:<syntaxhighlight lang="java" enclose="div">
#:<syntaxhighlight lang="java" enclose="div">
// LOG, SHOW, and RE-THROW
try {
String msg = "Unexpected exception in methodName()";
  ...
log(msg + ":\n" + e.getClass().getName() );     
}
show(msg + " - see debug log");   
catch (Exception e) {
throw e; // Roll back the current transaction
  // LOG and RE-THROW
  String msg = "Unexpected exception in methodName()";
  log(msg + ":\n" + e.getClass().getName() );     
  throw e; // Roll back the current transaction
}
</syntaxhighlight>
</syntaxhighlight>
#: If there are multiple calls to platform functions, and you want different messages for each, you need a separate try-catch block for each.
#: If there are multiple calls to platform functions, and you want different messages, you need a separate try-catch block for each call.
#:
#:
# In a catch block inside a method that is called by your code, the rule is to LOG and THROW:
# In code that is outside of a catch block (for example, when a call worked but you got back an unexpected value), the rule is to THROW THE ERROR, using [[Functions.throwError]] to generate an exception that interrupts processing and rolls back the current transaction:
#:<syntaxhighlight lang="java" enclose="div">
#:<syntaxhighlight lang="java" enclose="div">
// LOG and RE-THROW
// THROW THE ERROR
String msg = "Unexpected exception in methodName()";
String msg = ""Error <while doing something> in methodName()";
log(msg + ":\n" + e.getClass().getName() ); //+ "\n" + e.getMessage() ); 
throw e;
</syntaxhighlight>
#:
# In the catch block surrounding the call you make to that method, the rule is to SHOW:
#:<syntaxhighlight lang="java" enclose="div">
// SHOW
show("Error in getActivities() - see debug log");
return;
</syntaxhighlight>
#:
# Outside of a catch block, the rule is to THROW, using [[Functions.throwError]] to generate an exception that interrupts processing and rolls back the current transaction:
#:<syntaxhighlight lang="java" enclose="div">
// THROW
String msg = ""Error <while doing something>";
Functions.throwError(msg);
Functions.throwError(msg);
</syntaxhighlight>
</syntaxhighlight>

Revision as of 02:19, 14 November 2014

The goal of error handling is identify the error that occurred, where it happened, and (ideally) what data was present at the time. The ideas presented in this section can help to achieve those goals.

Error Handling Tools

The Java Class Template embodies the error handling principles explained below. To do so, it uses the following tools:

  • Logger.info - Put a text message into the Debug Log. (Add "/n" (newline) to create a line break.)
  • Functions.showMessage - Display an HTML message onscreen. (Add "<br>" to create a line break.
    Only one message is displayed, when the code returns to the platform. Multiple calls are concatenated.)
  • Functions.throwError - Raise an exception to discontinue processing and roll back the current transaction.

get a stack trace, but it generally doesn't help very much, because the trace is almost entirely devoted to the sequence of platform calls that got to your code. You're more interested in the steps your program followed. Following these steps gives you that information

Error Handling Principles

  1. All calls to platform functions and standard Java functions need to be in a try-catch block.
  2. Calls to Functions.showMessage are useful as part of the normal code flow, but they are useless in a catch-block.
    (You have to re-throw the exception, or the user never sees it. And when you re-throw it, the error message it contains is the only thing the user sees.)
  3. A standard Java stack trace is of little value, since is consists almost entirely of calls inside the platform.
  4. To get a useful trace, catch every exception and add the name of the current method to the log.
    a. Call Logger.info. Use the class name as "category" label.
    b. Include the method name in the message.
    c. Also include the exception's class name, using e.getClass().getName().
    For things like ArrayIndexOutOfBounds, that will generally tell you what went wrong.
  5. In a catch block, the rule is to LOG and RE-THROW:
    try {
       ...
    }
    catch (Exception e) {
       // LOG and RE-THROW
       String msg = "Unexpected exception in methodName()";
       log(msg + ":\n" + e.getClass().getName() );    
       throw e; // Roll back the current transaction
    }
    
    If there are multiple calls to platform functions, and you want different messages, you need a separate try-catch block for each call.
  6. In code that is outside of a catch block (for example, when a call worked but you got back an unexpected value), the rule is to THROW THE ERROR, using Functions.throwError to generate an exception that interrupts processing and rolls back the current transaction:
    // THROW THE ERROR
    String msg = ""Error <while doing something> in methodName()";
    Functions.throwError(msg);