1

I have a enum with some entries for a selectOneMenu, that means the enum stucture looks like this: display, pdfLabel.

I want to load the entries label from my message bundle, that means depending on the locale.

It works fine, but only the first time after I depoly the project. That means, if the locale is "en" first time I load the entries, even after logout - session invalidate; if I change the locale to "de" the entries are still from the "en" - message. It works only if I redeploy.

Anyone has an idea about this behavior?

My enum:

public enum Transportmittel {
     TRUCK(I18n.get("tv.moc.truck"), "TRUCK"), 
     AIRFREIGHT(I18n.get("tv.moc.airfreight"), "AIRFREIGHT"), 
     TRAIN(I18n.get("tv.moc.train"), "TRAIN"), 
     SEAFREIGHT(I18n.get("tv.moc.seafreight"), "SEAFREIGHT"), 
     BARGE(I18n.get("tv.moc.barge"), "BARGE");

String ausgabe;
String pdfLabel;

private Transportmittel(String ausgabe, String pdfLabel) {
    this.ausgabe = ausgabe;
    this.pdfLabel = pdfLabel;
}

public String toString() {
    return ausgabe;
}

public String getLabelForPdf() {
    return pdfLabel;
}

}

The controller where I load the entries:

@PostConstruct
public void init() {
    transportMittelSelectList.add(new SelectItem(Transportmittel.TRUCK.pdfLabel, Transportmittel.TRUCK.ausgabe));
    transportMittelSelectList.add(new SelectItem(Transportmittel.TRAIN.pdfLabel, Transportmittel.TRAIN.ausgabe));
    transportMittelSelectList.add(new SelectItem(Transportmittel.AIRFREIGHT.pdfLabel, Transportmittel.AIRFREIGHT.ausgabe));
    transportMittelSelectList.add(new SelectItem(Transportmittel.SEAFREIGHT.pdfLabel, Transportmittel.SEAFREIGHT.ausgabe));
    transportMittelSelectList.add(new SelectItem(Transportmittel.BARGE.pdfLabel, Transportmittel.BARGE.ausgabe));
}

And this is where I load the message bundle:

public class I18n {

    public static String get(String msg) {
        FacesContext context = FacesContext.getCurrentInstance();
        ResourceBundle bundle = context.getApplication().getResourceBundle(
                                context, "messages");
        return bundle.getString(msg);
    }
}
leostiw
  • 1,125
  • 3
  • 12
  • 28
  • 1
    Can you show us the xml configuration for the i18n? And as well how exactly you switch the locale. – noone Aug 30 '13 at 09:01
  • @noone I could add it, but I'm pretty sure that has nothing to do with my issue, because all of the others values from the message-bundle are loaded accordingly. I think it has to do more with the enum, as the answer belows explains. Thanks anyway for trying to help :) – leostiw Aug 30 '13 at 09:08

3 Answers3

2

The enum-values are static - so their constructor is called only once when loading the class by the classloader (=the first use). So at consecutive uses you still use the same instance containing the same string ausgabe set at construction-time during the first use.

So you have to set the values for ausgabe and pdfLabel when it is used. But maybe it is even better to have some "external" class which knows how to get the different labels for your enum-value instead of having these values somehow hard-coded inside the enum.

MrD
  • 1,255
  • 1
  • 10
  • 24
  • Yes, you are right, enum-values are static, good point. I however tought of this solution: I support anyways only 2 language, so I just added to my enum `ausgabe_de, ausgabe_en` and I load them in my `List` depending on the locale. What's your oppion on that ? – leostiw Aug 30 '13 at 09:31
  • 1
    I think this is not a good idea. What happens if there is another language to support (e.g. the austrian dialect ;) ). As already written, I would introduce another class which gives you the internationalized strings for a specific enum-value. So you simply have to call `EnumLabel.getLabel(enumValue)` and depending on the current locale, the correct label will be returned. To find a corresponding label for an enum-value you can either store a message-key in the enum-value or you can use the enum's name (or FQN) to accomplish this. – MrD Aug 30 '13 at 09:44
1

This is indeed not going to work. Enum properties are initialized only once, applicationwide, while i18n is essentially supposed to be resolved on a per-request basis.

You need to redesign your enum as such that only the label keys are hold instead of the resolved localized values.

TRUCK("tv.moc.truck", "TRUCK"), 
AIRFREIGHT("tv.moc.airfreight", "AIRFREIGHT"), 
TRAIN("tv.moc.train", "TRAIN"), 
SEAFREIGHT("tv.moc.seafreight", "SEAFREIGHT"), 
BARGE("tv.moc.barge", "BARGE");

And then provide the enum values as follows in an application scoped bean:

@ManagedBean
@ApplicationScoped
public class Data {

    public Transportmittel[] getTransportmittels() {
        return Transportmittel.values();
    }

}

And then reference it in <f:selectItems> as follows (look, no need for SelectItem boilerplate):

<f:selectItems value="#{data.transportmittels}" var="transportmittel"
    itemValue="#{transportmittel}" itemLabel="#{bundle[transportmittel.ausgabe]}" />

Or, if you happen to use JSF utility library OmniFaces already, as currently indicated in your user profile, then you could also bypass the whole application scoped Data bean and import it straight in the EL scope as follows:

<o:importConstants type="com.example.Transportmittels" /> <!-- can be declared in a master template -->
...
<f:selectItems value="#{Transportmittels}" var="transportmittel"
    itemValue="#{transportmittel}" itemLabel="#{bundle[transportmittel.ausgabe]}" />

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
0

I had the same problem, but with ZK, I did need to fetch some properties to my enum, but it was blank String everytime.

To solve this you need to pass as the arguments the key of your property file in your enum constructor, like this:

enter image description here

After that in the get method of your enum propertie you must get the values in resource bundle and return them, like this:

enter image description here

EACUAMBA
  • 461
  • 4
  • 8