Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 78218

Summary: Externalize Strings generates code with unhandled exception MissingResourceException
Product: [Eclipse Project] JDT Reporter: Dan Kehn <kehn>
Component: UIAssignee: Dani Megert <daniel_megert>
Status: RESOLVED WONTFIX QA Contact:
Severity: minor    
Priority: P3 CC: daniel_megert
Version: 3.0.1   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description Dan Kehn CLA 2004-11-09 15:24:00 EST
The Source > Externalize Strings... choice generates a resource bundle wrapper 
that looks something like this (using "Hello, World" template):

--- begin ---
public class Messages {
  private static final String BUNDLE_NAME = "helloworld.messages";//$NON-NLS-1$

  private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
      .getBundle(BUNDLE_NAME);

  private Messages() {
  }

  public static String getString(String key) {
    try {
      return RESOURCE_BUNDLE.getString(key);
    } catch (MissingResourceException e) {
      return '!' + key + '!';
    }
  }
}
--- end ---

Subsequent uses of this wrapper look like this:

--- begin ---
public void run(IAction action) {
  MessageDialog.openInformation(
    window.getShell(),
    Messages.getString("SampleAction.0"), //$NON-NLS-1$
    Messages.getString("SampleAction.1")); //$NON-NLS-1$
}
--- end ---

The problem is the static initializer 	

private static final ResourceBundle RESOURCE_BUNDLE = 
    ResourceBundle.getBundle(BUNDLE_NAME);

If the bundle isn't found, whatever method that happen to be the caller will 
get the unchecked exception MissingResourceException, which it will very 
likely not handle. In the case of "Hello, World", the result is 

"Could not create action delegate for id: helloworld.SampleAction
Reason: Plug-in helloworld was unable to load class helloworld.SampleAction."

Perhaps this was intentional, i.e., the resource bundle wrapper didn't want 
to 'eat' the error. I think a better solution would be to log an error and 
return the key. It would be prudent, whatever the choice, to put this code 
into a common wrapper superclass (e.g., 
org.eclipse.runtime.core.AbstractMessages) where it could (a) define the 
common methods that are currently generated in the RB wrapper, and (b) be 
corrected release-to-release if errors / improvements are necessary.
Comment 1 Dirk Baeumer CLA 2004-11-17 05:48:24 EST
Using a super class isn't possible since this would bind Externalize String to
the runtime. Externalize String must work with "normal" Java code as well. 

Another idea is to lazy create the bundle inside getString so that the exception
can be handled there.

Daniel, comments.
Comment 2 Dan Kehn CLA 2004-11-17 10:22:57 EST
Good point, Dirk. 

A common superclass could be optionally specified on the current Externalize 
Strings dialog under the "accessor class" field. If you want to get fancy, 
auto-select / prefill the accessor superclass field if the classpath / plug-in 
<requires> clause includes the "standard" implementation. For extra credit, 
add a settable default in the Java preferences.
Comment 3 Martin Aeschlimann CLA 2004-11-22 04:49:02 EST
To create the resource bundle lazily makes most sense to me.
For the superclass request we could think about offering a template for the
message class, but on the other hand that's a bit overkill; the user is already
free to change that class as they want after it is created.
Wouldn't be bad it we add a comment to 'BUNDLE_NAME' to not change this field
name as the NLS-wizard needs this to recognize it as a NLS-class

Moving to Dani!
Comment 4 Dani Megert CLA 2004-11-22 05:08:16 EST
Discussed last week with Erich and we agreed that this is intentional i.e. we
want the (client) code to fail as soon as possible.

There are no plans to change this.

See bug 79063 for more the template idea mentioned in comment 3.