Lokalizacja JSF 2 (managed bean)

Mam Plik Właściwości dla lokalizacji:

foo=Bar
title=Widget Application

Jest to związane jako resource-bundle w faces-config:

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

Mogę uzyskać dostęp do tego po prostu dobrze w widoku facelets za pomocą EL:

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

Jednakże, jeśli są takie rzeczy jak SQLExceptions, muszę być w stanie pisać wiadomości z zarządzanej fasoli. To wszystko działa również:

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

Oto problem: chcę, aby te wiadomości pochodzą z pliku properties, aby również mogły być zmieniane na podstawie miejsce. Czy istnieje łatwy sposób uzyskania dostępu do pliku właściwości za pomocą injection?

Author: Zack Marrapese, 2010-08-13

5 answers

Zadałem dość podobne pytanie na SO: jak wstrzyknąć nie serializowalną klasę (jak java.util.ResourceBundle) ze spoiną

I wewnątrz Forum Seam: http://seamframework.org/Community/HowToCreateAnInjectableResourcebundleWithWeld

Podsumowując: Zrealizowałem zastrzyki z 3 producentami. Najpierw potrzebujesz Facescontextproducent. Wziąłem ten ze źródeł Seam 3 Alpha.

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

Następnie potrzebujesz lokalnego producenta, który używa Facescontextproducent. Wziąłem go również z 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);
   }
}

Teraz masz wszystko, aby stworzyć Resourcebundleproducent, który może wyglądać tak:

public class ResourceBundleProducer {
  @Inject       
  public Locale locale;

  @Inject       
  public FacesContext facesContext;

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

Teraz możesz @ wstrzyknąć ResourceBundle do swojej fasoli. Zwróć uwagę, że musi zostać wstrzyknięty do atrybutu transient, w przeciwnym razie dostaniesz wyjątek narzekający, że ResourceBundle nie jest serializowalny.

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

  public void testMethod() {
    bundle.getString("SPECIFIC_BUNDLE_KEY");
  }
}
 16
Author: ifischer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:02

Łatwiej jest używać np. modułu komunikatów MyFaces CODI !

 2
Author: Peter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-24 15:41:29

Możesz to zrobić tylko z JSF.

Zacznij od zdefiniowania zarządzanej nieruchomości na Twoim zapleczu. W konfiguracji JSF można ustawić wartość właściwości managed na wyrażenie EL, które odwołuje się do pakietu zasobów.

Zrobiłem coś takiego jak poniżej używając Tomcat 6. Jedynym zastrzeżeniem jest to, że nie możesz uzyskać dostępu do tej wartości z konstruktora backing bean, ponieważ JSF jeszcze go nie zainicjalizuje. Użyj @PostConstruct w metodzie inicjalizacji, jeśli potrzebna jest wartość na początku cyklu życia fasoli.

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

Ma to tę zaletę, że Twoje metody tworzenia kopii zapasowych są mniej zależne od technologii prezentacji, więc powinno być łatwiejsze do przetestowania. Oddziela również Kod od szczegółów, takich jak nazwa nadana pakietowi.

Niektóre testy przy użyciu Mojarra 2.0.4-b09 wykazują małą niespójność, gdy użytkownik zmienia ustawienia regionalne w połowie sesji. Wyrażenia na stronie el używają nowych locale, ale fasola zaplecza nie otrzymuje nowego odniesienia do ResourceBundle. Na aby była spójna można użyć wartości właściwości bean w wyrażeniach EL, takich jak użycie #{backingBean.messages.greeting} zamiast #{msgs.greeting}. Następnie page EL i backing bean zawsze używali ustawień regionalnych, które były aktywne w momencie rozpoczęcia sesji. Jeśli użytkownicy mieli , aby przełączyć lokalizacje w połowie sesji i uzyskać nowe wiadomości, możesz spróbować zrobić request-scoped bean i nadać mu odwołania do zarówno sesji bean, jak i pakietu zasobów.

 2
Author: GargantuChet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-10 23:19:23

Oto przykład jak to zrobić: http://www.laliluna.de/articles/javaserver-faces-message-resource-bundle-tutorial.html

Chcesz rzucić okiem na ResourceBundle.getBundle() część.

Pozdrawiam, Lars

 0
Author: Lars,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-13 15:07:58

To stare pytanie, ale dodaję inny sposób. Szukałam czegoś innego i natknęłam się na to. Metody tutaj wszystko wydawało się zawiłe dla czegoś, co nie wydaje mi się tak trudne. Bawię się brokatem, bo jest ładny.

Podany PLIK:

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

Wewnątrz pliku:

SOME_ERROR_STRING=Your App Just Cratered

Tworzę metodę" getBundle ()", ponieważ lubię przechwytywać runtime i dodawać sensowną wiadomość, więc zrozumiem, gdzie nadchodzi od. Nie jest trudne i może pomóc, jeśli z jakiegoś powodu masz kaprys, aby grać z plikami właściwości i nie aktualizować wszystkiego poprawnie. Czasami robię to prywatnie, ponieważ czasami jest to metoda pomocnicza w ramach klasy (dla mnie). Dzięki temu problem try catch nie jest widoczny w znaczącym kodzie.

Użycie pełnej ścieżki do pliku pozwala umieścić go w innym miejscu niż domyślna lokalizacja / katalog, jeśli masz inne pomysły na organizację.

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");
    ...
}
 0
Author: Bill Rosmus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-05 08:06:27