Question

J'ai un fichier de propriétés pour la localisation:

foo=Bar
title=Widget Application

Ceci est lié comme un resource-bundle Dans les faces-config:

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

Je peux y accéder très bien dans la vue sur les facettes en utilisant EL:

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

Cependant, s'il y a des choses comme Sqlexceptions, je dois être en mesure d'écrire des messages à partir du haricot géré. Tout cela fonctionne également:

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

Voici le problème: je veux que ces messages proviennent du fichier de propriétés afin qu'ils puissent également être modifiés en fonction des paramètres régionaux. Existe-t-il un moyen facile d'accéder au fichier Properties en utilisant l'injection?

Était-ce utile?

La solution

J'ai posé une question assez connexe sur SO:Comment injecter une classe non sérialisable (comme java.util.resourcebundle) avec soudure

Et à l'intérieur du forum de couture:http://seamframework.org/community/howtocreateaninjectableResourceBundlewithweld

Pour résumer: j'ai réalisé une ressource injectable avec 3 producteurs. Vous avez d'abord besoin d'un facesContextProducer. J'ai pris celui des sources 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;
   }
}

Ensuite, vous avez besoin d'un eproducteur local, qui utilise le FACESContextProducer. Je l'ai également pris 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);
   }
}

Maintenant, vous avez tout pour créer un ResourceBundleProducer, qui peut ressembler à ceci:

public class ResourceBundleProducer {
  @Inject       
  public Locale locale;

  @Inject       
  public FacesContext facesContext;

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

Vous pouvez maintenant @inject the ResourceBundle dans vos haricots. Faites attention qu'il faut être injecté dans un attribut transitoire, sinon vous obtiendrez une exception se plaignant que ResourceBundle n'est pas sérialisable.

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

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

Autres conseils

Il est plus facile d'utiliser, par exemple le module de message de Myfaces codi!

Vous pouvez le faire avec JSF seul.

Commencez par définir une propriété gérée sur votre haricot de support. Dans la configuration JSF, vous pouvez définir la valeur de la propriété gérée sur une expression EL qui fait référence à votre bundle de ressources.

J'ai fait quelque chose comme ce qui suit en utilisant Tomcat 6. La seule mise en garde est que vous ne pouvez pas accéder à cette valeur à partir du constructeur de votre bean de soutien, car JSF ne l'a pas encore initialisé. Utilisation @PostConstruct sur une méthode d'initialisation si la valeur est nécessaire au début du cycle de vie du 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>

Cela a l'avantage de rendre vos méthodes de soutenance moins dépendantes de la technologie de présentation, il devrait donc être plus facile à tester. Il découple également votre code à partir de détails comme le nom donné au bundle.

Certains tests utilisant Mojarra 2.0.4-B09 montrent une petite incohérence lorsqu'un utilisateur modifie les paramètres régionaux. Les expressions EL en page utilisent les nouveaux paramètres régionaux, mais le bean de support n'a pas la nouvelle référence ResourceBundle. Pour le rendre cohérent, vous pouvez utiliser la valeur de la propriété Bean dans les expressions EL, comme l'utilisation #{backingBean.messages.greeting} au lieu de #{msgs.greeting}. Ensuite, Page El et le haricot de support utilisaient toujours le lieu qui était actif au début de la session. Si les utilisateurs avais Pour changer de lieux à mi-parcours et obtenir les nouveaux messages, vous pouvez essayer de fabriquer un bean à la demande de demande et de lui faire référence à la fois au bundle de bean de session et de ressources.

Voici un exemple sur la façon de procéder:http://www.laliluna.de/articles/javaserver-faces-message-resource-bundle-tutorial.html

Vous voulez jeter un œil au ResourceBundle.getBundle() partie.

Salutations, Lars

C'est une vieille question, mais j'ajoute une autre façon de le faire. Je cherchais autre chose et j'ai traversé ça. Les méthodes ici semblaient toutes alambiquées pour quelque chose qui ne me frappe pas comme si difficile. Jouer avec des paillettes parce que c'est joli si vous me demandez.

Étant donné un fichier:

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

À l'intérieur du fichier:

SOME_ERROR_STRING=Your App Just Cratered

Je crée une méthode "getBundle ()" car j'aime prendre le temps d'exécution et ajouter un message significatif afin que je comprenne d'où il vient. Pas dur et vous pouvez aider si vous obtenez le caprice de lire avec les fichiers Propriétés pour une raison quelconque et ne mettez pas tout mettre à jour correctement. Je fais parfois ce privé car il s'agit parfois d'une méthode d'assistance au sein d'une classe (pour moi). Cela maintient l'encombrement d'essai sur le code significatif.

L'utilisation du chemin complet vers le fichier vous permet de le placer ailleurs que l'emplacement / répertoire par défaut si vous avez d'autres idées sur l'organisation.

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");
    ...
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top