Previous | Next | Trail Map | Internationalization | Working with Exceptions

Creating Locale-independent Exception Subclasses

You'll want to create Exception subclasses when you need to handle errors specific to your own applications. You can make your Exception subclasses locale-independent by overriding their getLocalizedMessage methods. Each getLocalizedMessage method you override should isolate the message it returns in a ResourceBundle. This allows the message to be translated into various languages during localization.

In the example that follows, we'll show you how to create an Exception subclass that displays a locale-independent message. The source code for the example program is in two files: OverLimitException.java and Account.java.

The Account program simulates a simple credit account. If this program exceeds the credit limit, it retrieves a localized message from a ResourceBundle called ExceptionBundle, and then displays the message. In the ExceptionBundle_en_US.properties file, we specify this message as follows:

pattern =  Negative balance of {0,number,currency} is not allowed.
The Account program fetches the message with the getLocalizedMessage method, which we implement in an Exception subclass called OverLimitException. The getLocalizedMessage method accepts a Locale object as a parameter. We specify this Locale when fetching the message pattern from the ResourceBundle, and also when defining the MessageFormat object. Therefore, our OverLimitException class is locale-sensitive:
public class OverLimitException extends Exception {

   private double detail;

   public OverLimitException (double amount) {
       detail = amount;
   }

   public String getMessage() {
      return getLocalizedMessage(Locale.getDefault());
   }

   public String getLocalizedMessage(Locale currentLocale) {
      ResourceBundle messages =
         ResourceBundle.getBundle("ExceptionBundle",currentLocale);
      Object[] messageArguments = {new Float(detail)};
      MessageFormat formatter = new MessageFormat("");
      formatter.setLocale(currentLocale);
      formatter.applyPattern(messages.getString("pattern"));
      return formatter.format(messageArguments);
   }
}
In the Account class, the withdraw method throws an OverLimitException if the new balance exceeds the credit limit. In the code that follows, note that we pass the value parameter to the OverLimitException constructor in the throw statement. The constructor assigns this parameter to the detail field of the OverLimitException class. The getLocalizedMessage method inserts a String representation of the detail field in the message it returns. The withdraw method is as follows:
public void withdraw(double amount) throws OverLimitException {
   double value = balance - amount;
   if (value < creditLimit) {
     throw new OverLimitException(value);
   }
   else {
      balance = value;
   }
}
In the main method of the Account class, we invoke the withdraw method and catch the OverLimitException whenever it's thrown. The catch clause prints the String returned by getLocalizedMessage. Here is the main method:
static public void main(String[] args) {

   Locale[] locales = {
      new Locale("en","US"),
      new Locale("de","DE")
   };

   Account credit = new Account();
   credit.deposit(20.00f);

   for (int k = 0; k < locales.length; k++) {
      try {
         credit.withdraw(1000.00f);
      }
      catch (OverLimitException e) {
         System.out.println("Locale: " + locales[k].toString());
         System.out.println(e.getLocalizedMessage(locales[k]));
      }
   } // for
}
The Account program displays two localized messages. Not only is the message text in the correct language, but the currency is expressed in a format appropriate to each Locale:
% java Account

Locale: en_US
Negative balance of ($980.00) is not allowed.

Locale: de_DE
Ein negativer Kontostand von -980,00 DM is nicht gestattet.


Previous | Next | Trail Map | Internationalization | Working with Exceptions