2010-12-01 28 views
10

J'ai un regroupement de ressources en tant que classe Java qui lit les valeurs de la base de données. Quand je mets à jour la DB je dois recharger le paquet, mais je ne sais pas comment. Quelqu'un aide-t-il?Comment recharger un ensemble de ressources dans une application Web?

package model.helpers; 
public class Messages_en extends ListResourceBundle { 
     protected Object[][] getContents() { 
      // from DB 
      // ... 
     } 
} 

En vue j'utiliser bundle comme ci-dessous:

<f:loadBundle basename="model.helpers.Messages" var="m" /> 

Répondre

5
ResourceBundle.clearCache();  

OU

Messages_en .clearCache(); 

appel à cette méthode rechargera les ressources, il mettra à jour le faisceau

+1

Comment cela aide-t-il exactement? –

+1

Fonctionne bien. Merci :) – marioosh

+1

Je remarque que lorsque j'ai un paquet de messages défini dans faces-config.xml au lieu d'utiliser f: loadBundle - le rechargement ne fonctionne pas. Quelqu'un sait pourquoi? – marioosh

10

Ceci n'est pas exactement trivial.

Pour un effacement juste le ResourceBundle via clearCache() ne donne pas toujours les résultats souhaités. Souvent, vous avez besoin au moins aussi effacer en utilisant le chargeur de classe de contexte:

ResourceBundle.clearCache(Thread.currentThread().getContextClassLoader());

Cependant, cela rechargera pas encore le regroupement de ressources définies dans un fichier faces-config.xml. Au moins l'implémentation Mojarra JSF 1.2 met en cache le bundle de ressources en interne. Cela se produit dans:

FacesContext -> Application -> associate (ApplicationAssociate) -> resourceBundles (Map<String, ApplicationResourceBundle>()) -> resources (Map<Locale, ResourceBundle>) 

Il est possible d'effacer cette mémoire cache par réflexion (à la fin de la journée, il est juste une entrée dans une carte), ou vous voudrez peut-être remplacer l'application. Les deux ne sont pas des choses que vous faites normalement avec légèreté. Juste pour le développement, vous pouvez utiliser JRebel, qui a probablement déjà la connaissance de Mojarra et probablement le truc de réflexion mentionné ci-dessus. Après quelques expériences, je suis arrivé au code suivant qui fait l'affaire sur JBoss AS 5/JSF 1.2. Il lie votre code à Mojarra (importe des paquets solaires) et peut rompre avec n'importe quelle mise à niveau en raison des astuces réfléchissantes utilisées. Mais de toute façon, c'est le code:

public static void reloadBundle() { 

    ResourceBundle.clearCache(Thread.currentThread().getContextClassLoader()); 

    ApplicationResourceBundle appBundle = ApplicationAssociate.getCurrentInstance().getResourceBundles().get("your_bundle_name");    
    Map<Locale, ResourceBundle> resources = getFieldValue(appBundle, "resources");   
    resources.clear(); 
} 

@SuppressWarnings("unchecked") 
private static <T> T getFieldValue(Object object, String fieldName) { 
    try { 
     Field field = object.getClass().getDeclaredField(fieldName); 
     field.setAccessible(true); 
     return (T) field.get(object); 
    } catch (Exception e) { 
     return null; 
    }  
} 

(remplacer la méthode d'aide getFieldValue avec votre propre favori réfléchissant util si nécessaire et saupoudrer de gestionnaires d'exception et null le cas échéant)

+0

Salut Arjan, heureux de savoir sur ce teck, j'ai joué, n'a pas travaillé pour moi seulement pour GlassFish, j'ai essayé d'utiliser à la fois niveau de ressources et niveau d'application, les deux ont échoué en utilisant ce tweak dans GF env –

+0

Quelle version de Glassfish qui était? Si c'est V3 alors je suppose que ça ne marchera pas puisque la version de Mojarra est totalement différente. Je travaillais sur un projet JBoss AS 5 donc je l'ai seulement testé ici, mais il pourrait aussi ne pas fonctionner sur JBoss AS 6. –

+0

son V3, aucune idée de comment faire fonctionner en V3, et le système vous avertira si vous commencez votre commentaire avec @nomd'utilisateur –

1

Vous pouvez même éviter de doivent importer de soudure et des classes-jsf impl dans votre module avec quelques autres lignes de réflexion:

Class<?> applicationAssociateClass = Class.forName("com.sun.faces.application.ApplicationAssociate"); 
Method getCurrentInstance = applicationAssociateClass.getMethod("getCurrentInstance"); 
Object applicationAssociate = getCurrentInstance.invoke(null); 
Method getResourceBundles = applicationAssociate.getClass().getMethod("getResourceBundles"); 
Map<String, ?> resourceBundles = (Map<String, ?>)getResourceBundles.invoke(applicationAssociate); 
Object appBundle = resourceBundles.get(name); 
Map<Locale, ResourceBundle> resources = getFieldValue(appBundle, "resources"); 
resources.clear(); 

(fonctionne bien avec wildfly 10)

+0

Cela a bien fonctionné pour moi dans Wildfly 8, seule chose qui a effacé cette cache stupide ... – VeenarM