More Control over ResourceBundle
June 24, 2005
Did you ever wish you had a little more control over the ResourceBundle
class?
Say, have it instantiate bundles from XML files or from data in a database,
rather than just class and properties files? Or, to the contrary, have it look
only for properties files, because you never use class-based resource bundles?
Or have it reload a bundle with a little fix without having to restart your
web application, which otherwise is on the way towards reaching 99.999% uptime?
Well, you just got that little more control: The ResourceBundle.Control
class
in JDK 6.
The central method in ResourceBundle
has always been getBundle
.
This method looks for resource bundles of predefined types in predefined places
using a predefined search strategy, loaded them in predefined ways, and cached
them in a largely unspecified way.
The idea of the Control
class is to expose every major step of
the bundle loading process as a separate method that can be overridden and
customized. The Control
class itself implements the methods so
that using it directly results in the same behavior as in previous releases.
But applications can subclass it, override as many methods as necessary to
implement the behavior they need, and pass an instance of this subclass to
new getBundle
methods
that accept Control
objects.
For some of the most common cases, you don’t actually need to write your own
subclass: If you just want to use only class-based or only properties-based
resource bundles, or if you want to avoid the fallback to the default locale,
the getControl
and getNoFallbackControl
methods
provide you with ready-made instances.
Here are a few examples for how you can go further (the class description has more):
- To search for bundles according to the list of languages that your web
application received in an Accept-Language HTTP header, override the
getFallbackLocale
method to successively return the locales of the language list. - To load resource bundles from locale-specific directories rather than using
locale-specific suffixes, override the
toBundleName
method to insert the locale ID components into the appropriate places of the bundle name. - To use bundles for Chinese/Taiwan as the parent bundles of Chinese/Hong
Kong bundles in order to share traditional Chinese strings, override
getCandidateLocales
to insert the Chinese/Taiwan locale in the right place. - To ensure that cached bundles are checked against their source files on
disk at least every 6 hours, override
getTimeToLive
to return 21,600,000. (The specification currently says that that’s the default behavior. Unfortunately, this uncovered a bug in a major third-party application that we test with, so in order to avoid incompatibilities, the default behavior will revert toTTL_NO_EXPIRATION_CONTROL
, which reflects behavior in previous releases.)
Some methods need to be overridden together. For example, if you override getFormats
to
return formats other than "java.class"
and "java.properties"
,
you also need to override newBundle
to
load bundles of these formats. If, in addition, you override getTimeToLive
to
enable checking whether a bundle in the cache is still up to date, you may
also need to override needsReload
to
implement the checking.
If, instead of periodically checking whether resource bundles in the cache
are still up to date, you’d rather remove all your application’s bundles from
the cache when installing new bundles, you can use the new ResourceBundle.clearCache
methods.
As always, we’d love to hear from you whether these API additions meet your needs, or what’s wrong with them. Please try them, file bugs, or send us your feedback.