Provides utilities and common files used by the rest of MRALD. Utilities include:

Error and Exception Handling for MRALD

Why?

MRALD as a whole should have a consistent Error and Exception handling philosophy and infrastructure. This document describes the philosophy and infrastructure provided.

Java Basics

From the Java Language Specification, Second Edition:
The possible exceptions in a program are organized in a hierarchy of classes, rooted at class Throwable, a direct subclass of Object. The classes Exception and Error are direct subclasses of Throwable. The class RuntimeException is a direct subclass of Exception.

Programs can use the pre-existing exception classes in throw statements, or define additional exception classes, as subclasses of Throwable or of any of its subclasses, as appropriate. To take advantage of the Java platform's compile-time checking for exception handlers, it is typical to define most new exception classes as checked exception classes, specifically as subclasses of Exception that are not subclasses of RuntimeException.

The class Exception is the superclass of all the exceptions that ordinary programs may wish to recover from. The class RuntimeException is a subclass of class Exception. The subclasses of RuntimeException are unchecked exception classes. The subclasses of Exception other than RuntimeException are all checked exception classes.

The class Error and its subclasses are exceptions from which ordinary programs are not ordinarily expected to recover. See the Java API specification for a detailed description of the exception hierarchy.

The class Error is a separate subclass of Throwable, distinct from Exception in the class hierarchy, to allow programs to use the idiom:

} catch (Exception e) {
to catch all exceptions from which recovery may be possible without catching errors from which recovery is typically not possible.
Also, in Java 1.4, we have access to the new Chained Exception Facility:
It is common for Java code to catch one exception and throw another:
try {
    ...
} catch(YourException e) {
    throw new MyException();
}
Unfortunately, the information contained in the "causative exception" (YourException in the example above) is generally lost, which greatly complicates debugging. Recognizing this problem, developers sometimes build ad hoc mechanisms to allow certain "wrapped exceptions" to contain a second exception. An accessor is generally provided to extract the contained exception. Such mechanisms are sometimes known as "exception chaining facilities", as they allow arbitrary chains of exceptions to be constructed when contained exceptions are, themselves, wrapped exceptions.

There are many advantages to unifying all of these facilities. Chief among them are: (1) We guarantee that anyone who wants to record the fact that one exception caused another can do so, regardless of what the exceptions are. (2) By providing a common API to record the fact that one exception caused another, we ease this task, making it more likely that programmers will take the trouble to do it. (3) By providing a common API to access causative exceptions, we greatly increase the likelihood that this information will be made available to those who need it. In fact, the proposed mechanism prints entire "causal chain" as part of the standard stack backtrace, ensuring that preexisting programs will provide this information with no additional effort on the part of their authors.

To address these issues, we have added two new methods to Throwable, getCause() and initCause(Throwable), and two new constructors, Throwable(Throwable) and Throwable(String, Throwable). Other "general purpose" exception classes (like Exception, RunTimeException and Error) have been similarly outfitted with (Throwable) and (String, Throwable) constructors. However, even exceptions without such constructors will be usable as "wrapped exceptions" via the initCause method.

The implementation of Throwable.printStackTrace has been modified to display backtraces for the entire causal chain of exceptions. New method getStackTrace provides programmatic access to the stack trace information provided by printStackTrace.

All of the platform's wrapped exceptions will be retrofitted to support the new facility (in addition to their legacy APIs).

MRALD complications and opportunities

In MRALD, much of the internal state of the current thread can be shown by the internal state of the MsgObject. In order to take advantage of all these facilities, two new classes will be added to MRALD, MraldException and MraldError. Both these take constructors containing a MsgObject as well as having accessor methods for getting and setting the MsgObject fields in these classes.

MraldException

An MraldException is a subclass of Exception that indicates either reasonable calling code might want to catch this exception, or the current thread's MsgObject is not available to the throwing method.

An MraldException should be used when the current thread's MsgObject is not available OR the calling code should handle the exception.

An MraldError needs to be declared in a method's throws clause.

MraldError

An MraldError is a subclass of Error that indicates a serious problem that calling code cannot be expected to deal with.

An MraldError should only be used when the current thread's MsgObject is available AND there is no way reasonable calling code should be expected to handle the problem. If the case does not meet both requirements, use an MraldException instead.

An MraldError does not need to be declared in a method's throws clause.

Handling exceptions

When used properly, all errors and unhandled exceptions will traverse up the execution path to a final exception handling facitlity which will provide feedback to the user. The primary way of doing this now is ErrorHandler.jsp, though other mechanisms are possible. All of MRALD's code will be retrofitted to support the new facility.

In ErrorHandler.jsp, the user will be provided with a simple message, instructions on how to report the problem, and a link to an .err file. This file is a file that is created and contains the exception cause, the stack trace, and the interal state of the MsgObject at the time of the failure. For certain common exceptions, the user may also receive suggestions on how to fix a problem. A sample file is included below. Remember when writing exception messages in MRALD that the end user gets what you write as the error message. In addition to being useful to another developer (not just you), it should also be fairly nice to an average user.

Sample MRALD .err file:

          Fri Aug 29 10:04:46 EDT 2003
          ~v~v~v~v~v~v~v~v~v~v~v~v~v~v~v~v~v~v~v~v~v~v~
          Message: org.mitre.mrald.util.MraldThrowable: ERROR:  For SELECT DISTINCT, ORDER BY expressions must appear in target list
          Root Cause:
          java.sql.SQLException: ERROR:  For SELECT DISTINCT, ORDER BY expressions must appear in target list
          at org.postgresql.core.QueryExecutor.execute(QueryExecutor.java:131)
          at org.postgresql.jdbc1.AbstractJdbc1Connection.ExecSQL(AbstractJdbc1Connection.java:505)
          at org.postgresql.jdbc1.AbstractJdbc1Statement.execute(AbstractJdbc1Statement.java:320)
          at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:48)
          at org.postgresql.jdbc1.AbstractJdbc1Statement.executeQuery(AbstractJdbc1Statement.java:153)
          at org.postgresql.jdbc1.AbstractJdbc1Statement.executeQuery(AbstractJdbc1Statement.java:141)
          at org.mitre.mrald.output.OutputManager.run(OutputManager.java:423)
          at java.lang.Thread.run(Thread.java:534)
          State of this MRALD run's MsgObject:
          Content Type: text/html
          Queries stored:
          SELECT DISTINCT addictives.pat_id, addictives.heroin, subject.initial_exam, subject.nation_of_residence, subject.gender, subject.second_language, subject.third_language, subject.handedness From subject, addictives Where  ( subject.pat_id = 'MNI_0100' ) AND addictives.pat_id=subject.pat_id ORDER BY addictives.ex_date DESC
          Links stored:

          This is a(n) LINK element
          It's type and memory location are org.mitre.mrald.query.LinkElement@162e295
          It contains the following in its nameValues:
          SecondaryLink=addictives.pat_id; addictives.pat_id
          PrimaryLink=subject.pat_id; subject.pat_id
          Working Objects stored:

          This is a(n) FILTER element
          It's type and memory location are org.mitre.mrald.query.FilterElement@109de5b
          It contains the following in its nameValues:
          Table=subject
          Value=MNI_0100
          Field=pat_id

          This is a(n) SELECT element
          It's type and memory location are org.mitre.mrald.query.SelectElement@e53220
          It contains the following in its nameValues:
          Table=subject
          Field=second_language
          Order=29

          This is a(n) SELECT element
          It's type and memory location are org.mitre.mrald.query.SelectElement@13e0aba
          It contains the following in its nameValues:
          Table=subject
          Field=gender
          Order=26

          This is a(n) SELECT element
          It's type and memory location are org.mitre.mrald.query.SelectElement@3257b8
          It contains the following in its nameValues:
          Table=subject
          Field=nation_of_residence
          Order=25

          This is a(n) SELECT element
          It's type and memory location are org.mitre.mrald.query.SelectElement@11d2572
          It contains the following in its nameValues:
          Table=subject
          Field=initial_exam
          Order=23

          This is a(n) SORT element
          It's type and memory location are org.mitre.mrald.query.SortElement@859a68
          It contains the following in its nameValues:
          Table=addictives
          OrderType=DESC
          Field=ex_date
          Order=1

          This is a(n) SELECT element
          It's type and memory location are org.mitre.mrald.query.SelectElement@15c62bc
          It contains the following in its nameValues:
          Table=addictives
          Field=pat_id
          Order=1

          This is a(n) FILTER element
          It's type and memory location are org.mitre.mrald.query.FilterElement@5660d6
          It contains the following in its nameValues:
          Table=addictives
          Operator=<=
          Field=ex_date

          This is a(n) SELECT element
          It's type and memory location are org.mitre.mrald.query.SelectElement@ef83d3
          It contains the following in its nameValues:
          Table=addictives
          Field=heroin
          Order=15

          This is a(n) FILTER element
          It's type and memory location are org.mitre.mrald.query.FilterElement@b7b3f9
          It contains the following in its nameValues:
          Table=addictives
          Operator=>=
          Field=ex_date

          This is a(n) SELECT element
          It's type and memory location are org.mitre.mrald.query.SelectElement@88df60
          It contains the following in its nameValues:
          Table=subject
          Field=handedness
          Order=34

          This is a(n) SELECT element
          It's type and memory location are org.mitre.mrald.query.SelectElement@1318b
          It contains the following in its nameValues:
          Table=subject
          Field=third_language
          Order=30
          ~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~

Dealing with .err files

Left alone, .err files will quickly proliferate and fill up your ROOT (or other) directory. To avoid this, there is an option in the config.properties file, errFileExpireDays, which takes a number. After XX days, the .err files will be deleted. This "expiring" of .err files is still being discussed - any input is welcome.