2012-03-22 5 views
4

Il s'agit d'une application Web s'exécutant sur Tomcat, à l'aide de Guice. Selon les documents, nous devrions être en mesure d'appeler ResourceBundle.clearCache(); pour effacer le cache ResourceBundle et probablement obtenir les dernières informations à partir des fichiers de propriétés du bundle.Comment effacer le cache ResourceBundle

Nous avons également essayé ce qui suit:

Class klass = ResourceBundle.getBundle("my.bundle").getClass().getSuperclass(); 
Field field = klass.getDeclaredField("cacheList"); 
field.setAccessible(true); 
ConcurrentHashMap cache = (ConcurrentHashMap) field.get(null); 
cache.clear(); // If i debug here I can see the cache is now empty! 

et

ResourceBundle.clearCache(this.class.getClassLoader()); 

Le comportement que je me attends est:

  1. Démarrez tomcat et appuyez sur une page et il dit 'Hello World'
  2. Modifier le fichier de propriétés contenant 'Hello » To 'Au revoir la Terre'
  3. Vider le cache en utilisant un servlet
  4. Hit la page et attendent de voir 'Adieu la Terre'

Alors question est, comment ResourceBundle.clearCache() fonctionne réellement? Et y a-t-il un cache de fichiers génériques que nous devons effacer également?

+0

avez-vous trouvé des solutions à cela? – prongs

+0

ResourceBundle.clearCache() est ajouté à Java 1.6. Je travaillais sur un serveur Java 1.4 et c'était la raison pour laquelle clearCache() ne fonctionnait pas comme prévu. – Devrim

Répondre

4

Je ne crois pas que vous pouvez effectuer le rechargement d'une instance ResourceBundle déjà créée puisque sa classe de contrôle interne a déjà été créée. Vous pouvez essayer cela comme une alternative pour initialiser votre paquet:

ResourceBundle.getBundle("my.bundle", new ResourceBundle.Control() { 
    @Override 
    public long getTimeToLive(String arg0, Locale arg1) { 
     return TTL_DONT_CACHE; 
    } 
}); 
+0

Même si cette solution consiste à désactiver la mise en cache tous ensemble, je l'ai essayé et cela n'a toujours pas fonctionné. Mon sentiment est Tomcat est la mise en cache des fichiers de propriétés? Agaçant .... –

+0

Cela pourrait très bien être le cas. Laissez-moi penser à un autre moyen de contourner cela. – Perception

+0

@Perception: avez-vous trouvé une solution? – prongs

1

J'ai trouvé cette solution (fonctionne avec tomcat):

  • utiliser un ResourceBundle.Control personnalisé (parce que je dois UTF8)
  • ajouter la getTimeToLive comme description "Perception"
  • force le reload drapeau
  • le "ResourceBundle.clearCache" ne fonctionne pas

Comment appeler:

ResourceBundle bundle = ResourceBundle.getBundle("yourfile", new UTF8Control()); 

La classe personnalisée:

public class UTF8Control extends Control 
{ 
    public ResourceBundle newBundle(
     String baseName, 
     Locale locale, 
     String format, 
     ClassLoader loader, 
     boolean reload) 
    throws IllegalAccessException, InstantiationException, IOException 
    { 
     // The below is a copy of the default implementation. 
     String bundleName = toBundleName(baseName, locale); 
     String resourceName = toResourceName(bundleName, "properties"); 
     ResourceBundle bundle = null; 
     InputStream stream = null; 

     // FORCE RELOAD because needsReload doesn't work and reload is always false 
     reload = true; 

     if (reload) { 
      URL url = loader.getResource(resourceName); 
      if (url != null) { 
       URLConnection connection = url.openConnection(); 
       if (connection != null) { 
        connection.setUseCaches(false); 
        stream = connection.getInputStream(); 
       } 
      } 
     } 
     else { 
      stream = loader.getResourceAsStream(resourceName); 
     } 

     if (stream != null) { 
      try { 
       // Only this line is changed to make it to read properties files as UTF-8. 
       bundle = new PropertyResourceBundle(new InputStreamReader(stream, "UTF-8")); 
      } 
      finally { 
       stream.close(); 
      } 
     } 
     return bundle; 
    } 

    // ASK NOT TO CACHE 
    public long getTimeToLive(String arg0, Locale arg1) { 
     return TTL_DONT_CACHE; 
    } 
} 
+0

J'aime cette approche. J'ai combiné avec un cache de ressources ConcurrentHashMap regroupant un observateur de fichier qui supprime un ensemble lors du changement de fichier. Le moteur de gabarit de Pebble implémente sa propre copie ci-dessus, donc j'ai dû la surcharger. –

0
this is one more possibility to clear cache 
Class<ResourceBundle> type = ResourceBundle.class; 
     try { 
      Field cacheList = type.getDeclaredField("cacheList"); 
      cacheList.setAccessible(true); 

      ((Map<?, ?>) cacheList.get(ResourceBundle.class)).clear(); 
     } 
     catch (Exception e) { 

      system.out.print("Failed to clear ResourceBundle cache" + e); 
     } 
5

Cela a fonctionné pour moi:

ResourceBundle.clearCache(); 
ResourceBundle resourceBundle= ResourceBundle.getBundle("YourBundlePropertiesFile"); 
String value = resourceBundle.getString("your_resource_bundle_key"); 

Notes:

  1. ResourceBundle.clearCache() est ajouté à Java 1.6
  2. Ne pas utiliser une propriété resourceBundle statique, utilisez la méthode ResourceBundle.getBundle() après l'appel clearCache() méthode .
0

Cela fonctionne, vous pouvez intercepter ssi la première création du groupe de ressources:

while (true) { 
    ResourceBundle resourceBundle = ResourceBundle.getBundle("SystemMessages", new Locale("hu", "HU"), 
      new ResourceBundle.Control() { 
       @Override 
       public List<String> getFormats(String baseName) { 
        return ResourceBundle.Control.FORMAT_PROPERTIES; 
       } 

       @Override 
       public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException { 
        System.err.println(this.toBundleName(baseName, locale) + ": " + format + " - " + reload); 
        return super.newBundle(baseName, locale, format, loader, reload); 
       } 

       @Override 
       public long getTimeToLive(String baseName, Locale locale) { 
        long ttl = 1000; 
        System.err.println(this.toBundleName(baseName, locale) + " - " + ttl + "ms"); 
        return ttl; 
       } 

       @Override 
       public boolean needsReload(String baseName, Locale locale, String format, ClassLoader loader, ResourceBundle bundle, long loadTime) { 
        System.err.println(baseName + "_" + locale + " - " + new Date(loadTime)); 
        return true; 
       } 
      }); 
    System.out.println(resourceBundle.getString("display.first_name") + ": John"); 
    System.out.println(resourceBundle.getString("display.last_name") + ": Doe"); 
    Thread.sleep(5000); 
} 
+0

Ou utilisez simplement ReloadableResourceBundleMessageSource du printemps, si possible. – gabor