views:

379

answers:

4

I am developing a Struts 2 application with support for multiple languages. If one of the domain objects needs to throw an exception, how can it do so in such a way that the error message is no language-specific? And how can that exception later be displayed based on the current locale?

I was originally looking for a way to localize the error message at the point where it is thrown, but realized that this is not the best way because (a) it introduces an unnecessary dependency between the business model and the web framework; and (b) language should be determined by the current locale when the exception is displayed, not when it is thrown.

So I'm wondering how other people have approached this problem. (And I don't think this is really specific to Struts 2, but relevant to any multi-lingual application).

A: 

Just display the error message in the language you want at the level where you catch and handle the exception, not where you throw it. If you need some extra information such as a username or an identifier, just create a property in your BusinessException class, so that you can use them in the displayed message.

try {
   doSomething();

} catch (BusinessException e) {
   LOG.error("Create your error message in English, it's good for logging", e);

   int id = e.getId();
   // internationalize here
}
candiru
There are many possible errors, but the caller can deal with them all the same way. As such, I don't want to create exception subclasses for every possible error.
Todd Owen
A: 

Why would you throw exceptions with a locale specific message? I would keep them English all the time. You can make your error page locale specific however. Show a locale specific message that something has failed and what the user is supposed to do and that the user can find the details here below (insert plain English error details here). For basic validation messages ("This is required", "Please enter valid email", etcetera) of course use locale specific messages.

BalusC
I want display the exception message directly to the user. It's for obscure errors from the domain objects, e.g. "You cannot withdraw the offer because it has already been approved". Such errors won't occur often, and if they do they it's sufficient just to tell the user that the operation failed and display the exception message.
Todd Owen
That should already be covered by business level validation.
BalusC
A: 

I guess the error page need to use the localized strings to display errors as per the locale. Define your standard messages in respective locale specific files and struts 2 should render them as per the working locale. (see how s:text works).

To define a locale specific file and place where to put them in application see Struts 2 Localization

Nrj
A: 

After noticing that Throwable has a method called getLocalizedMessage(), I decided to use this in my solution.

My class BusinessException extends Exception, and its constructor takes a key representing the error:

public BusinessException(String key, Object[] arguments) {
 this.key = key;
 this.arguments = arguments;
 this.locale = Locale.getDefault();
}

As you can see, the locale defaults to the JVM's default locale. However, in a web application the current request's locale should be used instead. So, BusinessException provides a setLocale() method which should be called before getLocalizedMessage(). Hence, in a Struts2 action the idiom is something like:

try {
    // call business objects
}
catch(BusinessException be) {
    be.setLocale(ActionContext.getContext().getLocale());
    addActionError(be.getLocalizedMessage());
    return ERROR;
}

For the record, the localized messages come from the family of resource bundles for the exception class: BusinessException.properties, etc. The Struts2 application also has an application-wide resource bundle, but I decided not to use that to avoid dependencies by the business objects on the web framework.

Todd Owen