JDK-4212439 : (rb) No way to reload a ResourceBundle for a long-running process
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.util:i18n
  • Affected Version: 6
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 1999-02-17
  • Updated: 2005-05-23
  • Resolved: 2005-05-23
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6
6 b38Fixed
Related Reports
Duplicate :  
Relates :  
Description

Name: gsC80088			Date: 02/17/99


For long-running processes (24x7, for instance), it would be nice
if ResourceBundles were "reloadable", even if it were just
PropertyResourceBundle.  I've been researching how I could write
a subclass of ResourceBundle that could provide this functionality,
but the two things I need to get control over are not accessible
from subclasses of ResourceBundle.

First, there is no way to remove the entry from the "cacheList".
If I could remove the entry from that, then the next call to
"getBundle" for that resource file would reload the bundle (I
think).

Second, if I can't zero the cache entry, I could concievably
implement a "wrapper" that just used "Properties.load(String)",
but the ResourceBundle doesn't allow me to know the name of the
actual ".properties" file that was found.

What I'm left with is basically writing a class like
ResourceBundle, much simpler in some respects, but missing a lot
of the functionality I get with ResourceBundle.  This may not be
worth the trouble.

I would appreciate anything that would help me get closer to what
I need.
(Review ID: 53808)
======================================================================

Comments
EVALUATION Bug 4250226 suggests checking the file modification date before returning a resource bundle from the cache. norbert.lindenberg@Eng 1999-06-28 Will investigate this fix. john.oconner@Eng 2000-02-18 I contacted developers who had submitted, voted for, or commented on this RFE to get details about their requirements, and in which situations these would be necessary. I mentioned a possible fix, a new method ResourceBundle.flushCache that flushes the cache used by getBundle. The effect would be that later calls to getBundle find newly installed resource bundles, and will reload modified properties resource bundles. However, later calls to getBundle will usually not reload modified class-based resource bundles (because they're also cached by the class loader), and bundles previously returned by getBundle will not be affected. Replies: ###@###.###: > My requirements are reasonably simple, and only actually need to be > applicable to PropertyResourceBundle, although it would clearly be > cleaner if all ResourceBundles could be reloaded. > > [The proposed method] would be fine - but wouldn't give much granularity. It would > be much nicer to be able to reload a *specific* resource bundle, > as I'll potentially have thousands of resource bundles on the system. > (They're being used for internationalisation *and* customisation > within a servlet, so different companies using the same ASP may want > different text, etc.) > > I don't know the details of PropertyResourceBundle, but could you put an > actual reload method in that? > > Alternatively, could getBundle take an optional boolean "reload" flag > that forced new loading as far as possible? (That could involve creating > a new ClassLoader for class-based resource bundles, or just flushing the > cache for the specific PropertyResourceBundle.) ###@###.###: > The method ResourceBundle.flushCache as you describe it is all I need. ###@###.###: > I think that reloading is a general problem in Java. We had many problems > loading different images from one file, where the file changes over the time. > (Consumer-Producer). Especially we use resource bundles as configuration files > for our application (www.fujaba.de). For example, (popup) menus are loaded > dynamically and can be reconfigured during runtime. We currently fixed the > reload problem by reimplementing the resource bundle classes, means copying > the source code and changing it appropriately. We use checksums, date and time > of the file, and hash values to identify a changed resource bundle, whereas > each getBundle call checks if the file has been changed. ###@###.###: > Your proposed solution would resolve my issues with ResourceBundle. > However, I'm curious why the ResourceBundle was not built with this > capability in the first place? I can understand that the internal caching > provides performance improvements, but if a developer is foolish enough to > flush the cache then they should be willing to accept any related > performance degredation. ###@###.###: > My needs are actually quite simple, I believe. Basically, I program web > applications (using the Tomcat server, of course, plus the Jakarta Velocity > templates engine). The ideal for me would be the ability to specify somehow > whether or not this ResourceBundle should be reloaded, and how often. > Perhaps this could be a static set of properties which apply to all > ResourceBundles. > > Essentially, both Tomcat and Velocity check for changed classes/templates on > disk and reload them as necessary. In the case of Velocity, the > configuration file lets you specify a) whether or not to reload templates b) > how often to check for new templates. > > Generally, I would like, for example, to be able to tell a ResourceBundle to > check for a new copy of itself on disk every 60 seconds or so. No need to > check every time I use it, but by defining a period of time to "cache" the > xxx.properties file contents would be the ideal. > > I don't generally care about bundles already returned by getBundle, because > I call getBundle every time I need to use it (per request), because this > makes Internationalization very easy for me. I don't generally hang on to a > Bundle after the request is complete. > > The reason I mentioned that it could be a static set of properties, is > because the ideal would be to have this set at initialization time, and not > have to worry about it later. By setting the ResourceBundle.reloadable and > ResourceBundle.cacheExpiry (for example) at startup, everything I do will be > affected by this change, and none of my existing code will need to be modified. > > Again, these are long-running applications (since they would be on > production web servers), typically I would go for several weeks before I > update the source code from our staging server. If there's minor problems > with ResourceBundles (spelling errors and the like, or missing translations) > I wouldn't mind being able to fix them on the fly. ###@###.###: > [...] We/I generally mis-use ResourceBundles to handle > configuration parameters as well as any "localization" information (in our > case, usually only English message text). A periodic reload of a "changed" > properties file would probably suffice for our applications. > > Ideally, I think ResourceBundles/Properties/Preferences would work > similarly to a "hot load" of new class files or jsps in some J2EE > Application servers. > I also understand that adding such behavior would have an impact on other > uses of Java, so putting in a mechanism that allows an app developer or a > container provider to implement a "hot load" would be sufficient. > > So, if I understand your proposal correctly, to get a "refreshed" resource > bundle one would have to: > > * use text properties files as opposed to a compiled properties class > * execute the "flush" method to clear the cache (I might call it "clear" as > opposed to "flush" - flush implies a write-back to me). > * On subsequent requests for a property from that ResourceBundle, the cache > query would miss, and the property file would be reloaded. > > I think that would meet the minimum requirements. > > Another approach might be to have a property of the ResourceBundle that > would indicate that a check for changes should be made prior to returning a > value. Default behavior would remain the same. If this property were set, > then on each access the cache would be queried, and the property file > modification time would be compared with the cache. If the file is newer > than the cache, reload it. > > This still ignores the "class" representation of a ResourceBundle, but one > would think that anyone using a class for these values is not expecting > changes very often. ###@###.###: > [...] I believe > your thinking of adding ResourceBundle.flushCache addresses my issue > with the current implementation. ###@###.###: > Your suggestion is good altough I would call the method Reload instead. Also > it would be great if the bundle could reload itself if the file has changed. > This could be done through a property of the Bundle object. You would set > this property if you want the overhead of checking the file change. ###@###.###: > Here is a description of what we are doing with class loaders and how we > would like that reflected for resource bundles: > > We have a system where there is a platform that can be distributed across a > network and our customers can write Java components and dynamically add them > to the system. The component JAR that they put together contains the Java > classes and resource bundles containing text that will be displayed to the > user so that the system can be internationalised into other languages. The > JAR file is installed onto the central server and when a user wants to > access that component on a remote machine the classes and resources are > loaded over the network. In addition, these components are versioned and > users can upgrade components to a newer version. What happens then is that > any existing users will continue to use the original version and the new one > will gradually replace that over time. This is done using different class > loaders. The problem we have at the moment is that the new classes are > loaded but the resource bundle stays the same so the old text is still > displayed and any new items are not loaded at all. > > What we would like is to be able to treat resource bundles just like classes > and be able to load, unload and re-load specific bundles as required. ###@###.###: > I don't think [the proposed method] is sufficient because the usage of a cache at all > should be transparent. Furthermore the cache (might) use a lot of memory for > resource bundles not used anymore. Using soft references for the cache would > be much nicer. I have just implemented a cache class using softreferences. I > took a lot of care to help keeping the cache consistent. I (hopefully) can > send you the source code. > Checking the size and the date of the resource bundle should be an > appropriate solution. This might make a special class loader necessary. > > If you just implement the ResourceBundle.flushCache method many people will > just end in calling this method every time they get a resource bundle. This > would degrade performance serverely and make the whole cache unnecessary. > > Class-based resource bundles would be a different matter of course. In response to a query to the TRC, I also got the following reply from ###@###.###: > Are you attempting to > > (a) provide a new feature in the ResourceBundle mechanism to allow new > resource bundles to be loaded? > > or > > (b) define a strategy which a customer should use to allow resources to > be updated? > > I suggest that you stay away from (a) entirely. Consider this to be a > small part of a much larger problem: How can an application be upgraded > without shutting it down? > > One of the problems with (a) is that unless the different versions of > the properties/classes are in different locations, there is no way to > (automatically) prevent race conditions. What happens if a property > file or class gets is partly overwritten when the app needs it (and > neither the old version nor the new version is available)? > > There are several schemes for doing this kind of thing involving class > loaders, but the key is that the application must be designed to > accomplish it, and must have a mechanism for synchronizing the updates > with its environment. > > A strategy for (b) would be something like this: > > + Define a sequence of jar files containing the replaceable property (or > class) components: version1.jar, version2.jar, version3.jar, ... > > + Create a simple interface for access resources in the jar file. > > public Interface VersionedLoader { > public ResourceBundle getBundle(String baseName, Locale locale); > } > > + Let each of the jar files have a class with a method for fetching the > bundle. > > public VersionedJarLoader implements VersionedLoader { > public ResourceBundle getBundle(String baseName, Locale locale) { > return ResourceBundle.getBundle(baseName, locale); > } > } > > + Let the user load whatever version of resources he wants: > > ClassLoader classLoader = new URLClassLoader(".../version1.jar"); > VersionedLoader loader = > (VersionedLoader) classLoader.loadClass("VersionedJarLoader) > .newInstance(); > bundle = loader.getBundle(baseName, locale); > > This has the advantage the that the user is responsible for maintaining > the versioning. The user must isolate the dynamic resources from the > static resources (to prevent corruption). The user is responsible for > any race conditions in his environment. The user decides when to update > the "loader" variable. Etc. ###@###.### 2002-01-16 Introduced new methods clearCache() and clearCache(ClassLoader) in ResourceBundle to clear the cached bundles. In addition, introduced new nested class ResourceBundle.Control to be able to specify how long cached bundles can stay in the cache. ###@###.### 2005-05-17 02:47:32 GMT
17-05-2005

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mustang
01-10-2004