core
the foundation of the platform

[home] [documents] [downloads] [resources] [planning] [testing]

Message Bundles
Description

This is a description of the new message bundle format story for Eclipse.

Summary of the new format:

  • messages.properties - same as before except keys need to be valid Java identifier names (replace "." with "_", etc)
  • Java file has a static String field for each message
  • On startup, we set the values of the fields to be the strings from the messages.properties files and then discard the properties file from memory.

When creating a new message:

  • create a field in your Messages.java file
  • create a key/value pair in your messages.properties file
  • the key MUST be the same as the field name
  • in your code, just use the field reference rather than a lookup (e.g. Messages.my_key)

 

Performance
Time

The code is faster since accessing the messages is just a field access rather than a lookup in the resource bundle.

Our performance results indicate the time to load and initialize bundle are VM dependant but are 5% to 46% faster using the new mechanism.

 

Memory Footprint

With the new mechanism, the rough space savings is 88 + 5N per message where N is the length of the keys.

We have calculated in the best-case scenerio for the Eclipse SDK if every key in every properties file was referenced, then the savings would be roughly 4.5M. (based on the January 11, 2005 integration build)

 

Other benefits
  • Easily catch missing keys - Message lookups are now field accesses so you cannot reference a key that doesn't exist or you will get a compile error.
  • Easily find typos in code when referencing keys - Each key is represented by a field in the class so if the referencing code makes a spelling error, then you will get a compile error.
  • Find unused keys - During the development cycle code is deleted, moved and messages are changed. As a result there are keys in the messages.properties file which are never referenced.These can easily be found now since you can just do a search for references to the field. If there are no references, then delete the field from the class and the key/value pair from the file.

 

Drawbacks
  • There are now 2 files to maintain - Now the messages.properties and the java file must be kept in sync. There is an opportunity for tooling to help with this; a validation tool could indicate problems with markers. Currently there are debug options which log entries which exsit in one file but not the other.

 

File Formats

Client Code

Old Code:

public class MyClass {
   public void myMethod() {
      String message;
      ...
      // no args
      message = Messages.getString("key.one"); //$NON-NLS-1$
      ...
      // bind one arg
      message = MessageFormat.format(Messages.getString("key.two"), new Object[] {"example usage"}); //$NON-NLS-1$ //$NON-NLS-2$
      ...
   }
}

New Code:

public class MyClass {
   public void myMethod() {
      String message;
      ...
      // no args
      message = Messages.key_one;
      ...
      // bind one arg
      message = NLS.bind(Messages.key_two, "example usage"); //$NON-NLS-1$
      ...
   }
}

 

Messages.java

Old Code:
public class Messages {
   private static final String BUNDLE_NAME = "org.eclipse.core.utils.messages"; //$NON-NLS-1$
   private static final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_NAME);
   
   public static String getString(String key) {
      try {
         return bundle.getString(key);
      } catch (MissingResourceException e) {
         return key;
      }
   }
}
New Code:
public class Messages extends NLS {
   private static final String BUNDLE_NAME = "org.eclipse.core.utils.messages"; //$NON-NLS-1$
   
   public static String key_one;
   public static String key_two;
   ...
   static {
      NLS.initializeMessages(BUNDLE_NAME, Messages.class);
   }
}

 

messages.properties

Old Code:
key.one = Hello world.
key.two = This is an {0} of binding with one argument.
New Code:
key_one = Hello world.
key_two = This is an {0} of binding with one argument.

 

Tools
Conversion

We have written a tool which aids in converting from the basic Java resource bundle look-up mechanism, to the new format.

Note that the message bundle access class is replaced when the tool is run. If you define extra code, constants, etc in that class then please read the notes below to ensure that you don't have problems.

Here are the steps to use when converting your code.

  • Download version 1.0.0 and install the plug-in.
  • Run Eclipse.
  • Synchronize with the repository. (you will be using the Synchronize view as your compare browser to view changes)
  • Select your message bundle access class. (e.g. the class which has the #getString(String) method in it)
  • From the context menu, choose "Convert Message Bundle".
  • Choose the class's associated .properties file from the resulting "Open Resource..." dialog.
  • Use the Synchronize view to review the changes.
  • Release the new code.

Notes:

When using the NLS tooling from previous Eclipse releases, the java file which was created had the format of the "old" Messages.java file as described above. (basic class with #getString(String) method) Some plug-in owners have created extra helper methods on the class to aid in their message bundle lookup. Since the conversion tool has only basic functionality, these plug-in developers must perform a couple of extra steps before running the tool.

Essentially what you want to do is get your java file into the basic template form. This is possible via using existing refactorings. For instance, if your class defines a method like this:

public String getString(String key, Object binding) {
   return MessageFormat.format(getString(key), new Object[] {binding});
}

Then you want to do the following:

  1. Change the method body to be: return NLS.bind(getString(key), binding);
  2. Select the method name and from the context menu choose the "Inline" refactoring. This will replace calls to this method in your code with calls to the code in step 1.
  3. Run the tool. Since only calls to #getString(String) exist now, the tool will run sucessfully.