Pregunta

Tengo un archivo de propiedades para la localización:

foo=Bar
title=Widget Application

Esto está atado como un resource-bundle En las caras-config:

<resource-bundle>
    <base-name>com.example.messages.messages</base-name>
    <var>msgs</var>
</resource-bundle>

Puedo acceder a esto muy bien en la vista de facelets usando El:

<title>#{msgs.title}</title>

Sin embargo, si hay cosas como SQLExcepciones, necesito poder escribir mensajes desde el frijol administrado. Todo esto también funciona:

FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "There was an error saving this widget.", null);
FacesContext.getCurrentInstance().addMessage(null, message);

Aquí está el problema: quiero que esos mensajes provengan del archivo de propiedades para que ellos también puedan cambiarse en función de la ubicación. ¿Existe una manera fácil de acceder al archivo de propiedades usando inyección?

¿Fue útil?

Solución

Hice una pregunta bastante relacionada en Entonces:Cómo inyectar una clase no serializable (como java.util.resourceBundle) con soldadura

Y dentro del foro de costura:http://seamframework.org/community/howtocreateanInjectableSourceBundlewithweld

Para resumir: me di cuenta de un recurso inyectable con 3 productores. Primero necesita un FacescontextProducer. Tomé el de las fuentes Alpha Seam 3.

public class FacesContextProducer {
   @Produces @RequestScoped
   public FacesContext getFacesContext() {
      FacesContext ctx = FacesContext.getCurrentInstance();
      if (ctx == null)
         throw new ContextNotActiveException("FacesContext is not active");
      return ctx;
   }
}

Luego necesita un LocalProDucer, que utiliza el FacescontextProducer. También lo tomé de Seam 3 Alpha.

public class FacesLocaleResolver {
   @Inject
   FacesContext facesContext;

   public boolean isActive() {
      return (facesContext != null) && (facesContext.getCurrentPhaseId() != null);
   }

   @Produces @Faces
   public Locale getLocale() {
      if (facesContext.getViewRoot() != null) 
         return facesContext.getViewRoot().getLocale();
      else
         return facesContext.getApplication().getViewHandler().calculateLocale(facesContext);
   }
}

Ahora tiene todo para crear un ResourceBundleProducer, que puede verse así:

public class ResourceBundleProducer {
  @Inject       
  public Locale locale;

  @Inject       
  public FacesContext facesContext;

  @Produces
  public ResourceBundle getResourceBundle() {
   return ResourceBundle.getBundle("/messages", facesContext.getViewRoot().getLocale() );
  }
}

Ahora puede @Inyect The ResourCebundle en sus frijoles. Preste atención a que debe inyectarse en un atributo transitorio, de lo contrario, obtendrá una excepción quejándose de que ResourceBundle no es serializable.

@Named
public class MyBean {
  @Inject
  private transient ResourceBundle bundle;

  public void testMethod() {
    bundle.getString("SPECIFIC_BUNDLE_KEY");
  }
}

Otros consejos

Es más fácil usar, por ejemplo, el módulo de mensaje de Myfaces codi!

Puedes hacer esto solo con JSF.

Comience definiendo una propiedad administrada en su frijol de respaldo. En la configuración de JSF, puede establecer el valor de la propiedad administrada en una expresión EL que hace referencia a su paquete de recursos.

He hecho algo como lo siguiente usando Tomcat 6. La única advertencia es que no puede acceder a este valor desde el constructor de su bean de respaldo, ya que JSF aún no lo habrá inicializado. Usar @PostConstruct en un método de inicialización si el valor se necesita temprano en el ciclo de vida del bean.

<managed-bean>
  ...
  <managed-property>
    <property-name>messages</property-name>
    <property-class>java.util.ResourceBundle</property-class>
    <value>#{msgs}</value>
  </managed-property>
  ...
</managed-bean>

<application>
  ...
  <resource-bundle>
    <base-name>com.example.messages.messages</base-name>
    <var>msgs</var>
  </resource-bundle>
  ...
</application>

Esto tiene la ventaja de hacer que sus métodos de bean de respaldo dependan menos de la tecnología de presentación, por lo que debería ser más fácil de probar. También desacopla su código de detalles como el nombre dado al paquete.

Algunas pruebas con Mojarra 2.0.4-B09 muestran una pequeña inconsistencia cuando un usuario cambia la sesión local. Expresiones en la página EL usa la nueva ubicación pero el bean de respaldo no se le da la nueva referencia de ResourceBundle. Para que sea consistente, puede usar el valor de la propiedad Bean en las expresiones EL, como usar #{backingBean.messages.greeting} en lugar de #{msgs.greeting}. Luego, la página EL y el frijol de respaldo siempre usarían el lugar que estaba activo cuando comenzó la sesión. Si los usuarios tenido Para cambiar los locales a mitad de sesión y obtener los nuevos mensajes, puede intentar hacer un frijol scoped y dar referencias tanto al paquete de recursos y frijoles de sesión.

Aquí hay un ejemplo sobre cómo hacer esto:http://www.laliluna.de/articles/javaserver-faces-message-resource-bundle-tutorial.html

Quieres echar un vistazo al ResourceBundle.getBundle() parte.

Saludos, Lars

Esta es una vieja pregunta, pero estoy agregando otra forma de hacer esto. Estaba buscando algo más y me encontré con esto. Todos los métodos aquí parecían complicados por algo que no me pareció difícil. Jugando con brillo porque es bonito si me preguntas.

Dado un archivo:

/com/full/package/path/to/messages/errormessages.properties

Dentro del archivo:

SOME_ERROR_STRING=Your App Just Cratered

Creo un método "getBundle ()" ya que me gusta detectar el tiempo de ejecución y agregar un mensaje significativo para que entienda de dónde viene. No es difícil y puede ayudar si obtiene el capricho para que juegue con los archivos de propiedades por alguna razón y no actualice todo correctamente. A veces hago esto privado, ya que a veces es un método de ayuda dentro de una clase (para mí). Esto mantiene el trycle el desorden del código significativo.

El uso de la ruta completa del archivo le permite colocarlo en otro lugar que no sea la ubicación/directorio predeterminado si tiene otras ideas sobre la organización.

public/private ResourceBundle getMessageResourceBundle(){
    String messageBundle = "com.full.package.path.to.messages.errormessages";
    ResourceBundle bundle = null;
    try{
        bundle = ResourceBundle.getBundle(messageBundle);
    }catch(MissingResourceException ex){
        Logger.getLogger(this.getClass().getName()).log(Level.SEVERE,
                    "Unable to find message bundle in XYZ Class", ex);
        throw ex;
    }

}

public void doSomethingWithBundle(){

    ResourceBundle bundle = getMessageResourceBundle();
    String someString = bundle.getString("SOME_ERROR_STRING");
    ...
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top