| CONTENTS | PREV | NEXT | INDEX | Designing Enterprise Applications with the J2EETM Platform, Second Edition |
Error messages provide both users and system administrators with information about exceptional conditions. Localizing error messages and logging messages is an important part of localizing an application.
An application's presentation layer should localize messages to clients. Subclasses of java.lang.Exception are recommended for communicating errors between tiers. In a distributed environment, such exception classes must be serializable so that they can move across tier boundaries.
In general, exception classes should not contain localized messages; instead, they should contain information detailing the error. The presentation tier can use the error information to create an error message suitable for the client. JSP pages are a useful mechanism for formatting error messages for Web tier clients. For example, consider a message that creation of a new user account failed because the user ID already exists. A JSP page could deliver content appropriate to the user locale, getting only the user identifier from the exception object.
This section explains existing mechanisms for Web-tier error reporting, and then provides general guidelines for using them in an internationalized design.
10.7.1.0.1 JSP Pages Error MechanismJSP pages have defined behavior for handling request-time errors. Server behavior for errors that occur at page compilation or deployment time is not specified, and is therefore implementation dependent.
Uncaught JSP page exceptions are forwarded to the JSP page's error page, if one is defined. An error page informs the user that an error has occurred. JSP page errorPage defines the URL for the page to display when a JSP page produces errors; for example:
<%@ page language="java" errorPage="errorPages/userExists.jsp" %>
When the JSP page catches an unchecked exception, it creates a new ServletRequest parameter called javax.servlet.jsp.jspException, which contains the exception object. The error page may use this request parameter to format an error message.
The error page must include an isErrorPage directive, like this:
<%@ page language="java" isErrorPage="true" %>
The isErrorPage directive causes the implicit scripting variable exception to be initialized to the exception object thrown by the original JSP page. The page may then format the message using the data encoded in the exception. An error page that could potentially receive more than one type of exception would need to include some sort of logic, best implemented in a custom tag, to deliver the correct error message.
A servlet may indicate an error either by throwing an exception, or by calling ServletResponse.sendError with an HTTP error code argument. The servlet container's default behavior for either case is to serve an implementation-specific error page. Application assemblers or deployers can use servlet deployment descriptor entry <error-page> to specify custom error pages. Errors may be classified either by fully-specified exception class name or by HTTP error code. Servlets should throw only exceptions that are subclasses of RuntimeException, ServletException, or IOException, none of which should be used for application-level exceptions from EJB components. The servlet container error page mechanism should be used only for reporting Web-tier application exceptions.
Localization is primarily about presentation, not business logic. The BluePrints recommendation is to localize error messages in the code that generates a response to a client. For example, JSP pages and servlets in the Web tier can generate localized dynamic error messages for HTML browsers or XML-based rich clients. Application clients can localize data on the server or the client, but in either case, localization should occur in presentation code.
An internationalized MVC controller can easily localize error messages. The controller can catch all exceptions thrown from the Web tier and route them to the appropriate error page based on the name of the exception class. The controller looks up the error page URL in an XML-based exception map, which maps exception class type to error pages by locale. Application component providers, assemblers, or deployers would use the exception map to define localized error pages for application exceptions. Code Example 10.1 below provides a hypothetical example of how such a map might look.
<ExceptionMap>
<Exception type="EjbAppExceptions.UserExistsException">
<ErrorPage locale="en">/jsp/UserExists.jsp</ErrorPage>
<ErrorPage locale="sp">/jsp/sp/UserExists.jsp</ErrorPage>
<!-- Add pages for other locales here -->
</Exception>
<!-- Add additional exception mappings -->
</ExceptionMap>
| Code Example 10.1 Sample Localizing Exception Map for Web-Tier Controller |
A locale-aware Web controller would catch application exceptions from the application's business layer (often implemented by the EJB tier), get the class name of the thrown exception (using getClass.getName), look up the error JSP page in the exception map, and forward the request to the corresponding page (using RequestDispatcher.forward). As described above, the servlet container already offers a way to forward requests to error pages based on uncaught exceptions. The approach presented here also provides localization and handles error messages for business-layer application exceptions.
Looking again at Code Example 10.1, note that the controller forwards an exception's contents to an error page corresponding to the user's locale. An individual error JSP page in this example formats the contents of one application exception for a particular locale. The data in the exception are not localized: The localization is handled by the JSP page formatting the message. In the example shown, UserExistsException reports that the given user name already exists in the system, and the exception object contains the user name that caused the error. The exception does not contain localized messages, because the localization is handled by the JSP page for the locale. The English page (/jsp/UserExists.jsp) contains a line something like this:
User <app:exception property="userName"/> already exists.
while the Spanish page (/jsp/sp/UserExists.jsp) contains a line like this:
El usuario <app:exception property="userName"/> ya existe.
Note that the JSP pages follow the BluePrints recommendation to use a custom tag, rather than a scriptlet or an expression, to retrieve the user name from the application exception.
System exceptions are intended for a system administrator, so they need to be readable by those maintaining the runtime system. System exceptions and log messages need localization, but using the application presentation layer is too complex for this purpose. Instead, the BluePrints recommendation is to use resource bundles to localize system exceptions and log messages. System exception and log messages are typically for one locale only. The simplest way to determine a locale for system messages is to use the system default locale. If the application default locale differs from server to server, the system message locale may be indicated in a deployment descriptor environment entry for the component that produces the message.
Large system messages are localizable using XSLT (as described in Section 10.6.1 on page 337).
System exceptions should always be subclasses of java.lang.RuntimeException. Typically, the message of a RuntimeException explains the error condition. In an internationalized design, the exception message should contain the resource bundle key of the system message, not the message itself. The component that writes the log can use resource bundles and class MessageFormat to localize the exception message.