platform-core-home/documents/3.1/message_bundles.html

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (view) (download) (as text)

1 : dj 1.1 <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
2 :     <html>
3 :     <head>
4 :     <title>Eclipse Platform/Core</title>
5 :     <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
6 :     <link rel="stylesheet" href="http://dev.eclipse.org/default_style.css" type="text/css">
7 :     <STYLE TYPE="text/css">
8 :     <!--
9 :     CODE { font-size: 80% }
10 :     -->
11 :     </STYLE>
12 :     </head>
13 :     <body>
14 :     <center>
15 :     <font class=indextop>core</font><br>
16 :     <font class=indexsub>the foundation of the platform</font><p></p>
17 :     <a href="../../main.html">[home]</a>
18 :     <a href="../../documents.html">[documents]</a>
19 :     <a href="../../downloads.html">[downloads]</a>
20 :     <a href="../../resources.html">[resources]</a>
21 :     <a href="../../planning.html">[planning]</a>
22 :     <a href="../../testing.html">[testing]</a>
23 :     </center>
24 :     <br>
25 :     <table BORDER=0 CELLPADDING=2 WIDTH="100%" >
26 :     <tr>
27 :     <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica" color="#FFFFFF">Message Bundles</font></b></td>
28 :     </tr>
29 :     <tr>
30 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
31 :    
32 : dj 1.2 <td WIDTH="98%"><b>Description</b> <p>Standard Java ResourceBundles have quite
33 :     inefficient space characteristics. Since a running Eclipse tends to have
34 :     many externalized messages we have implemented a new message bundle story
35 :     to be used in Eclipse. The mechanism is quite simple and completely generic
36 :     - it can be used anywhere.</p>
37 :     <p>Summary of the new approach:</p>
38 : dj 1.1 <ul>
39 : dj 1.2 <li>messages.properties - this file is same as before except all keys
40 :     need to be valid Java identifiers.
41 :     <li>Each message file has a corresponding Java class.
42 :     <li>Each key/value pair in the file has a public static String field whose
43 :     name is the same as the message key.
44 :     <li>When message bundles are loaded, the values of the fields are set
45 :     to be the values from the messages.properties files.
46 :     <li>The message properties files are purged from memory.
47 :     </ul>
48 :     <p>When creating a new message:</p>
49 : dj 1.1 <ul>
50 :     <li>create a field in your Messages.java file</li>
51 : dj 1.2 <li>create a key/value pair in your messages.properties file where the
52 :     key name matches the field name</li>
53 :     <li>to reference the message, simply reference the field (e.g. Messages.my_key)
54 :     rather than the standard lookup</li>
55 : dj 1.1 </ul>
56 :     <p>&nbsp;</p></td>
57 :     </tr>
58 :     <tr>
59 :     <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica" color="#FFFFFF">File Formats</font></b></td>
60 :     </tr>
61 :     <tr>
62 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
63 :    
64 :     <td WIDTH="98%"><p><b>Client Code</b></p>
65 :     Old Code:
66 :     <p>
67 :     <pre><code>public class MyClass {
68 :     &nbsp;&nbsp;&nbsp;public void myMethod() {
69 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String message;
70 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
71 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// no args
72 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message = Messages.getString("key.one"); //$NON-NLS-1$
73 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
74 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// bind one arg
75 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message = MessageFormat.format(Messages.getString("key.two"), new Object[] {"example usage"}); //$NON-NLS-1$ //$NON-NLS-2$
76 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
77 :     &nbsp;&nbsp;&nbsp;}
78 :     }</code></pre>
79 :     </p>
80 :    
81 :     New Code:
82 :     <p><pre><code>public class MyClass {
83 :     &nbsp;&nbsp;&nbsp;public void myMethod() {
84 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String message;
85 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
86 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// no args
87 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message = Messages.key_one;
88 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
89 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// bind one arg
90 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message = NLS.bind(Messages.key_two, "example usage"); //$NON-NLS-1$
91 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
92 :     &nbsp;&nbsp;&nbsp;}
93 :     }</code></pre></p>
94 :     <p>&nbsp;</p>
95 :     </td>
96 :     </tr>
97 :     <tr>
98 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
99 :    
100 :     <td WIDTH="98%"><p><b>Messages.java</b></p>
101 :     Old Code:
102 :     <pre><code>public class Messages {
103 :     &nbsp;&nbsp;&nbsp;private static final String BUNDLE_NAME = &quot;org.eclipse.core.utils.messages&quot;; //$NON-NLS-1$
104 :     &nbsp;&nbsp;&nbsp;private static final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_NAME);
105 :     &nbsp;&nbsp;&nbsp;
106 :     &nbsp;&nbsp;&nbsp;public static String getString(String key) {
107 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try {
108 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return bundle.getString(key);
109 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch (MissingResourceException e) {
110 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return key;
111 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
112 :     &nbsp;&nbsp;&nbsp;}
113 :     }</code></pre>
114 :    
115 :     New Code:
116 :     <pre><code>public class Messages extends NLS {
117 :     &nbsp;&nbsp;&nbsp;private static final String BUNDLE_NAME = &quot;org.eclipse.core.utils.messages&quot;; //$NON-NLS-1$
118 :     &nbsp;&nbsp;&nbsp;
119 :     &nbsp;&nbsp;&nbsp;public static String key_one;
120 :     &nbsp;&nbsp;&nbsp;public static String key_two;
121 :     &nbsp;&nbsp;&nbsp;...
122 :     &nbsp;&nbsp;&nbsp;static {
123 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NLS.initializeMessages(BUNDLE_NAME, Messages.class);
124 :     &nbsp;&nbsp;&nbsp;}
125 :     }</code></pre>
126 :     <p>&nbsp;</p>
127 :     </td>
128 :     </tr>
129 :     <tr>
130 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
131 :    
132 :     <td WIDTH="98%"><p><b>messages.properties</b></p>
133 :     Old Code:
134 :     <pre><code>key.one = Hello world.
135 :     key.two = This is an {0} of binding with one argument.
136 :     </code></pre>
137 :     New Code:
138 :     <pre><code>key_one = Hello world.
139 :     key_two = This is an {0} of binding with one argument.
140 :     </code></pre>
141 :     </p>
142 :     <p>&nbsp; </p></td>
143 :     </td>
144 :     </tr>
145 :     <tr>
146 : dj 1.2 <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica" color="#FFFFFF">Performance</font></b></td>
147 :     </tr>
148 :     <tr>
149 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
150 :    
151 :     <td WIDTH="98%"><p><b>Time</b> </p>
152 :     <ul>
153 :     <li>Using a message is marginally faster since it is just a field access
154 :     rather than a lookup in the resource bundle.</li>
155 :     <li>Time to load and initialize a bundle is VM dependant but we have seen
156 :     5% to 46% improvements. </li>
157 :     </ul>
158 :     <p>&nbsp;</p>
159 :     </td>
160 :     </tr>
161 :     <tr>
162 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
163 :    
164 :     <td WIDTH="98%"><p><b>Memory Footprint</b> </p>
165 :     <ul>
166 :     <li>This is very much a scalability play. The more you use, the more you
167 :     save.</li>
168 :     <li>The rough space savings is 88 + 4N bytes per message where N is the
169 :     number of characters in the key.</li>
170 :     <li>The absolute best-case scenerio for the Eclipse SDK, if every property
171 :     file is loaded and every key referenced, is roughly 4.5M of memory.
172 :     (based on the January 11, 2005 integration build)</li>
173 :     <li>Realistic scenarios for the Eclipse IDE should see savings on the
174 :     order of 500KB </li>
175 :     </ul>
176 :     <p>&nbsp;</p>
177 :     </td>
178 :     </tr>
179 :     <tr>
180 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
181 :    
182 :     <td WIDTH="98%"><b>Other benefits</b> <ul>
183 :     <li>Easily catch missing keys - Message lookups are now field accesses
184 :     so you cannot reference a key that doesn't exist or you will get a compile
185 :     error. </li>
186 :     <li>Easily find typos in code when referencing keys - Each key is represented
187 :     by a field in the class so if the referencing code makes a spelling
188 :     error, then you will get a compile error.</li>
189 :     <li>Find unused keys - During the development cycle code is deleted, moved
190 :     and messages are changed. As a result there are keys in the messages.properties
191 :     file which are never referenced.These can easily be found now since
192 :     you can just do a search for references to the field. If there are no
193 :     references, then delete the field from the class and the key/value pair
194 :     from the file.</li>
195 :     </ul>
196 :     <p>&nbsp;</p></td>
197 :     </tr>
198 :     <tr>
199 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
200 :    
201 :     <td WIDTH="98%"><b>Drawbacks</b>
202 :     <ul>
203 :     <li>There are now 2 files to maintain - Now the messages.properties and the java file must be kept in sync. There
204 :     is an opportunity for tooling to help with this; a validation tool could indicate problems with markers. Currently
205 :     there are debug options which log entries which exsit in one file but not the other.</li>
206 :     </ul>
207 :     <p>&nbsp;
208 :     </p>
209 :     </td>
210 :     </tr>
211 :    
212 :    
213 :     <tr>
214 : dj 1.1 <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica" color="#FFFFFF">Tools</font></b></td>
215 :     </tr>
216 :     <tr>
217 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
218 :    
219 :     <td WIDTH="98%"><b>Conversion</b> <p>We have written a tool which aids in
220 :     converting from the basic Java resource bundle look-up mechanism, to the
221 : dj 1.2 new format. There is no requirement to do this conversion unless you want
222 :     to take advantage of the new mechanism.</p>
223 : dj 1.1 <p><em>Note that the message bundle access class is replaced when the tool
224 :     is run. If you define extra code, constants, etc in that class then please
225 :     read the notes below to ensure that you don't have problems.</em></p>
226 :     <p>Here are the steps to use when converting your code.</p>
227 :     <ul>
228 :     <li>Download <a href="../../downloads/tools/message_bundles/com.example.nls_1.0.0.zip">version 1.0.0</a>
229 :     and install the plug-in.</li>
230 :     <li>Run Eclipse.</li>
231 :     <li>Synchronize with the repository. (you will be using the Synchronize
232 :     view as your compare browser to view changes)</li>
233 :     <li>Select your message bundle access class. (e.g. the class which has
234 :     the <code>#getString(String)</code> method in it)</li>
235 :     <li>From the context menu, choose &quot;Convert Message Bundle&quot;.</li>
236 :     <li>Choose the class's associated .properties file from the resulting
237 :     &quot;Open Resource...&quot; dialog.</li>
238 :     <li>Use the Synchronize view to review the changes.</li>
239 :     <li>Release the new code.</li>
240 :     </ul>
241 :     <p><strong>Notes:</strong> </p>
242 :     <p>When using the NLS tooling from previous Eclipse releases, the java file
243 :     which was created had the format of the &quot;old&quot; Messages.java
244 :     file as described above. (basic class with <code>#getString(String)</code> method) Some plug-in owners have created extra helper
245 :     methods on the class to aid in their message bundle lookup. Since the
246 :     conversion tool has only basic functionality, these plug-in developers
247 :     must perform a couple of extra steps before running the tool.</p>
248 :     <p>Essentially what you want to do is get your java file into the basic
249 :     template form. This is possible via using existing refactorings. For instance,
250 :     if your class defines a method like this:</p>
251 :     <pre><code>public String getString(String key, Object binding) {
252 :     &nbsp;&nbsp;&nbsp;return MessageFormat.format(getString(key), new Object[] {binding});
253 :     }</code></pre>
254 :     <p>Then you want to do the following:</p>
255 :     <ol>
256 :     <li>Change the method body to be: <code>return NLS.bind(getString(key), binding);</code></li>
257 :     <li>Select the method name and from the context menu choose the &quot;Inline&quot;
258 :     refactoring. This will replace calls to this method in your code with
259 :     calls to the code in step 1.</li>
260 :     <li>Run the tool. Since only calls to <code>#getString(String)</code> exist now,
261 :     the tool will run sucessfully.</li>
262 :     </ol>
263 :     </tr>
264 :     </table>
265 :    
266 :    
267 :     </body>
268 :     </html>