Domanda

Ho un file di proprietà per la localizzazione:

foo=Bar
title=Widget Application

Questo è legato come a resource-bundle In The Faces-Config:

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

Posso accedervi bene nella vista di facciale usando EL:

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

Tuttavia, se ci sono cose come SQlexceptions, devo essere in grado di scrivere messaggi dal fagiolo gestito. Tutto questo funziona anche:

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

Ecco il problema: voglio che quei messaggi provengano dal file delle proprietà in modo che anche loro possano essere modificati in base al locale. Esiste un modo semplice per accedere al file delle proprietà utilizzando l'iniezione?

È stato utile?

Soluzione

Ho fatto una domanda abbastanza correlata su SO:Come iniettare una classe non serializzabile (come java.util.resourcebundle) con saldatura

E all'interno del forum di cucitura:http://seamframework.org/community/howtocreateaninjectablesourcebundleweld

Riassumendo: ho realizzato un ramo di risorse iniettabili con 3 produttori. Per prima cosa hai bisogno di un FACESContextProducer. Ho preso quello dalle fonti di cucitura 3 alfa.

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

Quindi hai bisogno di un LocaleProducer, che utilizza FaceSContextProducer. L'ho preso anche da SEAM 3 alfa.

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

Ora hai tutto per creare un prodotto di risorsa che può apparire così:

public class ResourceBundleProducer {
  @Inject       
  public Locale locale;

  @Inject       
  public FacesContext facesContext;

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

Ora puoi @Inject the ResourceBundle nei tuoi fagioli. Presta attenzione al fatto che deve essere iniettato in un attributo transitorio, altrimenti otterrai un'eccezione che si lamenta del fatto che le risorse non sono serializzabili.

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

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

Altri suggerimenti

È più facile usare ad esempio il modulo di messaggio di Myfaces codi!

Puoi farlo con JSF da solo.

Inizia definendo una proprietà gestita sul bean di supporto. Nella configurazione JSF, è possibile impostare il valore della proprietà gestita su un'espressione EL che fa riferimento al tuo pacchetto di risorse.

Ho fatto qualcosa come il seguente usando Tomcat 6. L'unico avvertimento è che non puoi accedere a questo valore dal costruttore del tuo fagiolo di supporto, poiché JSF non lo avrà ancora inizializzato. Uso @PostConstruct su un metodo di inizializzazione se il valore è necessario all'inizio del ciclo di vita del fagiolo.

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

Ciò ha il vantaggio di rendere i metodi di backing Bean meno dipendenti dalla tecnologia di presentazione, quindi dovrebbe essere più facile testare. Dicotterisce anche il tuo codice da dettagli come il nome dato al pacchetto.

Alcuni test tramite Mojarra 2.0.4-B09 mostrano una piccola incoerenza quando un utente cambia a metà sessione. Le espressioni El in pagina usano il nuovo locale ma al backing bean non viene dato il nuovo riferimento di risorse. Per renderlo coerente è possibile utilizzare il valore della proprietà del bean nelle espressioni EL, come l'uso #{backingBean.messages.greeting} al posto di #{msgs.greeting}. Quindi Page El e il fagiolo di supporto usavano sempre il locale che era attivo all'inizio della sessione. Se utenti avevo Per cambiare la sessione centrale delle località e ottenere i nuovi messaggi, è possibile provare a fare un fagiolo scavato e dargli riferimenti sia al fagiolo di sessione che al pacchetto di risorse.

Ecco un esempio su come farlo:http://www.laliluna.de/articles/javaserver-faces-message-resource-bundle-tutorial.html

Vuoi dare un'occhiata al ResourceBundle.getBundle() parte.

Saluti, Lars

Questa è una vecchia domanda ma sto aggiungendo un altro modo per farlo. Stavo cercando qualcos'altro e mi sono imbattuto in questo. I metodi qui sembravano tutti contorti per qualcosa che non mi colpisce come tutto così difficile. Giocare con glitter perché è carino se me lo chiedi.

Dato un file:

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

All'interno del file:

SOME_ERROR_STRING=Your App Just Cratered

Creo un metodo "getBundle ()" poiché mi piace catturare il runtime e aggiungere un messaggio significativo in modo da capire da dove viene. Non è difficile e può aiutare se si ottiene il capriccio da giocare con i file delle proprietà per qualche motivo e non aggiornare tutto correttamente. A volte lo rendo privato in quanto a volte è un metodo di supporto all'interno di una classe (per me). Questo mantiene il tentativo di cattura fuori dal codice significativo.

L'uso del percorso completo del file consente di metterlo in un posto diverso dalla posizione/directory predefinita se si dispone di altre idee sull'organizzazione.

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");
    ...
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top