Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 3 of 4
In order to prevent runtime errors caused by typos in key names, the key names used by an application should be given symbolic
names; these names should be used instead of the actual key names. That way, if you mistype a message string's name, you'll
find out at compile time. (The Javadoc pages for ResourceBundle make the error of embedding strings in the text as keys, but you should strive to do better in your programs.) Here is a
simple example of how the above code fragments would be written using resource bundles:
Listing 3. Build error messages with resource bundles
public interface FooResourcesKeys {
public static String MSG_FILE_NOT_FOUND = "MSG_FILE_NOT_FOUND";
public static String MSG_CANT_OPEN_FILE = "MSG_CANT_OPEN_FILE";
}
public class FooResources extends ListResourceBundle
implements FooResourcesKeys {
public Object[][] getContents() {
return contents;
}
static final Object[][] contents = {
// Localize from here
{MSG_FILE_NOT_FOUND, "Cannot find file {1}"},
{MSG_CANT_OPEN_FILE, "Cannot open file {1}"},
// Localize to here
};
}
public class MessageUtil {
private static ResourceBundle myResources =
ResourceBundle.getBundle("com.foo.FooResources");
private static String getMessageString(String messageKey) {
return myResources.getString(messageKey);
}
public static String formatMessage(String messageKey) {
MessageFormat mf = new MessageFormat(getMessageString(messageKey));
return mf.format(new Object[0]);
}
public static String formatMessage(String messageKey,
Object arg0) {
MessageFormat mf = new MessageFormat(getMessageString(messageKey));
Object[] args = new Object[1];
args[0] = arg0;
return mf.format(args);
}
public static String formatMessage(String messageKey,
Object arg0,
Object arg1) {
MessageFormat mf = new MessageFormat(getMessageString(messageKey));
Object[] args = new Object[2];
args[0] = arg0;
args[1] = arg1;
return mf.format(args);
}
// Include implementations of formatMessage() for as many arguments
// as you need
}
public class SomeClass implements FooResourcesKeys {
...
if (!file.exists()) {
throw new ResourceException(
MessageUtil.formatMessage(MSG_FILE_NOT_FOUND,
file.getName()));
}
}
In the above example, for each error message you will use in the application, you need to place one entry in FooResourcesKeys, and a corresponding entry in each resource bundle implementation (one for each locale) for that key. If you've named your
resource bundles correctly, ResourceBundle will be able to chain lookups so that if an entry is not in the localized bundle, it will search the default bundle too.
For each point in your code where you will throw an exception, you will need to create the message string through MessageUtil as shown in Listing 3's SomeClass.
In order to facilitate code reuse, you can extend this technique to support multiple resource bundles, with one bundle per
component or even one per package. In this case, the MessageUtil class would be slightly more complicated, specifying an additional argument for identifying what bundle a given error message
comes from.