Custom exception classes
The purpose of a custom exception class is to integrate the look-up of localized message strings in a custom message catalog into the mechanism that is used for error reporting in the client infrastructure. If you need only one error message catalog, you need only one custom exception class, but there is no restriction on the number of exception classes or message catalogs you can create.
Implementing custom exception handling using a custom exception class is formulaic. As the custom exception class must integrate into the existing message reporting system, only numeric message identifiers are supported for custom exceptions and there is very little room for deviation from the prescribed approach. You cannot, for example, use literal message strings in your code, you must use references to externalized strings.
Here is an example of a custom exception class:
public class CustomConversionException
extends ConversionException {
private static final MessageLocalizer MESSAGE_LOCALIZER
= new CatalogMessageLocalizer("custom.ErrorMessages");
public CustomConversionException(int messageID) {
super(messageID);
}
public CustomConversionException(int messageID,
String[] messageArgs) {
super(messageID, messageArgs);
}
public CustomConversionException(int messageID,
String messageArg) {
super(messageID, messageArg);
}
public MessageLocalizer getMessageLocalizer() {
return MESSAGE_LOCALIZER;
}
}
This class extends ConversionException and implements a number of
constructors simply by invoking the equivalent constructors in the super-class. You only
need to implement the constructors that you intend to use, the rest of the constructors in
the super-class can be ignored (Java classes do not inherit constructors, hence the need to
re-implement them). The available constructors are described in the JavaDoc. Next, it
defines a static MessageLocalizer field and instantiates it with a
CatalogMessageLocalizer object that takes your custom catalog name as its
argument. The getMessageLocalizer method then returns this static object.
That is all there is to it.
When you throw exceptions of this type, you need to pass your message identifier and
optional arguments to the relevant constructor. You can define constants for your numeric
message identifiers in this class if you wish. Your message strings can contain placeholders
such as %1s
, %2s
, etc., to be replaced by the argument strings (only string
types are supported). For an array of arguments, %1s
will be replaced by the first
argument in the array (index zero), and so on. The special argument %0s
can be used
to represent the name of the field in error, but you will not need to provide any matching
argument string for that value; it will be substituted automatically. You can also use the
same placeholder several times in a single message if you want the same value to be inserted
in more than one place. Here is a sample message catalog file containing a single
message:
-200000=ERROR: The field '%0s' contains an invalid value '%1s'.
The file is a standard Java properties file where each line contains a numeric identifier
and a message string separated by an equals character. A collection of properties files with
the same base name but with locale codes appended is treated as a single message catalog.
The custom exception class in the example above refers to the message catalog as
custom.ErrorMessages
, so the properties files should be located on the Java
classpath in the custom package folder and in files named
ErrorMessages.properties,
ErrorMessages_en_US.properties,
ErrorMessages_fr_CA.properties, etc., as you would do for any other
custom properties files. There should be one properties file for each locale that your
application supports. The selection of the correct locale-specific properties file at
run-time is completely automatic once you have written your custom exception class as shown
above.
Ensuring that these files end up on the classpath is simply a matter of placing them in their appropriate package folders below your web application's <client-dir>/<custom>/javasource folder, where custom is the name of a custom component. (see CDEJ project folder structure for details). The Java source files for your custom exceptions should also be placed below the <client-dir>/<custom>/javasource folder in the appropriate folders for the package names you have used.
When throwing a custom exception, the code will look like this (assuming you have decided not to use constants for your error message identifiers):
throw new CustomConversionException(-200000, myInvalidValue);
Remember, it is not necessary to pass any argument corresponding to the %0s
placeholder; it will be calculated and substituted automatically.
If you examine the constructors of the ConversionException class, you will
note that many accept a java.lang.Throwable object as the last argument.
You can implement similar constructors and pass Throwable objects (usually
other exception objects) to your custom exceptions when you want your custom exception to
include the exception that caused it. This is often very useful as error messages for both
exceptions will be reported automatically and both stack traces will be included on an
application error page if the error page is required. In fact, there is no imposed limit to
the length of the chain of exceptions that can be built this way; the exception that you add
to your own may already contain a reference to another exception, and so on.
This example show how you can even report two separate error messages at once. Perhaps one is a generic message that states that a field does not contain a valid value and another suggests the expected format for that value. You will have to implement the appropriate constructor to support this, but the reporting mechanism is automatic.
throw new CustomConversionException(
-200000, myInvalidValue,
new CustomConversionException(-200003));