2010-12-01 18 views
10

Tengo paquete de recursos como clase Java que lee valores de la base de datos. Cuando actualizo DB, necesito volver a cargar el paquete, pero no sé cómo. ¿Alguien ayuda?¿Cómo volver a cargar el paquete de recursos en la aplicación web?

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

En vista i uso bundle como a continuación:

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

Respuesta

5
ResourceBundle.clearCache();  

O

Messages_en .clearCache(); 

llama a este método que se recargue los recursos, se actualizará el haz

+1

¿Cómo ayuda esto exactamente? –

+1

Funciona bien. Gracias :) – marioosh

+1

Observo que cuando tengo el paquete de mensajes definido en faces-config.xml en lugar de usar f: loadBundle, la recarga no funciona. ¿Alguien sabe por qué? – marioosh

10

Esto no es exactamente trivial.

Por un solo borrar el ResourceBundle a través de clearCache() no siempre se obtienen los resultados deseados. A menudo se necesitan al menos también tratar de limpiar usando el cargador de clases de contexto:

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

Sin embargo, esto todavía no se vuelva a cargar el paquete de recursos definidos en un archivo faces-config.xml. Al menos, la implementación de Mojarra JSF 1.2 almacena de forma privada el paquete de recursos internamente. Esto sucede en:

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

Es posible borrar esta caché a través de la reflexión (al final del día, es sólo una entrada en un mapa), o Es posible que desee sustituir la aplicación. Ambas cosas no son cosas que normalmente haces alegremente.

Puramente para el desarrollo podrías usar JRebel, que probablemente ya tenga conocimiento de Mojarra y probablemente haga el truco de reflexión mencionado anteriormente.

Después de experimentar, llegué al siguiente código que hace el truco en JBoss AS 5/JSF 1.2. Ata tu código a Mojarra (importa paquetes de sol) y puede romperse con cualquier mejora debido a los trucos reflexivos que se utilizan. Pero de todos modos, este es el código:

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; 
    }  
} 

(reemplazar el método de ayuda GetFieldValue con su propio favorito reflexivo util si es necesario y espolvorear con excepción y nulos los manipuladores en su caso)

+0

hola arjan, me alegro de saber sobre esta teca, jugué, no funcionó para GlassFish solamente, traté de usar el paquete de recursos de nivel de vista y el nivel de aplicación, ambos fallaron al usar este ajuste en GF env –

+0

¿Qué versión de Glassfish? ¿era que? Si es V3 entonces supongo que podría no funcionar, ya que la versión de Mojarra es totalmente diferente. Yo estaba trabajando en un proyecto de JBoss AS 5, así que solo lo probé allí, pero también podría no funcionar en JBoss AS 6. –

+0

su V3, alguna idea de cómo trabajar en V3, y el sistema notificará si usted comienza su comentario con @username –

1

Usted puede incluso evitar que importar clases de soldadura y JSF-impl en su módulo con algunos más líneas de reflexión:

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(); 

(funciona bien con JBoss 10)

+0

Esto funcionó bien para mí en Wildfly 8, lo único que despejó ese estúpido caché ... – VeenarM

Cuestiones relacionadas